A game about forced loneliness, made by TACStudios
1using System.IO;
2using System.Collections.Generic;
3
4using UnityEditor;
5using UnityEditor.SceneManagement;
6using UnityEngine.SceneManagement;
7
8using Codice.Client.BaseCommands;
9using Codice.Client.Common;
10using Unity.PlasticSCM.Editor.AssetUtils.Processor;
11
12namespace Unity.PlasticSCM.Editor.AssetUtils
13{
14 internal interface ISaveAssets
15 {
16 void UnderWorkspaceWithConfirmation(
17 string wkPath,
18 WorkspaceOperationsMonitor workspaceOperationsMonitor,
19 out bool isCancelled);
20
21 void ForChangesWithConfirmation(
22 string wkPath,
23 List<ChangeInfo> changes,
24 WorkspaceOperationsMonitor workspaceOperationsMonitor,
25 out bool isCancelled);
26
27 void ForPathsWithConfirmation(
28 string wkPath,
29 List<string> paths,
30 WorkspaceOperationsMonitor workspaceOperationsMonitor,
31 out bool isCancelled);
32
33 void ForChangesWithoutConfirmation(
34 string wkPath,
35 List<ChangeInfo> changes,
36 WorkspaceOperationsMonitor workspaceOperationsMonitor);
37
38 void ForPathsWithoutConfirmation(
39 string wkPath,
40 List<string> paths,
41 WorkspaceOperationsMonitor workspaceOperationsMonitor);
42 }
43
44 internal class SaveAssets : ISaveAssets
45 {
46 void ISaveAssets.UnderWorkspaceWithConfirmation(
47 string wkPath,
48 WorkspaceOperationsMonitor workspaceOperationsMonitor,
49 out bool isCancelled)
50 {
51 ForPaths(
52 wkPath,
53 null,
54 true,
55 workspaceOperationsMonitor,
56 out isCancelled);
57 }
58
59 void ISaveAssets.ForChangesWithConfirmation(
60 string wkPath,
61 List<ChangeInfo> changes,
62 WorkspaceOperationsMonitor workspaceOperationsMonitor,
63 out bool isCancelled)
64 {
65 ForPaths(
66 wkPath,
67 GetPaths(changes),
68 true,
69 workspaceOperationsMonitor,
70 out isCancelled);
71 }
72
73 void ISaveAssets.ForPathsWithConfirmation(
74 string wkPath,
75 List<string> paths,
76 WorkspaceOperationsMonitor workspaceOperationsMonitor,
77 out bool isCancelled)
78 {
79 ForPaths(
80 wkPath,
81 paths,
82 true,
83 workspaceOperationsMonitor,
84 out isCancelled);
85 }
86
87 void ISaveAssets.ForChangesWithoutConfirmation(
88 string wkPath,
89 List<ChangeInfo> changes,
90 WorkspaceOperationsMonitor workspaceOperationsMonitor)
91 {
92 bool isCancelled;
93 ForPaths(
94 wkPath,
95 GetPaths(changes),
96 false,
97 workspaceOperationsMonitor,
98 out isCancelled);
99 }
100
101 void ISaveAssets.ForPathsWithoutConfirmation(
102 string wkPath,
103 List<string> paths,
104 WorkspaceOperationsMonitor workspaceOperationsMonitor)
105 {
106 bool isCancelled;
107 ForPaths(
108 wkPath,
109 paths,
110 false,
111 workspaceOperationsMonitor,
112 out isCancelled);
113 }
114
115 static void ForPaths(
116 string wkPath,
117 List<string> paths,
118 bool askForUserConfirmation,
119 WorkspaceOperationsMonitor workspaceOperationsMonitor,
120 out bool isCancelled)
121 {
122 workspaceOperationsMonitor.Disable();
123 try
124 {
125 SaveDirtyScenes(
126 wkPath,
127 paths,
128 askForUserConfirmation,
129 out isCancelled);
130
131 if (isCancelled)
132 return;
133
134 AssetDatabase.SaveAssets();
135 }
136 finally
137 {
138 workspaceOperationsMonitor.Enable();
139 }
140 }
141
142 static void SaveDirtyScenes(
143 string wkPath,
144 List<string> paths,
145 bool askForUserConfirmation,
146 out bool isCancelled)
147 {
148 isCancelled = false;
149
150 List<Scene> scenesToSave = GetScenesToSave(wkPath, paths);
151
152 if (scenesToSave.Count == 0)
153 return;
154
155 if (askForUserConfirmation)
156 {
157 isCancelled = !EditorSceneManager.
158 SaveModifiedScenesIfUserWantsTo(
159 scenesToSave.ToArray());
160
161 if (!isCancelled)
162 DiscardChangesInActiveSceneIfDirty(scenesToSave);
163
164 return;
165 }
166
167 EditorSceneManager.SaveScenes(
168 scenesToSave.ToArray());
169 }
170
171 static void DiscardChangesInActiveSceneIfDirty(List<Scene> scenesToSave)
172 {
173 string activeScenePath = EditorSceneManager.GetActiveScene().path;
174 Scene? activeScene = GetSceneByPath(scenesToSave, activeScenePath);
175
176 if (activeScene == null)
177 return;
178
179 if (!activeScene.Value.isDirty)
180 return;
181
182 EditorSceneManager.OpenScene(activeScenePath);
183 }
184
185 static Scene? GetSceneByPath(List<Scene> scenes, string scenePath)
186 {
187 foreach (Scene scene in scenes)
188 {
189 if (scene.path == scenePath)
190 return scene;
191 }
192
193 return null;
194 }
195
196 static List<Scene> GetScenesToSave(string wkPath, List<string> paths)
197 {
198 List<Scene> dirtyScenes = GetDirtyScenesUnderWorkspace(wkPath);
199
200 if (paths == null)
201 return dirtyScenes;
202
203 List<Scene> scenesToSave = new List<Scene>();
204
205 foreach (Scene dirtyScene in dirtyScenes)
206 {
207 if (Contains(paths, dirtyScene))
208 scenesToSave.Add(dirtyScene);
209 }
210
211 return scenesToSave;
212 }
213
214 static List<Scene> GetDirtyScenesUnderWorkspace(string wkPath)
215 {
216 List<Scene> dirtyScenes = new List<Scene>();
217
218 for (int i = 0; i < SceneManager.sceneCount; i++)
219 {
220 Scene scene = SceneManager.GetSceneAt(i);
221
222 if (!scene.isDirty)
223 continue;
224
225 if (string.IsNullOrEmpty(scene.path))
226 continue;
227
228 string fullPath = Path.GetFullPath(scene.path);
229
230 if (!PathHelper.IsContainedOn(fullPath, wkPath))
231 continue;
232
233 dirtyScenes.Add(scene);
234 }
235
236 return dirtyScenes;
237 }
238
239 static bool Contains(
240 List<string> paths,
241 Scene scene)
242 {
243 foreach (string path in paths)
244 {
245 if (PathHelper.IsSamePath(
246 path,
247 Path.GetFullPath(scene.path)))
248 return true;
249 }
250
251 return false;
252 }
253
254 static List<string> GetPaths(
255 List<ChangeInfo> changeInfos)
256 {
257 List<string> result = new List<string>();
258 foreach (ChangeInfo change in changeInfos)
259 result.Add(change.GetFullPath());
260 return result;
261 }
262 }
263}