A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using UnityEngine;
4
5namespace Unity.VisualScripting
6{
7 public static class GraphsExceptionUtility
8 {
9 // Note: Checking hasDebugData here instead of enableDebug,
10 // because we always want exceptions to register, even if
11 // background debug is disabled.
12
13 private const string handledKey = "Bolt.Core.Handled";
14
15 public static Exception GetException(this IGraphElementWithDebugData element, GraphPointer pointer)
16 {
17 if (!pointer.hasDebugData)
18 {
19 return null;
20 }
21
22 var debugData = pointer.GetElementDebugData<IGraphElementDebugData>(element);
23
24 return debugData.runtimeException;
25 }
26
27 public static void SetException(this IGraphElementWithDebugData element, GraphPointer pointer, Exception ex)
28 {
29 if (!pointer.hasDebugData)
30 {
31 return;
32 }
33
34 var debugData = pointer.GetElementDebugData<IGraphElementDebugData>(element);
35
36 debugData.runtimeException = ex;
37 }
38
39 public static void HandleException(this IGraphElementWithDebugData element, GraphPointer pointer, Exception ex)
40 {
41 Ensure.That(nameof(ex)).IsNotNull(ex);
42
43 if (pointer == null)
44 {
45 Debug.LogError("Caught exception with null graph pointer (flow was likely disposed):\n" + ex);
46 return;
47 }
48
49 var reference = pointer.AsReference();
50
51 if (!ex.HandledIn(reference))
52 {
53 element.SetException(pointer, ex);
54 }
55
56 while (reference.isChild)
57 {
58 var parentElement = reference.parentElement;
59 reference = reference.ParentReference(true);
60
61 if (parentElement is IGraphElementWithDebugData debuggableParentElement)
62 {
63 if (!ex.HandledIn(reference))
64 {
65 debuggableParentElement.SetException(reference, ex);
66 }
67 }
68 }
69 }
70
71 private static bool HandledIn(this Exception ex, GraphReference reference)
72 {
73 Ensure.That(nameof(ex)).IsNotNull(ex);
74
75 if (!ex.Data.Contains(handledKey))
76 {
77 ex.Data.Add(handledKey, new HashSet<GraphReference>());
78 }
79
80 var handled = (HashSet<GraphReference>)ex.Data[handledKey];
81
82 if (handled.Contains(reference))
83 {
84 return true;
85 }
86 else
87 {
88 handled.Add(reference);
89 return false;
90 }
91 }
92 }
93}