Skip to content

Commit 5c886e6

Browse files
authored
Dialogue Manager: Update to v3.10.2 (#2052)
Resolves #1825
1 parent 1234d0a commit 5c886e6

47 files changed

Lines changed: 2622 additions & 1359 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

addons/dialogue_manager/DialogueManager.cs

Lines changed: 154 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
namespace DialogueManagerRuntime
1111
{
12+
13+
public enum MutationBehaviour
14+
{
15+
Wait,
16+
DoNotWait,
17+
Skip
18+
}
19+
1220
public enum TranslationSource
1321
{
1422
None,
@@ -33,6 +41,8 @@ public partial class DialogueManager : RefCounted
3341

3442
[Signal] public delegate void ResolvedEventHandler(Variant value);
3543

44+
private static Random random = new Random();
45+
3646
private static GodotObject? instance;
3747
public static GodotObject Instance
3848
{
@@ -41,7 +51,11 @@ public static GodotObject Instance
4151
if (instance == null)
4252
{
4353
instance = Engine.GetSingleton("DialogueManager");
44-
instance.Connect("bridge_dialogue_started", Callable.From((Resource dialogueResource) => DialogueStarted?.Invoke(dialogueResource)));
54+
instance.Connect("dialogue_started", Callable.From((Resource dialogueResource) => DialogueStarted?.Invoke(dialogueResource)));
55+
instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title)));
56+
instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line))));
57+
instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation)));
58+
instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource)));
4559
}
4660
return instance;
4761
}
@@ -81,56 +95,37 @@ public static Func<Node> GetCurrentScene
8195
set => Instance.Set("get_current_scene", Callable.From(value));
8296
}
8397

84-
85-
public static void Prepare(GodotObject instance)
98+
public static Resource CreateResourceFromText(string text)
8699
{
87-
instance.Connect("passed_title", Callable.From((string title) => PassedTitle?.Invoke(title)));
88-
instance.Connect("got_dialogue", Callable.From((RefCounted line) => GotDialogue?.Invoke(new DialogueLine(line))));
89-
instance.Connect("mutated", Callable.From((Dictionary mutation) => Mutated?.Invoke(mutation)));
90-
instance.Connect("dialogue_ended", Callable.From((Resource dialogueResource) => DialogueEnded?.Invoke(dialogueResource)));
100+
return (Resource)Instance.Call("create_resource_from_text", text);
91101
}
92102

93-
94-
public static async Task<GodotObject> GetSingleton()
103+
public static async Task<DialogueLine?> GetNextDialogueLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null, MutationBehaviour mutation_behaviour = MutationBehaviour.Wait)
95104
{
96-
if (instance != null) return instance;
97-
98-
var tree = Engine.GetMainLoop();
99-
int x = 0;
100-
101-
// Try and find the singleton for a few seconds
102-
while (!Engine.HasSingleton("DialogueManager") && x < 300)
105+
int id = random.Next();
106+
Instance.Call("_bridge_get_next_dialogue_line", id, dialogueResource, key, extraGameStates ?? new Array<Variant>(), (int)mutation_behaviour);
107+
while (true)
103108
{
104-
await tree.ToSignal(tree, SceneTree.SignalName.ProcessFrame);
105-
x++;
106-
}
107-
108-
// If it times out something is wrong
109-
if (x >= 300)
110-
{
111-
throw new Exception("The DialogueManager singleton is missing.");
109+
var result = await Instance.ToSignal(Instance, "bridge_get_next_dialogue_line_completed");
110+
if ((int)result[0] == id)
111+
{
112+
return ((RefCounted)result[1] == null) ? null : new DialogueLine((RefCounted)result[1]);
113+
}
112114
}
113-
114-
instance = Engine.GetSingleton("DialogueManager");
115-
return instance;
116-
}
117-
118-
public static Resource CreateResourceFromText(string text)
119-
{
120-
return (Resource)Instance.Call("create_resource_from_text", text);
121115
}
122116

123-
public static async Task<DialogueLine?> GetNextDialogueLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null)
117+
public static async Task<DialogueLine?> GetLine(Resource dialogueResource, string key = "", Array<Variant>? extraGameStates = null)
124118
{
125-
var instance = (Node)Instance.Call("_bridge_get_new_instance");
126-
Prepare(instance);
127-
instance.Call("_bridge_get_next_dialogue_line", dialogueResource, key, extraGameStates ?? new Array<Variant>());
128-
var result = await instance.ToSignal(instance, "bridge_get_next_dialogue_line_completed");
129-
instance.QueueFree();
130-
131-
if ((RefCounted)result[0] == null) return null;
132-
133-
return new DialogueLine((RefCounted)result[0]);
119+
int id = random.Next();
120+
Instance.Call("_bridge_get_line", id, dialogueResource, key, extraGameStates ?? new Array<Variant>());
121+
while (true)
122+
{
123+
var result = await Instance.ToSignal(Instance, "bridge_get_line_completed");
124+
if ((int)result[0] == id)
125+
{
126+
return ((RefCounted)result[0] == null) ? null : new DialogueLine((RefCounted)result[0]);
127+
}
128+
}
134129
}
135130

136131

@@ -176,12 +171,20 @@ public static string StaticIdToLineId(Resource dialogueResource, string staticId
176171

177172
public static async void Mutate(Dictionary mutation, Array<Variant>? extraGameStates = null, bool isInlineMutation = false)
178173
{
179-
Instance.Call("_bridge_mutate", mutation, extraGameStates ?? new Array<Variant>(), isInlineMutation);
180-
await Instance.ToSignal(Instance, "bridge_mutated");
174+
int id = random.Next();
175+
Instance.Call("_bridge_mutate", id, mutation, extraGameStates ?? new Array<Variant>(), isInlineMutation);
176+
while (true)
177+
{
178+
var result = await Instance.ToSignal(Instance, "bridge_mutated");
179+
if ((int)result[0] == id)
180+
{
181+
return;
182+
}
183+
}
181184
}
182185

183186

184-
public static Array<Dictionary> GetMembersForAutoload(Script script)
187+
public static Array<Dictionary> GetMembersForScript(Script script)
185188
{
186189
Array<Dictionary> members = new Array<Dictionary>();
187190

@@ -215,6 +218,10 @@ public static Array<Dictionary> GetMembersForAutoload(Script script)
215218
type = "method";
216219
break;
217220

221+
case MemberTypes.NestedType:
222+
type = "constant";
223+
break;
224+
218225
default:
219226
continue;
220227
}
@@ -232,40 +239,43 @@ public static Array<Dictionary> GetMembersForAutoload(Script script)
232239

233240
public bool ThingHasConstant(GodotObject thing, string property)
234241
{
235-
var fieldInfos = thing.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
236-
foreach (var fieldInfo in fieldInfos)
237-
{
238-
if (fieldInfo.Name == property && fieldInfo.IsLiteral)
239-
{
240-
return true;
241-
}
242-
}
243-
244-
return false;
242+
var memberInfos = thing.GetType().GetMember(property, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
243+
return memberInfos.Length > 0;
245244
}
246245

247246

248247
public Variant ResolveThingConstant(GodotObject thing, string property)
249248
{
250-
var fieldInfos = thing.GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
251-
foreach (var fieldInfo in fieldInfos)
249+
var memberInfos = thing.GetType().GetMember(property, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
250+
foreach (var memberInfo in memberInfos)
252251
{
253-
if (fieldInfo.Name == property && fieldInfo.IsLiteral)
252+
if (memberInfo != null)
254253
{
255254
try
256255
{
257-
Variant value = fieldInfo.GetValue(thing) switch
256+
switch (memberInfo.MemberType)
258257
{
259-
int v => Variant.From((long)v),
260-
float v => Variant.From((double)v),
261-
System.String v => Variant.From((string)v),
262-
_ => Variant.From(fieldInfo.GetValue(thing))
263-
};
264-
return value;
258+
case MemberTypes.Field:
259+
return ConvertValueToVariant((memberInfo as FieldInfo).GetValue(thing));
260+
261+
case MemberTypes.Property:
262+
return ConvertValueToVariant((memberInfo as PropertyInfo).GetValue(thing));
263+
264+
case MemberTypes.NestedType:
265+
var type = thing.GetType().GetNestedType(property);
266+
if (type.IsEnum)
267+
{
268+
return GetEnumAsDictionary(type);
269+
}
270+
break;
271+
272+
default:
273+
continue;
274+
}
265275
}
266-
catch (Exception)
276+
catch (Exception e)
267277
{
268-
throw new Exception($"Constant {property} of type ${fieldInfo.GetValue(thing).GetType()} is not supported by Variant.");
278+
throw new Exception($"{property} is not supported by Variant.");
269279
}
270280
}
271281
}
@@ -274,6 +284,53 @@ public Variant ResolveThingConstant(GodotObject thing, string property)
274284
}
275285

276286

287+
Dictionary GetEnumAsDictionary(Type enumType)
288+
{
289+
Dictionary dictionary = new Dictionary();
290+
foreach (var value in enumType.GetEnumValuesAsUnderlyingType())
291+
{
292+
var key = enumType.GetEnumName(value);
293+
if (key != null)
294+
{
295+
dictionary.Add(key, ConvertValueToVariant(value));
296+
}
297+
}
298+
return dictionary;
299+
}
300+
301+
302+
Variant ConvertValueToVariant(object value)
303+
{
304+
if (value == null) return default;
305+
306+
Type rawType = value.GetType();
307+
if (rawType.IsEnum)
308+
{
309+
var values = GetEnumAsDictionary(rawType);
310+
value = values[value.ToString()];
311+
}
312+
313+
return value switch
314+
{
315+
Variant v => v,
316+
bool v => Variant.From(v),
317+
byte v => Variant.From((long)v),
318+
sbyte v => Variant.From((long)v),
319+
short v => Variant.From((long)v),
320+
ushort v => Variant.From((long)v),
321+
int v => Variant.From((long)v),
322+
uint v => Variant.From((long)v),
323+
long v => Variant.From(v),
324+
ulong v => Variant.From((long)v),
325+
float v => Variant.From((double)v),
326+
double v => Variant.From(v),
327+
string v => Variant.From(v),
328+
GodotObject godotObj => Variant.From(godotObj),
329+
_ => default
330+
};
331+
}
332+
333+
277334
public bool ThingHasMethod(GodotObject thing, string method, Array<Variant> args)
278335
{
279336
var methodInfos = thing.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
@@ -289,19 +346,22 @@ public bool ThingHasMethod(GodotObject thing, string method, Array<Variant> args
289346
}
290347

291348

292-
public async void ResolveThingMethod(GodotObject thing, string method, Array<Variant> args)
349+
public async void ResolveThingMethod(float id, GodotObject thing, string method, Array<Variant> args)
293350
{
294351
MethodInfo? info = null;
295352
var methodInfos = thing.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
296353
foreach (var methodInfo in methodInfos)
297354
{
298-
if (methodInfo.Name == method && args.Count >= methodInfo.GetParameters().Where(p => !p.HasDefaultValue).Count())
355+
if (methodInfo.Name == method && args.Count >= methodInfo.GetParameters().Count(p => !p.HasDefaultValue))
299356
{
300357
info = methodInfo;
301358
}
302359
}
303360

304-
if (info == null) return;
361+
if (info == null) {
362+
EmitSignal(SignalName.Resolved, id);
363+
return;
364+
}
305365

306366
#nullable disable
307367
// Convert the method args to something reflection can handle
@@ -339,20 +399,26 @@ public async void ResolveThingMethod(GodotObject thing, string method, Array<Var
339399
await taskResult;
340400
try
341401
{
342-
Variant value = (Variant)taskResult.GetType().GetProperty("Result").GetValue(taskResult);
343-
EmitSignal(SignalName.Resolved, value);
402+
object value = taskResult.GetType().GetProperty("Result").GetValue(taskResult);
403+
EmitSignal(SignalName.Resolved, id, ConvertValueToVariant(value));
344404
}
345405
catch (Exception)
346406
{
347-
EmitSignal(SignalName.Resolved);
407+
EmitSignal(SignalName.Resolved, id);
348408
}
349409
}
350410
else
351411
{
352-
EmitSignal(SignalName.Resolved, (Variant)result);
412+
EmitSignal(SignalName.Resolved, id, ConvertValueToVariant(result));
353413
}
354414
}
355415
#nullable enable
416+
417+
418+
public static string GetErrorMessage(int error)
419+
{
420+
return (string)Instance.Call("_bridge_get_error_message", error);
421+
}
356422
}
357423

358424

@@ -412,12 +478,6 @@ public string? Time
412478
get => time;
413479
}
414480

415-
private Dictionary pauses = new Dictionary();
416-
public Dictionary Pauses
417-
{
418-
get => pauses;
419-
}
420-
421481
private Dictionary speeds = new Dictionary();
422482
public Dictionary Speeds
423483
{
@@ -456,7 +516,6 @@ public DialogueLine(RefCounted data)
456516
character = (string)data.Get("character");
457517
text = (string)data.Get("text");
458518
translation_key = (string)data.Get("translation_key");
459-
pauses = (Dictionary)data.Get("pauses");
460519
speeds = (Dictionary)data.Get("speeds");
461520
inline_mutations = (Array<Godot.Collections.Array>)data.Get("inline_mutations");
462521
time = (string)data.Get("time");
@@ -474,6 +533,20 @@ public DialogueLine(RefCounted data)
474533
}
475534

476535

536+
public bool HasTag(string tagName)
537+
{
538+
string wrapped = $"{tagName}=";
539+
foreach (var tag in tags)
540+
{
541+
if (tag.StartsWith(wrapped))
542+
{
543+
return true;
544+
}
545+
}
546+
return false;
547+
}
548+
549+
477550
public string GetTagValue(string tagName)
478551
{
479552
string wrapped = $"{tagName}=";

0 commit comments

Comments
 (0)