Hue Preserving Color Blending
UpmBaseOperation.cs
1 using System;
2 using System.Globalization;
3 using System.Collections.Generic;
4 using System.Linq;
5 using Semver;
6 using UnityEngine;
7 using UnityEditor.PackageManager.Requests;
8 
10 {
11  internal abstract class UpmBaseOperation : IBaseOperation
12  {
13  public static string GroupName(PackageSource origin)
14  {
15  var group = PackageGroupOrigins.Packages.ToString();
16  if (origin == PackageSource.BuiltIn)
17  group = PackageGroupOrigins.BuiltInPackages.ToString();
18 
19  return group;
20  }
21 
22  protected static IEnumerable<PackageInfo> FromUpmPackageInfo(PackageManager.PackageInfo info, bool isCurrent=true)
23  {
24  var packages = new List<PackageInfo>();
25  var displayName = info.displayName;
26  if (string.IsNullOrEmpty(displayName))
27  {
28  displayName = info.name.Replace("com.unity.modules.", "");
29  displayName = displayName.Replace("com.unity.", "");
30  displayName = new CultureInfo("en-US").TextInfo.ToTitleCase(displayName);
31  }
32 
33  string author = info.author.name;
34  if (string.IsNullOrEmpty(info.author.name) && info.name.StartsWith("com.unity."))
35  author = "Unity Technologies Inc.";
36 
37  var lastCompatible = info.versions.latestCompatible;
38  var versions = new List<string>();
39  versions.AddRange(info.versions.compatible);
40  if (versions.FindIndex(version => version == info.version) == -1)
41  {
42  versions.Add(info.version);
43 
44  versions.Sort((left, right) =>
45  {
46  if (left == null || right == null) return 0;
47 
48  SemVersion leftVersion = left;
49  SemVersion righVersion = right;
50  return leftVersion.CompareByPrecedence(righVersion);
51  });
52 
53  SemVersion packageVersion = info.version;
54  if (!string.IsNullOrEmpty(lastCompatible))
55  {
56  SemVersion lastCompatibleVersion =
57  string.IsNullOrEmpty(lastCompatible) ? (SemVersion) null : lastCompatible;
58  if (packageVersion != null && string.IsNullOrEmpty(packageVersion.Prerelease) &&
59  packageVersion.CompareByPrecedence(lastCompatibleVersion) > 0)
60  lastCompatible = info.version;
61  }
62  else
63  {
64  if (packageVersion != null && string.IsNullOrEmpty(packageVersion.Prerelease))
65  lastCompatible = info.version;
66  }
67  }
68 
69  foreach(var version in versions)
70  {
71  var isVersionCurrent = version == info.version && isCurrent;
72  var isBuiltIn = info.source == PackageSource.BuiltIn;
73  var isVerified = string.IsNullOrEmpty(SemVersion.Parse(version).Prerelease) && version == info.versions.recommended;
74  var state = (isBuiltIn || info.version == lastCompatible || !isCurrent ) ? PackageState.UpToDate : PackageState.Outdated;
75 
76  // Happens mostly when using a package that hasn't been in production yet.
77  if (info.versions.all.Length <= 0)
78  state = PackageState.UpToDate;
79 
80  if (info.errors.Length > 0)
81  state = PackageState.Error;
82 
83  var packageInfo = new PackageInfo
84  {
85  Name = info.name,
86  DisplayName = displayName,
87  PackageId = version == info.version ? info.packageId : null,
88  Version = version,
89  Description = info.description,
90  Category = info.category,
91  IsCurrent = isVersionCurrent,
92  IsLatest = version == lastCompatible,
93  IsVerified = isVerified,
94  Errors = info.errors.ToList(),
95  Group = GroupName(info.source),
96  State = state,
97  Origin = isBuiltIn || isVersionCurrent ? info.source : PackageSource.Registry,
98  Author = author,
99  Info = info
100  };
101 
102  packages.Add(packageInfo);
103  }
104 
105  return packages;
106  }
107 
108  public static event Action<UpmBaseOperation> OnOperationStart = delegate { };
109 
110  public event Action<Error> OnOperationError = delegate { };
111  public event Action OnOperationFinalized = delegate { };
112 
113  public Error ForceError { get; set; } // Allow external component to force an error on the requests (eg: testing)
114  public Error Error { get; protected set; } // Keep last error
115 
116  public bool IsCompleted { get; private set; }
117 
118  protected abstract Request CreateRequest();
119 
120  [SerializeField]
121  protected Request CurrentRequest;
122  public readonly ThreadedDelay Delay = new ThreadedDelay();
123 
124  protected abstract void ProcessData();
125 
126  protected void Start()
127  {
128  Error = null;
129  OnOperationStart(this);
130 
131  Delay.Start();
132 
133  if (TryForcedError())
134  return;
135 
136  EditorApplication.update += Progress;
137  }
138 
139  // Common progress code for all classes
140  private void Progress()
141  {
142  if (!Delay.IsDone)
143  return;
144 
145  // Create the request after the delay
146  if (CurrentRequest == null)
147  {
148  CurrentRequest = CreateRequest();
149  }
150 
151  // Since CurrentRequest's error property is private, we need to simulate
152  // an error instead of just setting it.
153  if (TryForcedError())
154  return;
155 
156  if (CurrentRequest.IsCompleted)
157  {
158  if (CurrentRequest.Status == StatusCode.Success)
159  OnDone();
160  else if (CurrentRequest.Status >= StatusCode.Failure)
161  OnError(CurrentRequest.Error);
162  else
163  Debug.LogError("Unsupported progress state " + CurrentRequest.Status);
164  }
165  }
166 
167  private void OnError(Error error)
168  {
169  try
170  {
171  Error = error;
172 
173  var message = "Cannot perform upm operation.";
174  if (error != null)
175  message = "Cannot perform upm operation: " + Error.message + " [" + Error.errorCode + "]";
176 
177  Debug.LogError(message);
178 
179  OnOperationError(Error);
180  }
181  catch (Exception exception)
182  {
183  Debug.LogError("Package Manager Window had an error while reporting an error in an operation: " + exception);
184  }
185 
186  FinalizeOperation();
187  }
188 
189  private void OnDone()
190  {
191  try
192  {
193  ProcessData();
194  }
195  catch (Exception error)
196  {
197  Debug.LogError("Package Manager Window had an error while completing an operation: " + error);
198  }
199 
200  FinalizeOperation();
201  }
202 
203  private void FinalizeOperation()
204  {
205  EditorApplication.update -= Progress;
206  OnOperationFinalized();
207  IsCompleted = true;
208  }
209 
210  public void Cancel()
211  {
212  EditorApplication.update -= Progress;
213  OnOperationError = delegate { };
214  OnOperationFinalized = delegate { };
215  IsCompleted = true;
216  }
217 
218  private bool TryForcedError()
219  {
220  if (ForceError != null)
221  {
222  OnError(ForceError);
223  return true;
224  }
225 
226  return false;
227  }
228  }
229 }
A semantic version implementation. Conforms to v2.0.0 of http://semver.org/
Definition: SemVersion.cs:43
int CompareByPrecedence(SemVersion other)
Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build in...
Definition: SemVersion.cs:373
static SemVersion Parse(string version, bool strict=false)
Parses the specified string to a semantic version.
Definition: SemVersion.cs:132
string Prerelease
Gets the pre-release version.
Definition: SemVersion.cs:282