Hue Preserving Color Blending
Package.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Linq;
5 using UnityEngine;
6 
8 {
9  // History of a single package
10  internal class Package : IEquatable<Package>
11  {
12  static public bool ShouldProposeLatestVersions
13  {
14  get
15  {
16  // Until we figure out a way to test this properly, alway show standard behavior
17  // return InternalEditorUtility.IsUnityBeta() && !Unsupported.IsDeveloperMode();
18  return false;
19  }
20  }
21 
22  // There can only be one package add/remove operation.
23  private static IBaseOperation addRemoveOperationInstance;
24 
25  public static bool AddRemoveOperationInProgress
26  {
27  get { return addRemoveOperationInstance != null && !addRemoveOperationInstance.IsCompleted; }
28  }
29 
30  internal const string packageManagerUIName = "com.unity.package-manager-ui";
31  private readonly string packageName;
32  private IEnumerable<PackageInfo> source;
33 
34  internal Package(string packageName, IEnumerable<PackageInfo> infos)
35  {
36  if (string.IsNullOrEmpty(packageName))
37  throw new ArgumentException("Cannot be empty or null", "packageName");
38 
39  if (!infos.Any())
40  throw new ArgumentException("Cannot be empty", "infos");
41 
42  this.packageName = packageName;
43  UpdateSource(infos);
44  }
45 
46  internal void UpdateSource(IEnumerable<PackageInfo> source)
47  {
48  this.source = source;
49 #if UNITY_2018_3_OR_NEWER
50  if (IsPackageManagerUI)
51  this.source = this.source.Where(p => p != null && p.Version.Major >= 2);
52 #endif
53  }
54 
55  public PackageInfo Current { get { return Versions.FirstOrDefault(package => package.IsCurrent); } }
56 
57  // This is the latest verified or official release (eg: 1.3.2). Not necessarily the latest verified release (eg: 1.2.4) or that latest candidate (eg: 1.4.0-beta)
58  public PackageInfo LatestUpdate
59  {
60  get
61  {
62  // We want to show the absolute latest when in beta mode
63  if (ShouldProposeLatestVersions)
64  return Latest;
65 
66  // Override with current when it's version locked
67  var current = Current;
68  if (current != null && current.IsVersionLocked)
69  return current;
70 
71  // Get all the candidates versions (verified, release, preview) that are newer than current
72  var verified = Verified;
73  var latestRelease = LatestRelease;
74  var latestPreview = Versions.LastOrDefault(package => package.IsPreview);
75  var candidates = new List<PackageInfo>
76  {
77  verified,
78  latestRelease,
79  latestPreview,
80  }.Where(package => package != null && (current == null || current == package || current.Version < package.Version)).ToList();
81 
82  if (candidates.Contains(verified))
83  return verified;
84  if ((current == null || !current.IsVerified ) && candidates.Contains(latestRelease))
85  return latestRelease;
86  if ((current == null || current.IsPreview) && candidates.Contains(latestPreview))
87  return latestPreview;
88 
89  // Show current if it exists, otherwise latest user visible, and then otherwise show the absolute latest
90  return current ?? Latest;
91  }
92  }
93 
94  public PackageInfo LatestPatch
95  {
96  get
97  {
98  if (Current == null)
99  return null;
100 
101  // Get all version that have the same Major/Minor
102  var versions = Versions.Where(package => package.Version.Major == Current.Version.Major && package.Version.Minor == Current.Version.Minor);
103 
104  return versions.LastOrDefault();
105  }
106  }
107 
108  // This is the very latest version, including pre-releases (eg: 1.4.0-beta).
109  internal PackageInfo Latest { get { return Versions.FirstOrDefault(package => package.IsLatest) ?? Versions.LastOrDefault(); } }
110 
111  // Returns the current version if it exist, otherwise returns the latest user visible version.
112  internal PackageInfo VersionToDisplay { get { return Current ?? LatestUpdate; } }
113 
114  // Every version available for this package
115  internal IEnumerable<PackageInfo> Versions { get { return source.OrderBy(package => package.Version); } }
116 
117  // Every version that's not a pre-release (eg: not beta/alpha/preview).
118  internal IEnumerable<PackageInfo> ReleaseVersions
119  {
120  get { return Versions.Where(package => !package.IsPreRelease); }
121  }
122 
123  internal PackageInfo LatestRelease { get {return ReleaseVersions.LastOrDefault();}}
124  internal PackageInfo Verified { get {return Versions.FirstOrDefault(package => package.IsVerified);}}
125 
126  internal bool IsAfterCurrentVersion(PackageInfo packageInfo) { return Current == null || (packageInfo != null && packageInfo.Version > Current.Version); }
127 
128  internal bool IsBuiltIn {get { return Versions.Any() && Versions.First().IsBuiltIn; }}
129 
130  public string Name { get { return packageName; } }
131 
132  public bool IsPackageManagerUI
133  {
134  get { return Name == packageManagerUIName; }
135  }
136 
137  public bool Equals(Package other)
138  {
139  if (other == null)
140  return false;
141 
142  return packageName == other.packageName;
143  }
144 
145  public override int GetHashCode()
146  {
147  return packageName.GetHashCode();
148  }
149 
150  [SerializeField]
151  internal readonly OperationSignal<IAddOperation> AddSignal = new OperationSignal<IAddOperation>();
152 
153  private Action OnAddOperationFinalizedEvent;
154 
155  internal void Add(PackageInfo packageInfo)
156  {
157  if (packageInfo == Current || AddRemoveOperationInProgress)
158  return;
159 
160  var operation = OperationFactory.Instance.CreateAddOperation();
161  addRemoveOperationInstance = operation;
162  OnAddOperationFinalizedEvent = () =>
163  {
164  AddSignal.Operation = null;
165  operation.OnOperationFinalized -= OnAddOperationFinalizedEvent;
166  PackageCollection.Instance.FetchListOfflineCache(true);
167  };
168 
169  operation.OnOperationFinalized += OnAddOperationFinalizedEvent;
170 
171  AddSignal.SetOperation(operation);
172  operation.AddPackageAsync(packageInfo);
173  }
174 
175  internal void Update()
176  {
177  Add(Latest);
178  }
179 
180  internal static void AddFromLocalDisk(string path)
181  {
182  if (AddRemoveOperationInProgress)
183  return;
184 
185  var packageJson = PackageJsonHelper.Load(path);
186  if (null == packageJson)
187  {
188  Debug.LogError(string.Format("Invalid package path: cannot find \"{0}\".", path));
189  return;
190  }
191 
192  var operation = OperationFactory.Instance.CreateAddOperation();
193  addRemoveOperationInstance = operation;
194  operation.AddPackageAsync(packageJson.PackageInfo);
195  }
196 
197  [SerializeField]
198  internal readonly OperationSignal<IRemoveOperation> RemoveSignal = new OperationSignal<IRemoveOperation>();
199 
200  private Action OnRemoveOperationFinalizedEvent;
201 
202  public void Remove()
203  {
204  if (Current == null || AddRemoveOperationInProgress)
205  return;
206 
207  var operation = OperationFactory.Instance.CreateRemoveOperation();
208  addRemoveOperationInstance = operation;
209  OnRemoveOperationFinalizedEvent = () =>
210  {
211  RemoveSignal.Operation = null;
212  operation.OnOperationFinalized -= OnRemoveOperationFinalizedEvent;
213  PackageCollection.Instance.FetchListOfflineCache(true);
214  };
215 
216  operation.OnOperationFinalized += OnRemoveOperationFinalizedEvent;
217  RemoveSignal.SetOperation(operation);
218 
219  operation.RemovePackageAsync(Current);
220  }
221  }
222 }