A game about forced loneliness, made by TACStudios
1using System;
2using UnityEditor;
3using Unity.Collections;
4using Unity.Collections.LowLevel.Unsafe;
5using Unity.Jobs.LowLevel.Unsafe;
6using UnityEngine;
7
8// This menu is available from the editor directly on later versions
9#if !UNITY_2022_2_14F1_OR_NEWER
10class JobsMenu
11{
12 private static int savedJobWorkerCount = JobsUtility.JobWorkerCount;
13
14 [SettingsProvider]
15 private static SettingsProvider JobsPreferencesItem()
16 {
17 var provider = new SettingsProvider("Preferences/Jobs", SettingsScope.User)
18 {
19 label = "Jobs",
20 keywords = new[]{"Jobs"},
21 guiHandler = (searchContext) =>
22 {
23 var originalWidth = EditorGUIUtility.labelWidth;
24 EditorGUIUtility.labelWidth = 200f;
25 EditorGUILayout.BeginVertical();
26
27 GUILayout.BeginVertical();
28 EditorGUILayout.LabelField("For safety, these values are reset on editor restart.");
29
30 bool madeChange = false;
31
32 bool oldWorkerCount = (JobsUtility.JobWorkerCount > 0);
33 bool newWorkerCount = EditorGUILayout.Toggle(new GUIContent("Use Job Threads:"), oldWorkerCount);
34 if (newWorkerCount != oldWorkerCount)
35 {
36 madeChange = true;
37 SwitchUseJobThreads();
38 }
39
40 bool oldUseJobsDebugger = JobsUtility.JobDebuggerEnabled;
41 var newUseJobsDebugger = EditorGUILayout.Toggle(new GUIContent("Enable Jobs Debugger"), JobsUtility.JobDebuggerEnabled);
42 if (newUseJobsDebugger != oldUseJobsDebugger)
43 {
44 madeChange = true;
45 SetUseJobsDebugger(newUseJobsDebugger);
46 }
47
48 var oldLeakDetectionMode = NativeLeakDetection.Mode;
49 var newLeakDetectionMode = (NativeLeakDetectionMode) EditorGUILayout.EnumPopup(new GUIContent("Leak Detection Level"), oldLeakDetectionMode);
50 if (newLeakDetectionMode != oldLeakDetectionMode)
51 {
52 madeChange = true;
53 SetLeakDetection(newLeakDetectionMode);
54 }
55
56 if (madeChange)
57 Telemetry.LogMenuPreferences(new Telemetry.MenuPreferencesEvent { useJobsThreads = newUseJobsDebugger, enableJobsDebugger = newUseJobsDebugger, nativeLeakDetectionMode = newLeakDetectionMode });
58
59 GUILayout.EndVertical();
60 EditorGUILayout.EndVertical();
61
62 EditorGUIUtility.labelWidth = originalWidth;
63 }
64
65 };
66
67 return provider;
68 }
69
70 static void SwitchUseJobThreads()
71 {
72 if (JobsUtility.JobWorkerCount > 0)
73 {
74 savedJobWorkerCount = JobsUtility.JobWorkerCount;
75 JobsUtility.JobWorkerCount = 0;
76 }
77 else
78 {
79 JobsUtility.JobWorkerCount = savedJobWorkerCount;
80 if (savedJobWorkerCount == 0)
81 {
82 JobsUtility.ResetJobWorkerCount();
83 }
84 }
85 }
86
87 static void SetUseJobsDebugger(bool value)
88 {
89 JobsUtility.JobDebuggerEnabled = value;
90 }
91
92 static void SetLeakDetection(NativeLeakDetectionMode value)
93 {
94 switch(value)
95 {
96 case NativeLeakDetectionMode.Disabled:
97 {
98 // In the case where someone enables, disables, then re-enables leak checking, we might miss some frees
99 // while disabled. So to avoid spurious leak warnings, just forgive the leaks every time someone disables
100 // leak checking through the menu.
101 UnsafeUtility.ForgiveLeaks();
102 Debug.LogWarning("Leak detection has been disabled. Leak warnings will not be generated, and all leaks up to now are forgotten.");
103 break;
104 }
105 case NativeLeakDetectionMode.Enabled:
106 {
107 Debug.Log("Leak detection has been enabled. Leak warnings will be generated upon exiting play mode.");
108 break;
109 }
110 case NativeLeakDetectionMode.EnabledWithStackTrace:
111 {
112 Debug.Log("Leak detection with stack traces has been enabled. Leak warnings will be generated upon exiting play mode.");
113 break;
114 }
115 default:
116 {
117 throw new Exception($"Unhandled {nameof(NativeLeakDetectionMode)}");
118 }
119 }
120
121 NativeLeakDetection.Mode = value;
122 }
123}
124#endif