mirror of
https://github.com/storytold/Azure-Kinect-Sample-for-Unity.git
synced 2026-10-12 21:49:59 +00:00
Sample
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06b575597b644fe8ba88495149d01b66
|
||||
timeCreated: 1503684160
|
||||
+563
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
Copyright (c) 2013 Max Hauser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
From: https://github.com/maxhauser/semver
|
||||
*/
|
||||
|
||||
using System;
|
||||
#if !NETSTANDARD
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Permissions;
|
||||
#endif
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Semver
|
||||
{
|
||||
/// <summary>
|
||||
/// A semantic version implementation.
|
||||
/// Conforms to v2.0.0 of http://semver.org/
|
||||
/// </summary>
|
||||
#if NETSTANDARD
|
||||
public sealed class SemVersion : IComparable<SemVersion>, IComparable
|
||||
#else
|
||||
[Serializable]
|
||||
internal sealed class SemVersion : IComparable<SemVersion>, IComparable, ISerializable
|
||||
#endif
|
||||
{
|
||||
static Regex parseEx =
|
||||
new Regex(@"^(?<major>\d+)" +
|
||||
@"(\.(?<minor>\d+))?" +
|
||||
@"(\.(?<patch>\d+))?" +
|
||||
@"(\-(?<pre>[0-9A-Za-z\-\.]+))?" +
|
||||
@"(\+(?<build>[0-9A-Za-z\-\.]+))?$",
|
||||
#if NETSTANDARD
|
||||
RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
|
||||
#else
|
||||
RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
|
||||
#endif
|
||||
|
||||
#if !NETSTANDARD
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SemVersion" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
private SemVersion(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null) throw new ArgumentNullException("info");
|
||||
var semVersion = Parse(info.GetString("SemVersion"));
|
||||
Major = semVersion.Major;
|
||||
Minor = semVersion.Minor;
|
||||
Patch = semVersion.Patch;
|
||||
Prerelease = semVersion.Prerelease;
|
||||
Build = semVersion.Build;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SemVersion" /> class.
|
||||
/// </summary>
|
||||
/// <param name="major">The major version.</param>
|
||||
/// <param name="minor">The minor version.</param>
|
||||
/// <param name="patch">The patch version.</param>
|
||||
/// <param name="prerelease">The prerelease version (eg. "alpha").</param>
|
||||
/// <param name="build">The build eg ("nightly.232").</param>
|
||||
public SemVersion(int major, int minor = 0, int patch = 0, string prerelease = "", string build = "")
|
||||
{
|
||||
this.Major = major;
|
||||
this.Minor = minor;
|
||||
this.Patch = patch;
|
||||
|
||||
this.Prerelease = prerelease ?? "";
|
||||
this.Build = build ?? "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SemVersion"/> class.
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="System.Version"/> that is used to initialize
|
||||
/// the Major, Minor, Patch and Build properties.</param>
|
||||
public SemVersion(Version version)
|
||||
{
|
||||
if (version == null)
|
||||
throw new ArgumentNullException("version");
|
||||
|
||||
this.Major = version.Major;
|
||||
this.Minor = version.Minor;
|
||||
|
||||
if (version.Revision >= 0)
|
||||
{
|
||||
this.Patch = version.Revision;
|
||||
}
|
||||
|
||||
this.Prerelease = String.Empty;
|
||||
|
||||
if (version.Build > 0)
|
||||
{
|
||||
this.Build = version.Build.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Build = String.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the specified string to a semantic version.
|
||||
/// </summary>
|
||||
/// <param name="version">The version string.</param>
|
||||
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
||||
/// <returns>The SemVersion object.</returns>
|
||||
/// <exception cref="System.InvalidOperationException">When a invalid version string is passed.</exception>
|
||||
public static SemVersion Parse(string version, bool strict = false)
|
||||
{
|
||||
var match = parseEx.Match(version);
|
||||
if (!match.Success)
|
||||
{
|
||||
return new SemVersion(0);
|
||||
}
|
||||
|
||||
#if NETSTANDARD
|
||||
var major = int.Parse(match.Groups["major"].Value);
|
||||
#else
|
||||
var major = int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture);
|
||||
#endif
|
||||
|
||||
var minorMatch = match.Groups["minor"];
|
||||
int minor = 0;
|
||||
if (minorMatch.Success)
|
||||
{
|
||||
#if NETSTANDARD
|
||||
minor = int.Parse(minorMatch.Value);
|
||||
#else
|
||||
minor = int.Parse(minorMatch.Value, CultureInfo.InvariantCulture);
|
||||
#endif
|
||||
}
|
||||
else if (strict)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid version (no minor version given in strict mode)");
|
||||
}
|
||||
|
||||
var patchMatch = match.Groups["patch"];
|
||||
int patch = 0;
|
||||
if (patchMatch.Success)
|
||||
{
|
||||
#if NETSTANDARD
|
||||
patch = int.Parse(patchMatch.Value);
|
||||
#else
|
||||
patch = int.Parse(patchMatch.Value, CultureInfo.InvariantCulture);
|
||||
#endif
|
||||
}
|
||||
else if (strict)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid version (no patch version given in strict mode)");
|
||||
}
|
||||
|
||||
var prerelease = match.Groups["pre"].Value;
|
||||
var build = match.Groups["build"].Value;
|
||||
|
||||
return new SemVersion(major, minor, patch, prerelease, build);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the specified string to a semantic version.
|
||||
/// </summary>
|
||||
/// <param name="version">The version string.</param>
|
||||
/// <param name="semver">When the method returns, contains a SemVersion instance equivalent
|
||||
/// to the version string passed in, if the version string was valid, or <c>null</c> if the
|
||||
/// version string was not valid.</param>
|
||||
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
|
||||
/// <returns><c>False</c> when a invalid version string is passed, otherwise <c>true</c>.</returns>
|
||||
public static bool TryParse(string version, out SemVersion semver, bool strict = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
semver = Parse(version, strict);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
semver = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the specified versions for equality.
|
||||
/// </summary>
|
||||
/// <param name="versionA">The first version.</param>
|
||||
/// <param name="versionB">The second version.</param>
|
||||
/// <returns>If versionA is equal to versionB <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool Equals(SemVersion versionA, SemVersion versionB)
|
||||
{
|
||||
if (ReferenceEquals(versionA, null))
|
||||
return ReferenceEquals(versionB, null);
|
||||
return versionA.Equals(versionB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the specified versions.
|
||||
/// </summary>
|
||||
/// <param name="versionA">The version to compare to.</param>
|
||||
/// <param name="versionB">The version to compare against.</param>
|
||||
/// <returns>If versionA < versionB <c>< 0</c>, if versionA > versionB <c>> 0</c>,
|
||||
/// if versionA is equal to versionB <c>0</c>.</returns>
|
||||
public static int Compare(SemVersion versionA, SemVersion versionB)
|
||||
{
|
||||
if (ReferenceEquals(versionA, null))
|
||||
return ReferenceEquals(versionB, null) ? 0 : -1;
|
||||
return versionA.CompareTo(versionB);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a copy of the current instance with optional altered fields.
|
||||
/// </summary>
|
||||
/// <param name="major">The major version.</param>
|
||||
/// <param name="minor">The minor version.</param>
|
||||
/// <param name="patch">The patch version.</param>
|
||||
/// <param name="prerelease">The prerelease text.</param>
|
||||
/// <param name="build">The build text.</param>
|
||||
/// <returns>The new version object.</returns>
|
||||
public SemVersion Change(int? major = null, int? minor = null, int? patch = null,
|
||||
string prerelease = null, string build = null)
|
||||
{
|
||||
return new SemVersion(
|
||||
major ?? this.Major,
|
||||
minor ?? this.Minor,
|
||||
patch ?? this.Patch,
|
||||
prerelease ?? this.Prerelease,
|
||||
build ?? this.Build);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the major version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The major version.
|
||||
/// </value>
|
||||
public int Major { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minor version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The minor version.
|
||||
/// </value>
|
||||
public int Minor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the patch version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The patch version.
|
||||
/// </value>
|
||||
public int Patch { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pre-release version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The pre-release version.
|
||||
/// </value>
|
||||
public string Prerelease { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the build version.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The build version.
|
||||
/// </value>
|
||||
public string Build { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var version = "" + Major + "." + Minor + "." + Patch;
|
||||
if (!String.IsNullOrEmpty(Prerelease))
|
||||
version += "-" + Prerelease;
|
||||
if (!String.IsNullOrEmpty(Build))
|
||||
version += "+" + Build;
|
||||
return version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the current instance with another object of the same type and returns an integer that indicates
|
||||
/// whether the current instance precedes, follows, or occurs in the same position in the sort order as the
|
||||
/// other object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// A value that indicates the relative order of the objects being compared.
|
||||
/// The return value has these meanings: Value Meaning Less than zero
|
||||
/// This instance precedes <paramref name="obj" /> in the sort order.
|
||||
/// Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. i
|
||||
/// Greater than zero This instance follows <paramref name="obj" /> in the sort order.
|
||||
/// </returns>
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
return CompareTo((SemVersion)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the current instance with another object of the same type and returns an integer that indicates
|
||||
/// whether the current instance precedes, follows, or occurs in the same position in the sort order as the
|
||||
/// other object.
|
||||
/// </summary>
|
||||
/// <param name="other">An object to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// A value that indicates the relative order of the objects being compared.
|
||||
/// The return value has these meanings: Value Meaning Less than zero
|
||||
/// This instance precedes <paramref name="other" /> in the sort order.
|
||||
/// Zero This instance occurs in the same position in the sort order as <paramref name="other" />. i
|
||||
/// Greater than zero This instance follows <paramref name="other" /> in the sort order.
|
||||
/// </returns>
|
||||
public int CompareTo(SemVersion other)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
return 1;
|
||||
|
||||
var r = this.CompareByPrecedence(other);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CompareComponent(this.Build, other.Build);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build information.
|
||||
/// </summary>
|
||||
/// <param name="other">The semantic version.</param>
|
||||
/// <returns><c>true</c> if the version precedence matches.</returns>
|
||||
public bool PrecedenceMatches(SemVersion other)
|
||||
{
|
||||
return CompareByPrecedence(other) == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build information.
|
||||
/// </summary>
|
||||
/// <param name="other">The semantic version.</param>
|
||||
/// <returns>
|
||||
/// A value that indicates the relative order of the objects being compared.
|
||||
/// The return value has these meanings: Value Meaning Less than zero
|
||||
/// This instance precedes <paramref name="other" /> in the version precedence.
|
||||
/// Zero This instance has the same precedence as <paramref name="other" />. i
|
||||
/// Greater than zero This instance has creater precedence as <paramref name="other" />.
|
||||
/// </returns>
|
||||
public int CompareByPrecedence(SemVersion other)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
return 1;
|
||||
|
||||
var r = this.Major.CompareTo(other.Major);
|
||||
if (r != 0) return r;
|
||||
|
||||
r = this.Minor.CompareTo(other.Minor);
|
||||
if (r != 0) return r;
|
||||
|
||||
r = this.Patch.CompareTo(other.Patch);
|
||||
if (r != 0) return r;
|
||||
|
||||
r = CompareComponent(this.Prerelease, other.Prerelease, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int CompareComponent(string a, string b, bool lower = false)
|
||||
{
|
||||
var aEmpty = String.IsNullOrEmpty(a);
|
||||
var bEmpty = String.IsNullOrEmpty(b);
|
||||
if (aEmpty && bEmpty)
|
||||
return 0;
|
||||
|
||||
if (aEmpty)
|
||||
return lower ? 1 : -1;
|
||||
if (bEmpty)
|
||||
return lower ? -1 : 1;
|
||||
|
||||
var aComps = a.Split('.');
|
||||
var bComps = b.Split('.');
|
||||
|
||||
var minLen = Math.Min(aComps.Length, bComps.Length);
|
||||
for (int i = 0; i < minLen; i++)
|
||||
{
|
||||
var ac = aComps[i];
|
||||
var bc = bComps[i];
|
||||
int anum, bnum;
|
||||
var isanum = Int32.TryParse(ac, out anum);
|
||||
var isbnum = Int32.TryParse(bc, out bnum);
|
||||
int r;
|
||||
if (isanum && isbnum)
|
||||
{
|
||||
r = anum.CompareTo(bnum);
|
||||
if (r != 0) return anum.CompareTo(bnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isanum)
|
||||
return -1;
|
||||
if (isbnum)
|
||||
return 1;
|
||||
r = String.CompareOrdinal(ac, bc);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return aComps.Length.CompareTo(bComps.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(obj, null))
|
||||
return false;
|
||||
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
|
||||
var other = (SemVersion)obj;
|
||||
|
||||
return this.Major == other.Major &&
|
||||
this.Minor == other.Minor &&
|
||||
this.Patch == other.Patch &&
|
||||
string.Equals(this.Prerelease, other.Prerelease, StringComparison.Ordinal) &&
|
||||
string.Equals(this.Build, other.Build, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
|
||||
/// </returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int result = this.Major.GetHashCode();
|
||||
result = result * 31 + this.Minor.GetHashCode();
|
||||
result = result * 31 + this.Patch.GetHashCode();
|
||||
result = result * 31 + this.Prerelease.GetHashCode();
|
||||
result = result * 31 + this.Build.GetHashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NETSTANDARD
|
||||
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null) throw new ArgumentNullException("info");
|
||||
info.AddValue("SemVersion", ToString());
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Implicit conversion from string to SemVersion.
|
||||
/// </summary>
|
||||
/// <param name="version">The semantic version.</param>
|
||||
/// <returns>The SemVersion object.</returns>
|
||||
public static implicit operator SemVersion(string version)
|
||||
{
|
||||
return SemVersion.Parse(version);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the equals operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator ==(SemVersion left, SemVersion right)
|
||||
{
|
||||
return SemVersion.Equals(left, right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the un-equal operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is not equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator !=(SemVersion left, SemVersion right)
|
||||
{
|
||||
return !SemVersion.Equals(left, right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the greater operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is greater than right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator >(SemVersion left, SemVersion right)
|
||||
{
|
||||
return SemVersion.Compare(left, right) > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the greater than or equal operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is greater than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator >=(SemVersion left, SemVersion right)
|
||||
{
|
||||
return left == right || left > right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the less operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is less than right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator <(SemVersion left, SemVersion right)
|
||||
{
|
||||
return SemVersion.Compare(left, right) < 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The override of the less than or equal operator.
|
||||
/// </summary>
|
||||
/// <param name="left">The left value.</param>
|
||||
/// <param name="right">The right value.</param>
|
||||
/// <returns>If left is less than or equal to right <c>true</c>, else <c>false</c>.</returns>
|
||||
public static bool operator <=(SemVersion left, SemVersion right)
|
||||
{
|
||||
return left == right || left < right;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5075cb5aa3254b099b11b2840d7cd46e
|
||||
timeCreated: 1503684176
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
namespace Semver
|
||||
{
|
||||
internal static class SemVersionExtension
|
||||
{
|
||||
public static string VersionOnly(this SemVersion version)
|
||||
{
|
||||
return "" + version.Major + "." + version.Minor + "." + version.Patch;
|
||||
}
|
||||
|
||||
public static string ShortVersion(this SemVersion version)
|
||||
{
|
||||
return version.Major + "." + version.Minor;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f17a0688211d476f8d8c9742bb9f992
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afd7697844f4142f9aa91471c1fba506
|
||||
folderAsset: yes
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1067213df0c64b319bc81e73be809b1a
|
||||
timeCreated: 1505249387
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
class ApplicationUtil
|
||||
{
|
||||
public static bool IsPreReleaseVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var lastToken = Application.unityVersion.Split('.').LastOrDefault();
|
||||
return lastToken.Contains("a") || lastToken.Contains("b");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ed48dcc992234c659018e00590315b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal class OperationSignal<T> where T: IBaseOperation
|
||||
{
|
||||
public event Action<T> OnOperation = delegate { };
|
||||
|
||||
public T Operation { get; set; }
|
||||
|
||||
public void SetOperation(T operation)
|
||||
{
|
||||
Operation = operation;
|
||||
OnOperation(operation);
|
||||
}
|
||||
|
||||
public void WhenOperation(Action<T> callback)
|
||||
{
|
||||
if (Operation != null)
|
||||
callback(Operation);
|
||||
OnOperation += callback;
|
||||
}
|
||||
|
||||
internal void ResetEvents()
|
||||
{
|
||||
OnOperation = delegate { };
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7da0c11c52b4044de81c175887699282
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class Resources
|
||||
{
|
||||
private static string TemplateRoot { get { return PackageManagerWindow.ResourcesPath + "Templates"; } }
|
||||
|
||||
private static string TemplatePath(string filename)
|
||||
{
|
||||
return string.Format("{0}/{1}", TemplateRoot, filename);
|
||||
}
|
||||
|
||||
public static VisualElement GetTemplate(string templateFilename)
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(TemplatePath(templateFilename)).CloneTree(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6a708dbb74414a6dbd60e07d9513c1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class ThreadedDelay
|
||||
{
|
||||
public int Length { get; set; } // In milliseconds
|
||||
public bool IsDone { get; private set; }
|
||||
|
||||
public ThreadedDelay(int length = 0)
|
||||
{
|
||||
Length = length;
|
||||
IsDone = false;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (Length <= 0)
|
||||
{
|
||||
IsDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
IsDone = false;
|
||||
|
||||
Thread newThread = new Thread(() =>
|
||||
{
|
||||
Thread.Sleep(Length);
|
||||
IsDone = true;
|
||||
});
|
||||
|
||||
newThread.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 490fe93dbc954e3ba3651b7f55eaba70
|
||||
timeCreated: 1505249395
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3385f7527e5be4c65b3a5294e8995ff8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal interface IAddOperation : IBaseOperation
|
||||
{
|
||||
event Action<PackageInfo> OnOperationSuccess;
|
||||
|
||||
PackageInfo PackageInfo { get; }
|
||||
|
||||
void AddPackageAsync(PackageInfo packageInfo, Action<PackageInfo> doneCallbackAction = null, Action<Error> errorCallbackAction = null);
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3dcbbc060dea46168ffc09a580836240
|
||||
timeCreated: 1504191596
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal interface IBaseOperation
|
||||
{
|
||||
event Action<Error> OnOperationError;
|
||||
event Action OnOperationFinalized;
|
||||
|
||||
bool IsCompleted { get; }
|
||||
|
||||
void Cancel();
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f1849b9179b464381598f68663790d3
|
||||
timeCreated: 1507041169
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal interface IListOperation : IBaseOperation
|
||||
{
|
||||
bool OfflineMode { get; set; }
|
||||
void GetPackageListAsync(Action<IEnumerable<PackageInfo>> doneCallbackAction, Action<Error> errorCallbackAction = null);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7e8a8fb69eacee439474914ea54bf9b
|
||||
timeCreated: 1502913188
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the Interface we will use to create the facade we need for testing.
|
||||
/// In the case of the Fake factory, we can create fake operations with doctored data we use for our tests.
|
||||
/// </summary>
|
||||
internal interface IOperationFactory
|
||||
{
|
||||
IListOperation CreateListOperation(bool offlineMode = false);
|
||||
ISearchOperation CreateSearchOperation();
|
||||
IAddOperation CreateAddOperation();
|
||||
IRemoveOperation CreateRemoveOperation();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a1161a2ab6569948a0aa7899197218c
|
||||
timeCreated: 1502915478
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal interface IRemoveOperation : IBaseOperation
|
||||
{
|
||||
event Action<PackageInfo> OnOperationSuccess;
|
||||
|
||||
void RemovePackageAsync(PackageInfo package, Action<PackageInfo> doneCallbackAction = null, Action<Error> errorCallbackAction = null);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54e5fc61925bc4ca3b2c1e82dfb35eb5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal interface ISearchOperation : IBaseOperation
|
||||
{
|
||||
void GetAllPackageAsync(Action<IEnumerable<PackageInfo>> doneCallbackAction = null, Action<Error> errorCallbackAction = null);
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85dba6b2d7204a7f9a1f976eb0a6b4d2
|
||||
timeCreated: 1508160206
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class OperationFactory
|
||||
{
|
||||
private static IOperationFactory _instance;
|
||||
|
||||
public static IOperationFactory Instance
|
||||
{
|
||||
get {
|
||||
if (_instance == null)
|
||||
_instance = new UpmOperationFactory ();
|
||||
return _instance;
|
||||
}
|
||||
internal set {
|
||||
_instance = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Reset()
|
||||
{
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ec5dc72125424af38a9bfaca532acc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e53bc96d2d054b8cbc811f0d73e761eb
|
||||
timeCreated: 1504191702
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
// History of a single package
|
||||
internal class Package : IEquatable<Package>
|
||||
{
|
||||
static public bool ShouldProposeLatestVersions
|
||||
{
|
||||
get
|
||||
{
|
||||
// Until we figure out a way to test this properly, alway show standard behavior
|
||||
// return InternalEditorUtility.IsUnityBeta() && !Unsupported.IsDeveloperMode();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// There can only be one package add/remove operation.
|
||||
private static IBaseOperation addRemoveOperationInstance;
|
||||
|
||||
public static bool AddRemoveOperationInProgress
|
||||
{
|
||||
get { return addRemoveOperationInstance != null && !addRemoveOperationInstance.IsCompleted; }
|
||||
}
|
||||
|
||||
internal const string packageManagerUIName = "com.unity.package-manager-ui";
|
||||
private readonly string packageName;
|
||||
private IEnumerable<PackageInfo> source;
|
||||
|
||||
internal Package(string packageName, IEnumerable<PackageInfo> infos)
|
||||
{
|
||||
if (string.IsNullOrEmpty(packageName))
|
||||
throw new ArgumentException("Cannot be empty or null", "packageName");
|
||||
|
||||
if (!infos.Any())
|
||||
throw new ArgumentException("Cannot be empty", "infos");
|
||||
|
||||
this.packageName = packageName;
|
||||
UpdateSource(infos);
|
||||
}
|
||||
|
||||
internal void UpdateSource(IEnumerable<PackageInfo> source)
|
||||
{
|
||||
this.source = source;
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
if (IsPackageManagerUI)
|
||||
this.source = this.source.Where(p => p != null && p.Version.Major >= 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
public PackageInfo Current { get { return Versions.FirstOrDefault(package => package.IsCurrent); } }
|
||||
|
||||
// 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)
|
||||
public PackageInfo LatestUpdate
|
||||
{
|
||||
get
|
||||
{
|
||||
// We want to show the absolute latest when in beta mode
|
||||
if (ShouldProposeLatestVersions)
|
||||
return Latest;
|
||||
|
||||
// Override with current when it's version locked
|
||||
var current = Current;
|
||||
if (current != null && current.IsVersionLocked)
|
||||
return current;
|
||||
|
||||
// Get all the candidates versions (verified, release, preview) that are newer than current
|
||||
var verified = Verified;
|
||||
var latestRelease = LatestRelease;
|
||||
var latestPreview = Versions.LastOrDefault(package => package.IsPreview);
|
||||
var candidates = new List<PackageInfo>
|
||||
{
|
||||
verified,
|
||||
latestRelease,
|
||||
latestPreview,
|
||||
}.Where(package => package != null && (current == null || current == package || current.Version < package.Version)).ToList();
|
||||
|
||||
if (candidates.Contains(verified))
|
||||
return verified;
|
||||
if ((current == null || !current.IsVerified ) && candidates.Contains(latestRelease))
|
||||
return latestRelease;
|
||||
if ((current == null || current.IsPreview) && candidates.Contains(latestPreview))
|
||||
return latestPreview;
|
||||
|
||||
// Show current if it exists, otherwise latest user visible, and then otherwise show the absolute latest
|
||||
return current ?? Latest;
|
||||
}
|
||||
}
|
||||
|
||||
public PackageInfo LatestPatch
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Current == null)
|
||||
return null;
|
||||
|
||||
// Get all version that have the same Major/Minor
|
||||
var versions = Versions.Where(package => package.Version.Major == Current.Version.Major && package.Version.Minor == Current.Version.Minor);
|
||||
|
||||
return versions.LastOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// This is the very latest version, including pre-releases (eg: 1.4.0-beta).
|
||||
internal PackageInfo Latest { get { return Versions.FirstOrDefault(package => package.IsLatest) ?? Versions.LastOrDefault(); } }
|
||||
|
||||
// Returns the current version if it exist, otherwise returns the latest user visible version.
|
||||
internal PackageInfo VersionToDisplay { get { return Current ?? LatestUpdate; } }
|
||||
|
||||
// Every version available for this package
|
||||
internal IEnumerable<PackageInfo> Versions { get { return source.OrderBy(package => package.Version); } }
|
||||
|
||||
// Every version that's not a pre-release (eg: not beta/alpha/preview).
|
||||
internal IEnumerable<PackageInfo> ReleaseVersions
|
||||
{
|
||||
get { return Versions.Where(package => !package.IsPreRelease); }
|
||||
}
|
||||
|
||||
internal PackageInfo LatestRelease { get {return ReleaseVersions.LastOrDefault();}}
|
||||
internal PackageInfo Verified { get {return Versions.FirstOrDefault(package => package.IsVerified);}}
|
||||
|
||||
internal bool IsAfterCurrentVersion(PackageInfo packageInfo) { return Current == null || (packageInfo != null && packageInfo.Version > Current.Version); }
|
||||
|
||||
internal bool IsBuiltIn {get { return Versions.Any() && Versions.First().IsBuiltIn; }}
|
||||
|
||||
public string Name { get { return packageName; } }
|
||||
|
||||
public bool IsPackageManagerUI
|
||||
{
|
||||
get { return Name == packageManagerUIName; }
|
||||
}
|
||||
|
||||
public bool Equals(Package other)
|
||||
{
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
return packageName == other.packageName;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return packageName.GetHashCode();
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
internal readonly OperationSignal<IAddOperation> AddSignal = new OperationSignal<IAddOperation>();
|
||||
|
||||
private Action OnAddOperationFinalizedEvent;
|
||||
|
||||
internal void Add(PackageInfo packageInfo)
|
||||
{
|
||||
if (packageInfo == Current || AddRemoveOperationInProgress)
|
||||
return;
|
||||
|
||||
var operation = OperationFactory.Instance.CreateAddOperation();
|
||||
addRemoveOperationInstance = operation;
|
||||
OnAddOperationFinalizedEvent = () =>
|
||||
{
|
||||
AddSignal.Operation = null;
|
||||
operation.OnOperationFinalized -= OnAddOperationFinalizedEvent;
|
||||
PackageCollection.Instance.FetchListOfflineCache(true);
|
||||
};
|
||||
|
||||
operation.OnOperationFinalized += OnAddOperationFinalizedEvent;
|
||||
|
||||
AddSignal.SetOperation(operation);
|
||||
operation.AddPackageAsync(packageInfo);
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
Add(Latest);
|
||||
}
|
||||
|
||||
internal static void AddFromLocalDisk(string path)
|
||||
{
|
||||
if (AddRemoveOperationInProgress)
|
||||
return;
|
||||
|
||||
var packageJson = PackageJsonHelper.Load(path);
|
||||
if (null == packageJson)
|
||||
{
|
||||
Debug.LogError(string.Format("Invalid package path: cannot find \"{0}\".", path));
|
||||
return;
|
||||
}
|
||||
|
||||
var operation = OperationFactory.Instance.CreateAddOperation();
|
||||
addRemoveOperationInstance = operation;
|
||||
operation.AddPackageAsync(packageJson.PackageInfo);
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
internal readonly OperationSignal<IRemoveOperation> RemoveSignal = new OperationSignal<IRemoveOperation>();
|
||||
|
||||
private Action OnRemoveOperationFinalizedEvent;
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
if (Current == null || AddRemoveOperationInProgress)
|
||||
return;
|
||||
|
||||
var operation = OperationFactory.Instance.CreateRemoveOperation();
|
||||
addRemoveOperationInstance = operation;
|
||||
OnRemoveOperationFinalizedEvent = () =>
|
||||
{
|
||||
RemoveSignal.Operation = null;
|
||||
operation.OnOperationFinalized -= OnRemoveOperationFinalizedEvent;
|
||||
PackageCollection.Instance.FetchListOfflineCache(true);
|
||||
};
|
||||
|
||||
operation.OnOperationFinalized += OnRemoveOperationFinalizedEvent;
|
||||
RemoveSignal.SetOperation(operation);
|
||||
|
||||
operation.RemovePackageAsync(Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f499e12eaeb145bf9022f581c0b7fa5b
|
||||
timeCreated: 1505740170
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class PackageAssetPostprocessor : AssetPostprocessor
|
||||
{
|
||||
static bool IsPackageJsonAsset(string path)
|
||||
{
|
||||
var pathComponents = (path ?? "").Split('/');
|
||||
return pathComponents.Length == 3 && pathComponents[0] == "Packages" && pathComponents[2] == "package.json";
|
||||
}
|
||||
|
||||
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
if (PackageCollection.Instance != null && (importedAssets.Any(IsPackageJsonAsset) || deletedAssets.Any(IsPackageJsonAsset) || movedAssets.Any(IsPackageJsonAsset)))
|
||||
{
|
||||
PackageCollection.Instance.FetchListOfflineCache(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63e8a6023745e4347bb661e87a9be1d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageCollection
|
||||
{
|
||||
private static PackageCollection instance = new PackageCollection();
|
||||
public static PackageCollection Instance { get { return instance; } }
|
||||
|
||||
public event Action<IEnumerable<Package>> OnPackagesChanged = delegate { };
|
||||
public event Action<PackageFilter> OnFilterChanged = delegate { };
|
||||
|
||||
private readonly Dictionary<string, Package> packages;
|
||||
|
||||
private PackageFilter filter;
|
||||
|
||||
private string selectedListPackage;
|
||||
private string selectedSearchPackage;
|
||||
|
||||
internal string lastUpdateTime;
|
||||
private List<PackageInfo> listPackagesOffline;
|
||||
private List<PackageInfo> listPackages;
|
||||
private List<PackageInfo> searchPackages;
|
||||
|
||||
private List<PackageError> packageErrors;
|
||||
|
||||
private int listPackagesVersion;
|
||||
private int listPackagesOfflineVersion;
|
||||
|
||||
private bool searchOperationOngoing;
|
||||
private bool listOperationOngoing;
|
||||
private bool listOperationOfflineOngoing;
|
||||
|
||||
private IListOperation listOperationOffline;
|
||||
private IListOperation listOperation;
|
||||
private ISearchOperation searchOperation;
|
||||
|
||||
public readonly OperationSignal<ISearchOperation> SearchSignal = new OperationSignal<ISearchOperation>();
|
||||
public readonly OperationSignal<IListOperation> ListSignal = new OperationSignal<IListOperation>();
|
||||
|
||||
public static void InitInstance(ref PackageCollection value)
|
||||
{
|
||||
if (value == null) // UI window opened
|
||||
{
|
||||
value = instance;
|
||||
|
||||
Instance.OnPackagesChanged = delegate { };
|
||||
Instance.OnFilterChanged = delegate { };
|
||||
Instance.SearchSignal.ResetEvents();
|
||||
Instance.ListSignal.ResetEvents();
|
||||
|
||||
Instance.FetchListOfflineCache(true);
|
||||
Instance.FetchListCache(true);
|
||||
Instance.FetchSearchCache(true);
|
||||
}
|
||||
else // Domain reload
|
||||
{
|
||||
instance = value;
|
||||
|
||||
Instance.RebuildPackageDictionary();
|
||||
|
||||
// Resume operations interrupted by domain reload
|
||||
Instance.FetchListOfflineCache(Instance.listOperationOfflineOngoing);
|
||||
Instance.FetchListCache(Instance.listOperationOngoing);
|
||||
Instance.FetchSearchCache(Instance.searchOperationOngoing);
|
||||
}
|
||||
}
|
||||
|
||||
public PackageFilter Filter
|
||||
{
|
||||
get { return filter; }
|
||||
|
||||
// For public usage, use SetFilter() instead
|
||||
private set
|
||||
{
|
||||
var changed = value != filter;
|
||||
filter = value;
|
||||
|
||||
if (changed)
|
||||
OnFilterChanged(filter);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PackageInfo> LatestListPackages
|
||||
{
|
||||
get { return listPackagesVersion > listPackagesOfflineVersion? listPackages : listPackagesOffline; }
|
||||
}
|
||||
|
||||
public List<PackageInfo> LatestSearchPackages { get { return searchPackages; } }
|
||||
|
||||
public string SelectedPackage
|
||||
{
|
||||
get { return PackageFilter.All == Filter ? selectedSearchPackage : selectedListPackage; }
|
||||
set
|
||||
{
|
||||
if (PackageFilter.All == Filter)
|
||||
selectedSearchPackage = value;
|
||||
else
|
||||
selectedListPackage = value;
|
||||
}
|
||||
}
|
||||
|
||||
private PackageCollection()
|
||||
{
|
||||
packages = new Dictionary<string, Package>();
|
||||
|
||||
listPackagesOffline = new List<PackageInfo>();
|
||||
listPackages = new List<PackageInfo>();
|
||||
searchPackages = new List<PackageInfo>();
|
||||
|
||||
packageErrors = new List<PackageError>();
|
||||
|
||||
listPackagesVersion = 0;
|
||||
listPackagesOfflineVersion = 0;
|
||||
|
||||
searchOperationOngoing = false;
|
||||
listOperationOngoing = false;
|
||||
listOperationOfflineOngoing = false;
|
||||
|
||||
Filter = PackageFilter.All;
|
||||
}
|
||||
|
||||
public bool SetFilter(PackageFilter value, bool refresh = true)
|
||||
{
|
||||
if (value == Filter)
|
||||
return false;
|
||||
|
||||
Filter = value;
|
||||
if (refresh)
|
||||
{
|
||||
UpdatePackageCollection();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdatePackageCollection(bool rebuildDictionary = false)
|
||||
{
|
||||
if (rebuildDictionary)
|
||||
{
|
||||
lastUpdateTime = DateTime.Now.ToString("HH:mm");
|
||||
RebuildPackageDictionary();
|
||||
}
|
||||
if (packages.Any())
|
||||
OnPackagesChanged(OrderedPackages());
|
||||
}
|
||||
|
||||
internal void FetchListOfflineCache(bool forceRefetch = false)
|
||||
{
|
||||
if (!forceRefetch && (listOperationOfflineOngoing || listPackagesOffline.Any())) return;
|
||||
if (listOperationOffline != null)
|
||||
listOperationOffline.Cancel();
|
||||
listOperationOfflineOngoing = true;
|
||||
listOperationOffline = OperationFactory.Instance.CreateListOperation(true);
|
||||
listOperationOffline.OnOperationFinalized += () =>
|
||||
{
|
||||
listOperationOfflineOngoing = false;
|
||||
UpdatePackageCollection(true);
|
||||
};
|
||||
listOperationOffline.GetPackageListAsync(
|
||||
infos =>
|
||||
{
|
||||
var version = listPackagesVersion;
|
||||
UpdateListPackageInfosOffline(infos, version);
|
||||
},
|
||||
error => { Debug.LogError("Error fetching package list (offline mode)."); });
|
||||
}
|
||||
|
||||
internal void FetchListCache(bool forceRefetch = false)
|
||||
{
|
||||
if (!forceRefetch && (listOperationOngoing || listPackages.Any())) return;
|
||||
if (listOperation != null)
|
||||
listOperation.Cancel();
|
||||
listOperationOngoing = true;
|
||||
listOperation = OperationFactory.Instance.CreateListOperation();
|
||||
listOperation.OnOperationFinalized += () =>
|
||||
{
|
||||
listOperationOngoing = false;
|
||||
UpdatePackageCollection(true);
|
||||
};
|
||||
listOperation.GetPackageListAsync(UpdateListPackageInfos,
|
||||
error => { Debug.LogError("Error fetching package list."); });
|
||||
ListSignal.SetOperation(listOperation);
|
||||
}
|
||||
|
||||
internal void FetchSearchCache(bool forceRefetch = false)
|
||||
{
|
||||
if (!forceRefetch && (searchOperationOngoing || searchPackages.Any())) return;
|
||||
if (searchOperation != null)
|
||||
searchOperation.Cancel();
|
||||
searchOperationOngoing = true;
|
||||
searchOperation = OperationFactory.Instance.CreateSearchOperation();
|
||||
searchOperation.OnOperationFinalized += () =>
|
||||
{
|
||||
searchOperationOngoing = false;
|
||||
UpdatePackageCollection(true);
|
||||
};
|
||||
searchOperation.GetAllPackageAsync(UpdateSearchPackageInfos,
|
||||
error => { Debug.LogError("Error searching packages online."); });
|
||||
SearchSignal.SetOperation(searchOperation);
|
||||
}
|
||||
|
||||
private void UpdateListPackageInfosOffline(IEnumerable<PackageInfo> newInfos, int version)
|
||||
{
|
||||
listPackagesOfflineVersion = version;
|
||||
listPackagesOffline = newInfos.Where(p => p.IsUserVisible).ToList();
|
||||
}
|
||||
|
||||
private void UpdateListPackageInfos(IEnumerable<PackageInfo> newInfos)
|
||||
{
|
||||
// Each time we fetch list packages, the cache for offline mode will be updated
|
||||
// We keep track of the list packages version so that we know which version of cache
|
||||
// we are getting with the offline fetch operation.
|
||||
listPackagesVersion++;
|
||||
listPackages = newInfos.Where(p => p.IsUserVisible).ToList();
|
||||
listPackagesOffline = listPackages;
|
||||
}
|
||||
|
||||
private void UpdateSearchPackageInfos(IEnumerable<PackageInfo> newInfos)
|
||||
{
|
||||
searchPackages = newInfos.Where(p => p.IsUserVisible).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<Package> OrderedPackages()
|
||||
{
|
||||
return packages.Values.OrderBy(pkg => pkg.Versions.LastOrDefault() == null ? pkg.Name : pkg.Versions.Last().DisplayName).AsEnumerable();
|
||||
}
|
||||
|
||||
public Package GetPackageByName(string name)
|
||||
{
|
||||
Package package;
|
||||
packages.TryGetValue(name, out package);
|
||||
return package;
|
||||
}
|
||||
|
||||
public Error GetPackageError(Package package)
|
||||
{
|
||||
if (null == package) return null;
|
||||
var firstMatchingError = packageErrors.FirstOrDefault(p => p.PackageName == package.Name);
|
||||
return firstMatchingError != null ? firstMatchingError.Error : null;
|
||||
}
|
||||
|
||||
public void AddPackageError(Package package, Error error)
|
||||
{
|
||||
if (null == package || null == error) return;
|
||||
packageErrors.Add(new PackageError(package.Name, error));
|
||||
}
|
||||
|
||||
public void RemovePackageErrors(Package package)
|
||||
{
|
||||
if (null == package) return;
|
||||
packageErrors.RemoveAll(p => p.PackageName == package.Name);
|
||||
}
|
||||
|
||||
private void RebuildPackageDictionary()
|
||||
{
|
||||
// Merge list & search packages
|
||||
var allPackageInfos = new List<PackageInfo>(LatestListPackages);
|
||||
var installedPackageIds = new HashSet<string>(allPackageInfos.Select(p => p.PackageId));
|
||||
allPackageInfos.AddRange(searchPackages.Where(p => !installedPackageIds.Contains(p.PackageId)));
|
||||
|
||||
if (!PackageManagerPrefs.ShowPreviewPackages)
|
||||
{
|
||||
allPackageInfos = allPackageInfos.Where(p => !p.IsPreRelease || installedPackageIds.Contains(p.PackageId)).ToList();
|
||||
}
|
||||
|
||||
// Rebuild packages dictionary
|
||||
packages.Clear();
|
||||
foreach (var p in allPackageInfos)
|
||||
{
|
||||
var packageName = p.Name;
|
||||
if (packages.ContainsKey(packageName))
|
||||
continue;
|
||||
|
||||
var packageQuery = from pkg in allPackageInfos where pkg.Name == packageName select pkg;
|
||||
var package = new Package(packageName, packageQuery);
|
||||
packages[packageName] = package;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61d72cb49da3040d5ade3edfd6eccfc1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageError
|
||||
{
|
||||
public string PackageName;
|
||||
public Error Error;
|
||||
|
||||
public PackageError(string packageName, Error error)
|
||||
{
|
||||
PackageName = packageName;
|
||||
Error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7c10e584b708734ba6141e7d4797931
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal enum PackageFilter
|
||||
{
|
||||
None,
|
||||
All,
|
||||
Local,
|
||||
Modules
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03ffb9844f8d40e8a2f59dd2aff561eb
|
||||
timeCreated: 1508251051
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal enum PackageGroupOrigins
|
||||
{
|
||||
Packages,
|
||||
BuiltInPackages
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e372f1bbea04aa9bd68055d4105bd84
|
||||
timeCreated: 1508855779
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Semver;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageInfo : IEquatable<PackageInfo>
|
||||
{
|
||||
// Module package.json files contain a documentation url embedded in the description.
|
||||
// We parse that to have the "View Documentation" button direct to it, instead of showing
|
||||
// the link in the description text.
|
||||
private const string builtinPackageDocsUrlKey = "Scripting API: ";
|
||||
|
||||
public string Name;
|
||||
public string DisplayName;
|
||||
private string _PackageId;
|
||||
public SemVersion Version;
|
||||
public string Description;
|
||||
public string Category;
|
||||
public PackageState State;
|
||||
public bool IsCurrent;
|
||||
public bool IsLatest;
|
||||
public string Group;
|
||||
public PackageSource Origin;
|
||||
public List<Error> Errors;
|
||||
public bool IsVerified;
|
||||
public string Author;
|
||||
|
||||
public PackageManager.PackageInfo Info { get; set; }
|
||||
|
||||
public string PackageId {
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_PackageId ))
|
||||
return _PackageId;
|
||||
return string.Format("{0}@{1}", Name.ToLower(), Version);
|
||||
}
|
||||
set
|
||||
{
|
||||
_PackageId = value;
|
||||
}
|
||||
}
|
||||
|
||||
// This will always be <name>@<version>, even for an embedded package.
|
||||
public string VersionId { get { return string.Format("{0}@{1}", Name.ToLower(), Version); } }
|
||||
public string ShortVersionId { get { return string.Format("{0}@{1}", Name.ToLower(), Version.ShortVersion()); } }
|
||||
|
||||
public string BuiltInDescription { get {
|
||||
if (IsBuiltIn)
|
||||
return string.Format("This built in package controls the presence of the {0} module.", DisplayName);
|
||||
else
|
||||
return Description.Split(new[] {builtinPackageDocsUrlKey}, StringSplitOptions.None)[0];
|
||||
} }
|
||||
|
||||
private static Version ParseShortVersion(string shortVersionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var versionToken = shortVersionId.Split('@')[1];
|
||||
return new Version(versionToken);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Keep default version 0.0 on exception
|
||||
return new Version();
|
||||
}
|
||||
}
|
||||
|
||||
// Method content must be matched in package manager UI
|
||||
public static string GetPackageUrlRedirect(string packageName, string shortVersionId)
|
||||
{
|
||||
var redirectUrl = "";
|
||||
if (packageName == "com.unity.ads")
|
||||
redirectUrl = "https://docs.unity3d.com/Manual/UnityAds.html";
|
||||
else if (packageName == "com.unity.analytics")
|
||||
{
|
||||
if (ParseShortVersion(shortVersionId) < new Version(3, 2))
|
||||
redirectUrl = "https://docs.unity3d.com/Manual/UnityAnalytics.html";
|
||||
}
|
||||
else if (packageName == "com.unity.purchasing")
|
||||
redirectUrl = "https://docs.unity3d.com/Manual/UnityIAP.html";
|
||||
else if (packageName == "com.unity.standardevents")
|
||||
redirectUrl = "https://docs.unity3d.com/Manual/UnityAnalyticsStandardEvents.html";
|
||||
else if (packageName == "com.unity.xiaomi")
|
||||
redirectUrl = "https://unity3d.com/cn/partners/xiaomi/guide";
|
||||
else if (packageName == "com.unity.shadergraph")
|
||||
{
|
||||
if (ParseShortVersion(shortVersionId) < new Version(4, 1))
|
||||
redirectUrl = "https://github.com/Unity-Technologies/ShaderGraph/wiki";
|
||||
}
|
||||
|
||||
return redirectUrl;
|
||||
}
|
||||
|
||||
public bool RedirectsToManual(PackageInfo packageInfo)
|
||||
{
|
||||
return !string.IsNullOrEmpty(GetPackageUrlRedirect(packageInfo.Name, packageInfo.ShortVersionId));
|
||||
}
|
||||
|
||||
public bool HasChangelog(PackageInfo packageInfo)
|
||||
{
|
||||
// Packages with no docs have no third party notice
|
||||
return !RedirectsToManual(packageInfo);
|
||||
}
|
||||
|
||||
public string GetDocumentationUrl()
|
||||
{
|
||||
if (IsBuiltIn)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
var split = Description.Split(new[] {builtinPackageDocsUrlKey}, StringSplitOptions.None);
|
||||
if (split.Length > 1)
|
||||
return split[1];
|
||||
}
|
||||
}
|
||||
return string.Format("http://docs.unity3d.com/Packages/{0}/index.html", ShortVersionId);
|
||||
}
|
||||
|
||||
public string GetChangelogUrl()
|
||||
{
|
||||
return string.Format("http://docs.unity3d.com/Packages/{0}/changelog/CHANGELOG.html", ShortVersionId);
|
||||
}
|
||||
|
||||
public string GetLicensesUrl()
|
||||
{
|
||||
var url = string.Format("http://docs.unity3d.com/Packages/{0}/license/index.html", ShortVersionId);
|
||||
if (RedirectsToManual(this))
|
||||
url = "https://unity3d.com/legal/licenses/Unity_Companion_License";
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
public bool Equals(PackageInfo other)
|
||||
{
|
||||
if (other == null)
|
||||
return false;
|
||||
if (other == this)
|
||||
return true;
|
||||
|
||||
return Name == other.Name && Version == other.Version;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return PackageId.GetHashCode();
|
||||
}
|
||||
|
||||
public bool HasVersionTag(string tag)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Version.Prerelease))
|
||||
return false;
|
||||
|
||||
return String.Equals(Version.Prerelease.Split('.').First(), tag, StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public bool HasVersionTag(PackageTag tag)
|
||||
{
|
||||
return HasVersionTag(tag.ToString());
|
||||
}
|
||||
|
||||
// Is it a pre-release (alpha/beta/experimental/preview)?
|
||||
// Current logic is any tag is considered pre-release, except recommended
|
||||
public bool IsPreRelease
|
||||
{
|
||||
get { return !string.IsNullOrEmpty(Version.Prerelease) || Version.Major == 0; }
|
||||
}
|
||||
|
||||
public bool IsPreview
|
||||
{
|
||||
get { return HasVersionTag(PackageTag.preview) || Version.Major == 0; }
|
||||
}
|
||||
|
||||
// A version is user visible if it has a supported tag (or no tag at all)
|
||||
public bool IsUserVisible
|
||||
{
|
||||
get { return IsCurrent || string.IsNullOrEmpty(Version.Prerelease) || HasVersionTag(PackageTag.preview) || IsVerified; }
|
||||
}
|
||||
|
||||
public bool IsInDevelopment { get { return Origin == PackageSource.Embedded; } }
|
||||
public bool IsLocal { get { return Origin == PackageSource.Local; } }
|
||||
public bool IsBuiltIn { get { return Origin == PackageSource.BuiltIn; } }
|
||||
|
||||
public string VersionWithoutTag { get { return Version.VersionOnly(); } }
|
||||
|
||||
public bool IsVersionLocked
|
||||
{
|
||||
get { return Origin == PackageSource.Embedded || Origin == PackageSource.Git || Origin == PackageSource.BuiltIn; }
|
||||
}
|
||||
|
||||
public bool CanBeRemoved
|
||||
{
|
||||
get { return Origin == PackageSource.Registry || Origin == PackageSource.BuiltIn || Origin == PackageSource.Local; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9f324f08cd904ec986357c98dd9eaa6
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class PackageInfoListExtensions
|
||||
{
|
||||
public static IEnumerable<PackageInfo> ByName(this IEnumerable<PackageInfo> list, string name)
|
||||
{
|
||||
return from package in list where package.Name == name select package;
|
||||
}
|
||||
|
||||
public static void SetCurrent(this IEnumerable<PackageInfo> list, bool current = true)
|
||||
{
|
||||
foreach (var package in list)
|
||||
{
|
||||
package.IsCurrent = current;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLatest(this IEnumerable<PackageInfo> list, bool latest = true)
|
||||
{
|
||||
foreach (var package in list)
|
||||
{
|
||||
package.IsLatest = latest;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetGroup(this IEnumerable<PackageInfo> list, string group)
|
||||
{
|
||||
foreach (var package in list)
|
||||
{
|
||||
package.Group = group;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7b89acd74e047778b42209a7a733d39
|
||||
timeCreated: 1505740214
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class PackageJsonHelper
|
||||
{
|
||||
[SerializeField]
|
||||
private string name = string.Empty;
|
||||
|
||||
private string path = string.Empty;
|
||||
|
||||
public static string GetPackagePath(string jsonPath)
|
||||
{
|
||||
return Path.GetDirectoryName(jsonPath).Replace("\\", "/");
|
||||
}
|
||||
|
||||
public static PackageJsonHelper Load(string path)
|
||||
{
|
||||
// If the path is a directory, find the `package.json` file path
|
||||
var jsonPath = Directory.Exists(path) ? Path.Combine(path, "package.json") : path;
|
||||
if (!File.Exists(jsonPath))
|
||||
return null;
|
||||
var packageJson = JsonUtility.FromJson<PackageJsonHelper>(File.ReadAllText(jsonPath));
|
||||
packageJson.path = GetPackagePath(jsonPath);
|
||||
return string.IsNullOrEmpty(packageJson.name) ? null : packageJson;
|
||||
}
|
||||
|
||||
public PackageInfo PackageInfo
|
||||
{
|
||||
get { return new PackageInfo {PackageId = string.Format("{0}@file:{1}", name, path)}; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9374526debed24449d75f8cc6d0103f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class PackageListExtensions
|
||||
{
|
||||
public static IEnumerable<Package> Current(this IEnumerable<Package> list)
|
||||
{
|
||||
return (from package in list where package.Current != null select package);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a74094b34f74992a5121c0586ccf6ea
|
||||
timeCreated: 1506458921
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal enum PackageOrigin
|
||||
{
|
||||
Unknown,
|
||||
Builtin,
|
||||
Registry
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a98bc92072da64d49a393088e55ce2a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
[Serializable]
|
||||
internal class PackageSearchFilter
|
||||
{
|
||||
private static PackageSearchFilter instance = new PackageSearchFilter();
|
||||
public static PackageSearchFilter Instance { get { return instance; } }
|
||||
|
||||
public string SearchText { get; set; }
|
||||
|
||||
public static void InitInstance(ref PackageSearchFilter value)
|
||||
{
|
||||
if (value == null) // UI window opened
|
||||
value = instance;
|
||||
else // Domain reload
|
||||
instance = value;
|
||||
}
|
||||
|
||||
public void ResetSearch()
|
||||
{
|
||||
SearchText = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d65a43500ec84d9186cb6d9ab681277
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal enum PackageState {
|
||||
UpToDate,
|
||||
Outdated,
|
||||
InProgress,
|
||||
Error
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a822dba3d5c4c85b150866e5442a5ec
|
||||
timeCreated: 1505740158
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal enum PackageTag
|
||||
{
|
||||
preview,
|
||||
verified,
|
||||
inDevelopment,
|
||||
local
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a3f4f8c4e2df41108f55825c24ff694
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 669717f3193a457b9bad9665ebcae836
|
||||
timeCreated: 1504191654
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using System.Linq;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class UpmAddOperation : UpmBaseOperation, IAddOperation
|
||||
{
|
||||
public PackageInfo PackageInfo { get; protected set; }
|
||||
|
||||
public event Action<PackageInfo> OnOperationSuccess = delegate { };
|
||||
|
||||
public void AddPackageAsync(PackageInfo packageInfo, Action<PackageInfo> doneCallbackAction = null, Action<Error> errorCallbackAction = null)
|
||||
{
|
||||
PackageInfo = packageInfo;
|
||||
OnOperationError += errorCallbackAction;
|
||||
OnOperationSuccess += doneCallbackAction;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
protected override Request CreateRequest()
|
||||
{
|
||||
return Client.Add(PackageInfo.PackageId);
|
||||
}
|
||||
|
||||
protected override void ProcessData()
|
||||
{
|
||||
var request = CurrentRequest as AddRequest;
|
||||
var package = FromUpmPackageInfo(request.Result).First();
|
||||
OnOperationSuccess(package);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f091dea68a1452cb6c04a6dfa73d5f5
|
||||
timeCreated: 1504190581
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Semver;
|
||||
using UnityEngine;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal abstract class UpmBaseOperation : IBaseOperation
|
||||
{
|
||||
public static string GroupName(PackageSource origin)
|
||||
{
|
||||
var group = PackageGroupOrigins.Packages.ToString();
|
||||
if (origin == PackageSource.BuiltIn)
|
||||
group = PackageGroupOrigins.BuiltInPackages.ToString();
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
protected static IEnumerable<PackageInfo> FromUpmPackageInfo(PackageManager.PackageInfo info, bool isCurrent=true)
|
||||
{
|
||||
var packages = new List<PackageInfo>();
|
||||
var displayName = info.displayName;
|
||||
if (string.IsNullOrEmpty(displayName))
|
||||
{
|
||||
displayName = info.name.Replace("com.unity.modules.", "");
|
||||
displayName = displayName.Replace("com.unity.", "");
|
||||
displayName = new CultureInfo("en-US").TextInfo.ToTitleCase(displayName);
|
||||
}
|
||||
|
||||
string author = info.author.name;
|
||||
if (string.IsNullOrEmpty(info.author.name) && info.name.StartsWith("com.unity."))
|
||||
author = "Unity Technologies Inc.";
|
||||
|
||||
var lastCompatible = info.versions.latestCompatible;
|
||||
var versions = new List<string>();
|
||||
versions.AddRange(info.versions.compatible);
|
||||
if (versions.FindIndex(version => version == info.version) == -1)
|
||||
{
|
||||
versions.Add(info.version);
|
||||
|
||||
versions.Sort((left, right) =>
|
||||
{
|
||||
if (left == null || right == null) return 0;
|
||||
|
||||
SemVersion leftVersion = left;
|
||||
SemVersion righVersion = right;
|
||||
return leftVersion.CompareByPrecedence(righVersion);
|
||||
});
|
||||
|
||||
SemVersion packageVersion = info.version;
|
||||
if (!string.IsNullOrEmpty(lastCompatible))
|
||||
{
|
||||
SemVersion lastCompatibleVersion =
|
||||
string.IsNullOrEmpty(lastCompatible) ? (SemVersion) null : lastCompatible;
|
||||
if (packageVersion != null && string.IsNullOrEmpty(packageVersion.Prerelease) &&
|
||||
packageVersion.CompareByPrecedence(lastCompatibleVersion) > 0)
|
||||
lastCompatible = info.version;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packageVersion != null && string.IsNullOrEmpty(packageVersion.Prerelease))
|
||||
lastCompatible = info.version;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var version in versions)
|
||||
{
|
||||
var isVersionCurrent = version == info.version && isCurrent;
|
||||
var isBuiltIn = info.source == PackageSource.BuiltIn;
|
||||
var isVerified = string.IsNullOrEmpty(SemVersion.Parse(version).Prerelease) && version == info.versions.recommended;
|
||||
var state = (isBuiltIn || info.version == lastCompatible || !isCurrent ) ? PackageState.UpToDate : PackageState.Outdated;
|
||||
|
||||
// Happens mostly when using a package that hasn't been in production yet.
|
||||
if (info.versions.all.Length <= 0)
|
||||
state = PackageState.UpToDate;
|
||||
|
||||
if (info.errors.Length > 0)
|
||||
state = PackageState.Error;
|
||||
|
||||
var packageInfo = new PackageInfo
|
||||
{
|
||||
Name = info.name,
|
||||
DisplayName = displayName,
|
||||
PackageId = version == info.version ? info.packageId : null,
|
||||
Version = version,
|
||||
Description = info.description,
|
||||
Category = info.category,
|
||||
IsCurrent = isVersionCurrent,
|
||||
IsLatest = version == lastCompatible,
|
||||
IsVerified = isVerified,
|
||||
Errors = info.errors.ToList(),
|
||||
Group = GroupName(info.source),
|
||||
State = state,
|
||||
Origin = isBuiltIn || isVersionCurrent ? info.source : PackageSource.Registry,
|
||||
Author = author,
|
||||
Info = info
|
||||
};
|
||||
|
||||
packages.Add(packageInfo);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
public static event Action<UpmBaseOperation> OnOperationStart = delegate { };
|
||||
|
||||
public event Action<Error> OnOperationError = delegate { };
|
||||
public event Action OnOperationFinalized = delegate { };
|
||||
|
||||
public Error ForceError { get; set; } // Allow external component to force an error on the requests (eg: testing)
|
||||
public Error Error { get; protected set; } // Keep last error
|
||||
|
||||
public bool IsCompleted { get; private set; }
|
||||
|
||||
protected abstract Request CreateRequest();
|
||||
|
||||
[SerializeField]
|
||||
protected Request CurrentRequest;
|
||||
public readonly ThreadedDelay Delay = new ThreadedDelay();
|
||||
|
||||
protected abstract void ProcessData();
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
Error = null;
|
||||
OnOperationStart(this);
|
||||
|
||||
Delay.Start();
|
||||
|
||||
if (TryForcedError())
|
||||
return;
|
||||
|
||||
EditorApplication.update += Progress;
|
||||
}
|
||||
|
||||
// Common progress code for all classes
|
||||
private void Progress()
|
||||
{
|
||||
if (!Delay.IsDone)
|
||||
return;
|
||||
|
||||
// Create the request after the delay
|
||||
if (CurrentRequest == null)
|
||||
{
|
||||
CurrentRequest = CreateRequest();
|
||||
}
|
||||
|
||||
// Since CurrentRequest's error property is private, we need to simulate
|
||||
// an error instead of just setting it.
|
||||
if (TryForcedError())
|
||||
return;
|
||||
|
||||
if (CurrentRequest.IsCompleted)
|
||||
{
|
||||
if (CurrentRequest.Status == StatusCode.Success)
|
||||
OnDone();
|
||||
else if (CurrentRequest.Status >= StatusCode.Failure)
|
||||
OnError(CurrentRequest.Error);
|
||||
else
|
||||
Debug.LogError("Unsupported progress state " + CurrentRequest.Status);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnError(Error error)
|
||||
{
|
||||
try
|
||||
{
|
||||
Error = error;
|
||||
|
||||
var message = "Cannot perform upm operation.";
|
||||
if (error != null)
|
||||
message = "Cannot perform upm operation: " + Error.message + " [" + Error.errorCode + "]";
|
||||
|
||||
Debug.LogError(message);
|
||||
|
||||
OnOperationError(Error);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogError("Package Manager Window had an error while reporting an error in an operation: " + exception);
|
||||
}
|
||||
|
||||
FinalizeOperation();
|
||||
}
|
||||
|
||||
private void OnDone()
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessData();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Debug.LogError("Package Manager Window had an error while completing an operation: " + error);
|
||||
}
|
||||
|
||||
FinalizeOperation();
|
||||
}
|
||||
|
||||
private void FinalizeOperation()
|
||||
{
|
||||
EditorApplication.update -= Progress;
|
||||
OnOperationFinalized();
|
||||
IsCompleted = true;
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
EditorApplication.update -= Progress;
|
||||
OnOperationError = delegate { };
|
||||
OnOperationFinalized = delegate { };
|
||||
IsCompleted = true;
|
||||
}
|
||||
|
||||
private bool TryForcedError()
|
||||
{
|
||||
if (ForceError != null)
|
||||
{
|
||||
OnError(ForceError);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e830e2dbc3315b4b97cd5311a54e4fe
|
||||
timeCreated: 1502918867
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class UpmListOperation : UpmBaseOperation, IListOperation
|
||||
{
|
||||
[SerializeField]
|
||||
private Action<IEnumerable<PackageInfo>> _doneCallbackAction;
|
||||
|
||||
public UpmListOperation(bool offlineMode) : base()
|
||||
{
|
||||
OfflineMode = offlineMode;
|
||||
}
|
||||
|
||||
public bool OfflineMode { get; set; }
|
||||
|
||||
public void GetPackageListAsync(Action<IEnumerable<PackageInfo>> doneCallbackAction, Action<Error> errorCallbackAction = null)
|
||||
{
|
||||
this._doneCallbackAction = doneCallbackAction;
|
||||
OnOperationError += errorCallbackAction;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
protected override Request CreateRequest()
|
||||
{
|
||||
return Client.List(OfflineMode);
|
||||
}
|
||||
|
||||
protected override void ProcessData()
|
||||
{
|
||||
var request = CurrentRequest as ListRequest;
|
||||
var packages = new List<PackageInfo>();
|
||||
foreach (var upmPackage in request.Result)
|
||||
{
|
||||
var packageInfos = FromUpmPackageInfo(upmPackage);
|
||||
packages.AddRange(packageInfos);
|
||||
}
|
||||
|
||||
_doneCallbackAction(packages);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a2c874c382e2419184b302497279dd9
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class UpmOperationFactory : IOperationFactory
|
||||
{
|
||||
public IListOperation CreateListOperation(bool offlineMode = false)
|
||||
{
|
||||
return new UpmListOperation(offlineMode);
|
||||
}
|
||||
|
||||
public ISearchOperation CreateSearchOperation()
|
||||
{
|
||||
return new UpmSearchOperation();
|
||||
}
|
||||
|
||||
public IAddOperation CreateAddOperation()
|
||||
{
|
||||
return new UpmAddOperation();
|
||||
}
|
||||
|
||||
public IRemoveOperation CreateRemoveOperation()
|
||||
{
|
||||
return new UpmRemoveOperation();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6925bb38494e6a43ba0921e65e424fe
|
||||
timeCreated: 1502915478
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class UpmRemoveOperation : UpmBaseOperation, IRemoveOperation
|
||||
{
|
||||
[SerializeField]
|
||||
private PackageInfo _package;
|
||||
|
||||
public event Action<PackageInfo> OnOperationSuccess = delegate { };
|
||||
|
||||
public void RemovePackageAsync(PackageInfo package, Action<PackageInfo> doneCallbackAction = null, Action<Error> errorCallbackAction = null)
|
||||
{
|
||||
_package = package;
|
||||
OnOperationError += errorCallbackAction;
|
||||
OnOperationSuccess += doneCallbackAction;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
protected override Request CreateRequest()
|
||||
{
|
||||
return Client.Remove(_package.Name);
|
||||
}
|
||||
|
||||
protected override void ProcessData()
|
||||
{
|
||||
OnOperationSuccess(_package);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5a61f8cc87394b28aec6b88b4083217
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class UpmSearchOperation : UpmBaseOperation, ISearchOperation
|
||||
{
|
||||
[SerializeField]
|
||||
private Action<IEnumerable<PackageInfo>> _doneCallbackAction;
|
||||
|
||||
public void GetAllPackageAsync(Action<IEnumerable<PackageInfo>> doneCallbackAction = null, Action<Error> errorCallbackAction = null)
|
||||
{
|
||||
_doneCallbackAction = doneCallbackAction;
|
||||
OnOperationError += errorCallbackAction;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
protected override Request CreateRequest()
|
||||
{
|
||||
return Client.SearchAll();
|
||||
}
|
||||
|
||||
protected override void ProcessData()
|
||||
{
|
||||
var request = CurrentRequest as SearchRequest;
|
||||
var packages = new List<PackageInfo>();
|
||||
foreach (var upmPackage in request.Result)
|
||||
{
|
||||
var packageInfos = FromUpmPackageInfo(upmPackage, false);
|
||||
packages.AddRange(packageInfos);
|
||||
}
|
||||
_doneCallbackAction(packages);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef5a2781610c4f12a79939f717f789cf
|
||||
timeCreated: 1508160183
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 301fbaa0e62e44fd2a7383bd338a2898
|
||||
folderAsset: yes
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42064bc130be4c44b288d249a44b356f
|
||||
timeCreated: 1504191962
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class AlertFactory : UxmlFactory<Alert>
|
||||
{
|
||||
protected override Alert DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new Alert();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class Alert : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<Alert> { }
|
||||
#endif
|
||||
|
||||
private const string TemplatePath = PackageManagerWindow.ResourcesPath + "Templates/Alert.uxml";
|
||||
private readonly VisualElement root;
|
||||
private const float originalPositionRight = 5.0f;
|
||||
private const float positionRightWithScroll = 12.0f;
|
||||
|
||||
public Action OnCloseError;
|
||||
|
||||
public Alert()
|
||||
{
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
|
||||
root = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(TemplatePath).CloneTree(null);
|
||||
Add(root);
|
||||
root.StretchToParentSize();
|
||||
|
||||
CloseButton.clickable.clicked += () =>
|
||||
{
|
||||
if (null != OnCloseError)
|
||||
OnCloseError();
|
||||
ClearError();
|
||||
};
|
||||
}
|
||||
|
||||
public void SetError(Error error)
|
||||
{
|
||||
var message = "An error occured.";
|
||||
if (error != null)
|
||||
message = error.message ?? string.Format("An error occurred ({0})", error.errorCode.ToString());
|
||||
|
||||
AlertMessage.text = message;
|
||||
UIUtils.SetElementDisplay(this, true);
|
||||
}
|
||||
|
||||
public void ClearError()
|
||||
{
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
AdjustSize(false);
|
||||
AlertMessage.text = "";
|
||||
OnCloseError = null;
|
||||
}
|
||||
|
||||
public void AdjustSize(bool verticalScrollerVisible)
|
||||
{
|
||||
if (verticalScrollerVisible)
|
||||
style.positionRight = originalPositionRight + positionRightWithScroll;
|
||||
else
|
||||
style.positionRight = originalPositionRight;
|
||||
}
|
||||
|
||||
private Label AlertMessage { get { return root.Q<Label>("alertMessage"); } }
|
||||
private Button CloseButton { get { return root.Q<Button>("close"); } }
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b274f3d1ea05d4bd8a13f4556f7797d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class LoadingSpinnerFactory : UxmlFactory<LoadingSpinner>
|
||||
{
|
||||
protected override LoadingSpinner DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new LoadingSpinner();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class LoadingSpinner : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<LoadingSpinner, UxmlTraits>
|
||||
{
|
||||
}
|
||||
|
||||
// This works around an issue with UXML instantiation
|
||||
// See https://fogbugz.unity3d.com/f/cases/1046459/
|
||||
internal new class UxmlTraits : VisualElement.UxmlTraits
|
||||
{
|
||||
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
base.Init(ve, bag, cc);
|
||||
UIUtils.SetElementDisplay(ve, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool InvertColor { get; set; }
|
||||
public bool Started { get; private set; }
|
||||
|
||||
private int rotation;
|
||||
|
||||
public LoadingSpinner()
|
||||
{
|
||||
InvertColor = false;
|
||||
Started = false;
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
}
|
||||
|
||||
private void UpdateProgress()
|
||||
{
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
parent.transform.rotation = Quaternion.Euler(0, 0, rotation);
|
||||
rotation += 3;
|
||||
if (rotation > 360)
|
||||
rotation -= 360;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (Started)
|
||||
return;
|
||||
|
||||
// Weird hack to make sure loading spinner doesn't generate an error every frame.
|
||||
// Cannot put in constructor as it give really strange result.
|
||||
if (parent != null && parent.parent != null)
|
||||
parent.parent.clippingOptions = ClippingOptions.ClipAndCacheContents;
|
||||
|
||||
rotation = 0;
|
||||
|
||||
EditorApplication.update += UpdateProgress;
|
||||
|
||||
Started = true;
|
||||
UIUtils.SetElementDisplay(this, true);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (!Started)
|
||||
return;
|
||||
|
||||
EditorApplication.update -= UpdateProgress;
|
||||
|
||||
Started = false;
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06f8e3404d534cab82fe852ff33dad77
|
||||
timeCreated: 1504191988
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal class PopupField<T> : Experimental.UIElements.PopupField<T>
|
||||
{
|
||||
private Func<T, string> m_Callback;
|
||||
|
||||
public override T value
|
||||
{
|
||||
get { return base.value; }
|
||||
set
|
||||
{
|
||||
base.value = value;
|
||||
if (m_Callback != null)
|
||||
m_TextElement.text = m_Callback(m_Value);
|
||||
else
|
||||
m_TextElement.text = m_Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback that will return the string to be set in the field's label.
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public void SetLabelCallback(Func<T, string> callback)
|
||||
{
|
||||
m_Callback = callback;
|
||||
}
|
||||
|
||||
public PopupField(List<T> choices, T defaultValue) :
|
||||
base(choices, defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
public PopupField(List<T> choices, int defaultIndex) :
|
||||
base(choices, defaultIndex)
|
||||
{
|
||||
}
|
||||
}
|
||||
#else
|
||||
internal class PopupField<T> : BaseTextElement, INotifyValueChanged<T>
|
||||
{
|
||||
private readonly List<T> m_PossibleValues;
|
||||
private Func<T, string> m_Callback;
|
||||
private EventCallback<ChangeEvent<T>> m_valueCallback;
|
||||
private T m_Value;
|
||||
public T value
|
||||
{
|
||||
get { return m_Value; }
|
||||
set
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(m_Value, value))
|
||||
return;
|
||||
|
||||
if (!m_PossibleValues.Contains(value))
|
||||
throw new ArgumentException(string.Format("Value {0} is not present in the list of possible values", value));
|
||||
|
||||
m_Value = value;
|
||||
m_Index = m_PossibleValues.IndexOf(m_Value);
|
||||
if (m_Callback != null)
|
||||
text = m_Callback(m_Value);
|
||||
else
|
||||
text = m_Value.ToString();
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
MarkDirtyRepaint();
|
||||
#else
|
||||
Dirty(ChangeType.Repaint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private int m_Index = -1;
|
||||
public int index
|
||||
{
|
||||
get { return m_Index; }
|
||||
set
|
||||
{
|
||||
if (value != m_Index)
|
||||
{
|
||||
if (value >= m_PossibleValues.Count || value < 0)
|
||||
throw new ArgumentException(string.Format("Index {0} is beyond the scope of possible value", value));
|
||||
m_Index = value;
|
||||
this.value = m_PossibleValues[m_Index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback that will return the string to be set in the field's label.
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public void SetLabelCallback(Func<T, string> callback)
|
||||
{
|
||||
m_Callback = callback;
|
||||
}
|
||||
|
||||
private PopupField(List<T> possibleValues)
|
||||
{
|
||||
if (possibleValues == null)
|
||||
throw new ArgumentNullException("possibleValues can't be null");
|
||||
|
||||
m_PossibleValues = possibleValues;
|
||||
|
||||
AddToClassList("popupField");
|
||||
}
|
||||
|
||||
public PopupField(List<T> possibleValues, T defaultValue) :
|
||||
this(possibleValues)
|
||||
{
|
||||
if (defaultValue == null)
|
||||
throw new ArgumentNullException("defaultValue can't be null");
|
||||
|
||||
if (!m_PossibleValues.Contains(defaultValue))
|
||||
throw new ArgumentException(string.Format("Default value {0} is not present in the list of possible values", defaultValue));
|
||||
|
||||
// note: idx will be set when setting value
|
||||
value = defaultValue;
|
||||
}
|
||||
|
||||
public PopupField(List<T> possibleValues, int defaultIndex) :
|
||||
this(possibleValues)
|
||||
{
|
||||
if (defaultIndex >= m_PossibleValues.Count || defaultIndex < 0)
|
||||
throw new ArgumentException(string.Format("Default Index {0} is beyond the scope of possible value", value));
|
||||
|
||||
// note: value will be set when setting idx
|
||||
index = defaultIndex;
|
||||
}
|
||||
|
||||
public void SetValueAndNotify(T newValue)
|
||||
{
|
||||
if (!EqualityComparer<T>.Default.Equals(newValue, value))
|
||||
{
|
||||
using (ChangeEvent<T> evt = ChangeEvent<T>.GetPooled(value, newValue))
|
||||
{
|
||||
value = newValue;
|
||||
if (m_valueCallback != null)
|
||||
m_valueCallback(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnValueChanged(EventCallback<ChangeEvent<T>> callback)
|
||||
{
|
||||
m_valueCallback = callback;
|
||||
RegisterCallback(callback);
|
||||
}
|
||||
|
||||
protected override void ExecuteDefaultAction(EventBase evt)
|
||||
{
|
||||
base.ExecuteDefaultAction(evt);
|
||||
|
||||
if (evt.GetEventTypeId() == MouseDownEvent.TypeId())
|
||||
OnMouseDown();
|
||||
}
|
||||
|
||||
private void OnMouseDown()
|
||||
{
|
||||
var menu = new GenericMenu();
|
||||
|
||||
foreach (T item in m_PossibleValues)
|
||||
{
|
||||
bool isSelected = EqualityComparer<T>.Default.Equals(item, value);
|
||||
menu.AddItem(new GUIContent(item.ToString()), isSelected,
|
||||
() => ChangeValueFromMenu(item));
|
||||
}
|
||||
|
||||
var menuPosition = new Vector2(0.0f, layout.height);
|
||||
menuPosition = this.LocalToWorld(menuPosition);
|
||||
var menuRect = new Rect(menuPosition, Vector2.zero);
|
||||
menu.DropDown(menuRect);
|
||||
}
|
||||
|
||||
private void ChangeValueFromMenu(T menuItem)
|
||||
{
|
||||
SetValueAndNotify(menuItem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e69df8ff024a4dc1a9e5c22725e4863
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class UIUtils
|
||||
{
|
||||
private const string DisplayNone = "display-none";
|
||||
|
||||
public static void SetElementDisplay(VisualElement element, bool value)
|
||||
{
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
if (value)
|
||||
element.RemoveFromClassList(DisplayNone);
|
||||
else
|
||||
element.AddToClassList(DisplayNone);
|
||||
|
||||
element.visible = value;
|
||||
}
|
||||
|
||||
public static void SetElementDisplayNonEmpty(Label element)
|
||||
{
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
var empty = string.IsNullOrEmpty(element.text);
|
||||
if (empty)
|
||||
element.AddToClassList(DisplayNone);
|
||||
else
|
||||
element.RemoveFromClassList(DisplayNone);
|
||||
|
||||
element.visible = !empty;
|
||||
}
|
||||
|
||||
public static void SetElementDisplayNonEmpty(Button element)
|
||||
{
|
||||
if (element == null)
|
||||
return;
|
||||
|
||||
var empty = string.IsNullOrEmpty(element.text);
|
||||
if (empty)
|
||||
element.AddToClassList(DisplayNone);
|
||||
else
|
||||
element.RemoveFromClassList(DisplayNone);
|
||||
|
||||
element.visible = !empty;
|
||||
}
|
||||
|
||||
public static bool IsElementVisible(VisualElement element)
|
||||
{
|
||||
return element.visible && !element.ClassListContains(DisplayNone);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0edd86f97b0648f685604a5582cff608
|
||||
timeCreated: 1508956933
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal class VersionItem
|
||||
{
|
||||
internal PackageInfo Version;
|
||||
|
||||
public string MenuName { get; set; }
|
||||
|
||||
// Base label
|
||||
public string Label
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Version == null)
|
||||
return MenuName;
|
||||
|
||||
var label = Version.VersionWithoutTag;
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
public string DropdownLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Version == null)
|
||||
return MenuName;
|
||||
|
||||
var label = MenuName + Label;
|
||||
|
||||
if (Version.IsLocal)
|
||||
label += " - local";
|
||||
if (Version.IsCurrent)
|
||||
label += " - current";
|
||||
if (Version.IsVerified)
|
||||
label += " - verified";
|
||||
else if (!string.IsNullOrEmpty(Version.Version.Prerelease))
|
||||
label += string.Format(" - {0}", Version.Version.Prerelease);
|
||||
else if (Version.IsPreview)
|
||||
label += " - preview";
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return DropdownLabel;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(obj, null)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
|
||||
var other = (VersionItem)obj;
|
||||
return Version == other.Version;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Version.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3877b2be7ee07495d8918dc8937e6de2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfd715cd54ab84c22b128149c12b516c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for Package Manager UI Extension
|
||||
/// </summary>
|
||||
public interface IPackageManagerExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the extension UI visual element.
|
||||
/// </summary>
|
||||
/// <returns>A visual element that represents the UI or null if none</returns>
|
||||
VisualElement CreateExtensionUI();
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Package Manager UI when the package selection changed.
|
||||
/// </summary>
|
||||
/// <param name="packageInfo">The newly selected package information (can be null)</param>
|
||||
void OnPackageSelectionChange(PackageManager.PackageInfo packageInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Package Manager UI when a package is added or updated.
|
||||
/// </summary>
|
||||
/// <param name="packageInfo">The package information</param>
|
||||
void OnPackageAddedOrUpdated(PackageManager.PackageInfo packageInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Called by the Package Manager UI when a package is removed.
|
||||
/// </summary>
|
||||
/// <param name="packageInfo">The package information</param>
|
||||
void OnPackageRemoved(PackageManager.PackageInfo packageInfo);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66083b7f6dc2e433eae33f3244b2ce88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class PackageAddFromUrlFieldFactory : UxmlFactory<PackageAddFromUrlField>
|
||||
{
|
||||
protected override PackageAddFromUrlField DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new PackageAddFromUrlField();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class PackageAddFromUrlField : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<PackageAddFromUrlField> { }
|
||||
#endif
|
||||
private string urlText;
|
||||
|
||||
private readonly VisualElement root;
|
||||
|
||||
public PackageAddFromUrlField()
|
||||
{
|
||||
root = Resources.GetTemplate("PackageAddFromUrlField.uxml");
|
||||
Add(root);
|
||||
|
||||
UrlTextField.value = urlText;
|
||||
|
||||
AddButton.SetEnabled(!string.IsNullOrEmpty(urlText));
|
||||
AddButton.clickable.clicked += OnAddButtonClick;
|
||||
|
||||
RegisterCallback<AttachToPanelEvent>(OnEnterPanel);
|
||||
RegisterCallback<DetachFromPanelEvent>(OnLeavePanel);
|
||||
}
|
||||
|
||||
private void OnUrlTextFieldChange(ChangeEvent<string> evt)
|
||||
{
|
||||
urlText = evt.newValue;
|
||||
AddButton.SetEnabled(!string.IsNullOrEmpty(urlText));
|
||||
}
|
||||
|
||||
private void OnUrlTextFieldFocus(FocusEvent evt)
|
||||
{
|
||||
Show();
|
||||
}
|
||||
|
||||
private void OnUrlTextFieldFocusOut(FocusOutEvent evt)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void OnContainerFocus(FocusEvent evt)
|
||||
{
|
||||
UrlTextField.Focus();
|
||||
}
|
||||
|
||||
private void OnContainerFocusOut(FocusOutEvent evt)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void OnEnterPanel(AttachToPanelEvent evt)
|
||||
{
|
||||
AddFromUrlFieldContainer.RegisterCallback<FocusEvent>(OnContainerFocus);
|
||||
AddFromUrlFieldContainer.RegisterCallback<FocusOutEvent>(OnContainerFocusOut);
|
||||
UrlTextField.RegisterCallback<FocusEvent>(OnUrlTextFieldFocus);
|
||||
UrlTextField.RegisterCallback<FocusOutEvent>(OnUrlTextFieldFocusOut);
|
||||
UrlTextField.RegisterCallback<ChangeEvent<string>>(OnUrlTextFieldChange);
|
||||
UrlTextField.RegisterCallback<KeyDownEvent>(OnKeyDownShortcut);
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void OnLeavePanel(DetachFromPanelEvent evt)
|
||||
{
|
||||
AddFromUrlFieldContainer.UnregisterCallback<FocusEvent>(OnContainerFocus);
|
||||
AddFromUrlFieldContainer.UnregisterCallback<FocusOutEvent>(OnContainerFocusOut);
|
||||
UrlTextField.UnregisterCallback<FocusEvent>(OnUrlTextFieldFocus);
|
||||
UrlTextField.UnregisterCallback<FocusOutEvent>(OnUrlTextFieldFocusOut);
|
||||
UrlTextField.UnregisterCallback<ChangeEvent<string>>(OnUrlTextFieldChange);
|
||||
UrlTextField.UnregisterCallback<KeyDownEvent>(OnKeyDownShortcut);
|
||||
}
|
||||
|
||||
private void OnKeyDownShortcut(KeyDownEvent evt)
|
||||
{
|
||||
switch (evt.keyCode)
|
||||
{
|
||||
case KeyCode.Escape:
|
||||
Hide();
|
||||
break;
|
||||
case KeyCode.Return:
|
||||
case KeyCode.KeypadEnter:
|
||||
OnAddButtonClick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAddButtonClick()
|
||||
{
|
||||
var path = urlText;
|
||||
if (!string.IsNullOrEmpty(path) && !Package.AddRemoveOperationInProgress)
|
||||
{
|
||||
Package.AddFromLocalDisk(path);
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Hide()
|
||||
{
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
}
|
||||
|
||||
internal void Show(bool reset = false)
|
||||
{
|
||||
if (reset)
|
||||
Reset();
|
||||
UIUtils.SetElementDisplay(this, true);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
UrlTextField.value = string.Empty;
|
||||
urlText = string.Empty;
|
||||
AddButton.SetEnabled(false);
|
||||
UrlTextField.Focus();
|
||||
}
|
||||
|
||||
private VisualElement AddFromUrlFieldContainer { get { return root.Q<VisualElement>("addFromUrlFieldContainer"); }}
|
||||
private TextField UrlTextField { get { return root.Q<TextField>("urlTextField"); } }
|
||||
private Button AddButton{ get { return root.Q<Button>("addFromUrlButton"); }}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 40f980217d9196e4baa9ebd2ac1328af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+626
@@ -0,0 +1,626 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Semver;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class PackageDetailsFactory : UxmlFactory<PackageDetails>
|
||||
{
|
||||
protected override PackageDetails DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new PackageDetails();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class PackageDetails : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<PackageDetails> { }
|
||||
#endif
|
||||
|
||||
private readonly VisualElement root;
|
||||
private Package package;
|
||||
private const string emptyDescriptionClass = "empty";
|
||||
private List<VersionItem> VersionItems;
|
||||
internal PopupField<VersionItem> VersionPopup;
|
||||
private PackageInfo DisplayPackage;
|
||||
|
||||
private PackageInfo SelectedPackage
|
||||
{
|
||||
get { return VersionPopup.value.Version != null ? VersionPopup.value.Version : null; }
|
||||
}
|
||||
|
||||
internal enum PackageAction
|
||||
{
|
||||
Add,
|
||||
Remove,
|
||||
Update,
|
||||
Downgrade,
|
||||
Enable,
|
||||
Disable,
|
||||
UpToDate,
|
||||
Current,
|
||||
Local,
|
||||
Git,
|
||||
Embedded
|
||||
}
|
||||
|
||||
private static readonly VersionItem EmptyVersion = new VersionItem {Version = null};
|
||||
internal static readonly string[] PackageActionVerbs = { "Install", "Remove", "Update to", "Update to", "Enable", "Disable", "Up to date", "Current", "Local", "Git", "Embedded" };
|
||||
internal static readonly string[] PackageActionInProgressVerbs = { "Installing", "Removing", "Updating to", "Updating to", "Enabling", "Disabling", "Up to date", "Current", "Local", "Git", "Embedded" };
|
||||
|
||||
public PackageDetails()
|
||||
{
|
||||
UIUtils.SetElementDisplay(this, false);
|
||||
|
||||
root = Resources.GetTemplate("PackageDetails.uxml");
|
||||
Add(root);
|
||||
|
||||
foreach (var extension in PackageManagerExtensions.Extensions)
|
||||
CustomContainer.Add(extension.CreateExtensionUI());
|
||||
|
||||
root.StretchToParentSize();
|
||||
|
||||
SetUpdateVisibility(false);
|
||||
RemoveButton.visible = false;
|
||||
UpdateBuiltIn.visible = false;
|
||||
|
||||
UpdateButton.clickable.clicked += UpdateClick;
|
||||
UpdateBuiltIn.clickable.clicked += UpdateClick;
|
||||
RemoveButton.clickable.clicked += RemoveClick;
|
||||
ViewDocButton.clickable.clicked += ViewDocClick;
|
||||
ViewChangelogButton.clickable.clicked += ViewChangelogClick;
|
||||
ViewLicenses.clickable.clicked += ViewLicensesClick;
|
||||
|
||||
VersionItems = new List<VersionItem> {EmptyVersion};
|
||||
VersionPopup = new PopupField<VersionItem>(VersionItems, 0);
|
||||
VersionPopup.SetLabelCallback(VersionSelectionSetLabel);
|
||||
VersionPopup.AddToClassList("popup");
|
||||
VersionPopup.OnValueChanged(VersionSelectionChanged);
|
||||
|
||||
if (VersionItems.Count == 1)
|
||||
VersionPopup.SetEnabled(false);
|
||||
|
||||
UpdateDropdownContainer.Add(VersionPopup);
|
||||
VersionPopup.StretchToParentSize();
|
||||
|
||||
|
||||
// Fix button on dark skin but overlapping edge pixel perfectly
|
||||
if (EditorGUIUtility.isProSkin)
|
||||
{
|
||||
VersionPopup.style.positionLeft = -1;
|
||||
UpdateDropdownContainer.style.sliceLeft = 4;
|
||||
}
|
||||
}
|
||||
|
||||
private string VersionSelectionSetLabel(VersionItem item)
|
||||
{
|
||||
return item.Label;
|
||||
}
|
||||
|
||||
private void VersionSelectionChanged(ChangeEvent<VersionItem> e)
|
||||
{
|
||||
RefreshAddButton();
|
||||
}
|
||||
|
||||
private void SetUpdateVisibility(bool value)
|
||||
{
|
||||
if (UpdateContainer != null)
|
||||
UIUtils.SetElementDisplay(UpdateContainer, value);
|
||||
}
|
||||
|
||||
internal void SetDisplayPackage(PackageInfo packageInfo)
|
||||
{
|
||||
DisplayPackage = packageInfo;
|
||||
|
||||
var detailVisible = true;
|
||||
Error error = null;
|
||||
|
||||
if (package == null || DisplayPackage == null)
|
||||
{
|
||||
detailVisible = false;
|
||||
UIUtils.SetElementDisplay(DocumentationContainer, false);
|
||||
UIUtils.SetElementDisplay(CustomContainer, false);
|
||||
UIUtils.SetElementDisplay(UpdateBuiltIn, false);
|
||||
|
||||
foreach (var extension in PackageManagerExtensions.Extensions)
|
||||
extension.OnPackageSelectionChange(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUpdateVisibility(true);
|
||||
UIUtils.SetElementDisplay(ViewDocButton, true);
|
||||
RemoveButton.visible = true;
|
||||
|
||||
if (string.IsNullOrEmpty(DisplayPackage.Description))
|
||||
{
|
||||
DetailDesc.text = "There is no description for this package.";
|
||||
DetailDesc.AddToClassList(emptyDescriptionClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailDesc.text = DisplayPackage.Description;
|
||||
DetailDesc.RemoveFromClassList(emptyDescriptionClass);
|
||||
}
|
||||
|
||||
root.Q<Label>("detailTitle").text = DisplayPackage.DisplayName;
|
||||
DetailVersion.text = "Version " + DisplayPackage.VersionWithoutTag;
|
||||
|
||||
if (DisplayPackage.IsInDevelopment || DisplayPackage.HasVersionTag(PackageTag.preview))
|
||||
UIUtils.SetElementDisplay(GetTag(PackageTag.verified), false);
|
||||
else
|
||||
{
|
||||
var unityVersionParts = Application.unityVersion.Split('.');
|
||||
var unityVersion = string.Format("{0}.{1}", unityVersionParts[0], unityVersionParts[1]);
|
||||
VerifyLabel.text = unityVersion + " verified";
|
||||
UIUtils.SetElementDisplay(GetTag(PackageTag.verified), DisplayPackage.IsVerified);
|
||||
}
|
||||
|
||||
UIUtils.SetElementDisplay(GetTag(PackageTag.inDevelopment), DisplayPackage.IsInDevelopment);
|
||||
UIUtils.SetElementDisplay(GetTag(PackageTag.local), DisplayPackage.IsLocal);
|
||||
UIUtils.SetElementDisplay(GetTag(PackageTag.preview), DisplayPackage.IsPreview);
|
||||
|
||||
UIUtils.SetElementDisplay(DocumentationContainer, DisplayPackage.Origin != PackageSource.BuiltIn);
|
||||
UIUtils.SetElementDisplay(ChangelogContainer, DisplayPackage.HasChangelog(DisplayPackage));
|
||||
|
||||
root.Q<Label>("detailName").text = DisplayPackage.Name;
|
||||
root.Q<ScrollView>("detailView").scrollOffset = new Vector2(0, 0);
|
||||
|
||||
DetailModuleReference.text = "";
|
||||
var isBuiltIn = DisplayPackage.IsBuiltIn;
|
||||
if (isBuiltIn)
|
||||
DetailModuleReference.text = DisplayPackage.BuiltInDescription;
|
||||
|
||||
DetailAuthor.text = "";
|
||||
if (!string.IsNullOrEmpty(DisplayPackage.Author))
|
||||
DetailAuthor.text = string.Format("Author: {0}", DisplayPackage.Author);
|
||||
|
||||
UIUtils.SetElementDisplay(DetailDesc, !isBuiltIn);
|
||||
UIUtils.SetElementDisplay(DetailVersion, !isBuiltIn);
|
||||
UIUtils.SetElementDisplayNonEmpty(DetailModuleReference);
|
||||
UIUtils.SetElementDisplayNonEmpty(DetailAuthor);
|
||||
|
||||
if (DisplayPackage.Errors.Count > 0)
|
||||
error = DisplayPackage.Errors.First();
|
||||
|
||||
RefreshAddButton();
|
||||
RefreshRemoveButton();
|
||||
UIUtils.SetElementDisplay(CustomContainer, true);
|
||||
|
||||
package.AddSignal.OnOperation += OnAddOperation;
|
||||
package.RemoveSignal.OnOperation += OnRemoveOperation;
|
||||
foreach (var extension in PackageManagerExtensions.Extensions)
|
||||
extension.OnPackageSelectionChange(DisplayPackage.Info);
|
||||
}
|
||||
|
||||
// Set visibility
|
||||
root.Q<VisualElement>("detail").visible = detailVisible;
|
||||
|
||||
if (null == error)
|
||||
error = PackageCollection.Instance.GetPackageError(package);
|
||||
|
||||
if (error != null)
|
||||
SetError(error);
|
||||
else
|
||||
DetailError.ClearError();
|
||||
}
|
||||
|
||||
private void ResetVersionItems(PackageInfo displayPackage)
|
||||
{
|
||||
VersionItems.Clear();
|
||||
VersionPopup.SetEnabled(true);
|
||||
|
||||
if (displayPackage == null)
|
||||
return;
|
||||
|
||||
//
|
||||
// Get key versions -- Latest, Verified, LatestPatch, Current.
|
||||
var keyVersions = new List<PackageInfo>();
|
||||
if (package.LatestRelease != null) keyVersions.Add(package.LatestRelease);
|
||||
if (package.Current != null) keyVersions.Add(package.Current);
|
||||
if (package.Verified != null && package.Verified != package.Current) keyVersions.Add(package.Verified);
|
||||
if (package.LatestPatch != null && package.IsAfterCurrentVersion(package.LatestPatch)) keyVersions.Add(package.LatestPatch);
|
||||
if (package.Current == null && package.LatestRelease == null && package.Latest != null) keyVersions.Add(package.Latest);
|
||||
if (Package.ShouldProposeLatestVersions && package.Latest != package.LatestRelease && package.Latest != null) keyVersions.Add(package.Latest);
|
||||
keyVersions.Add(package.LatestUpdate); // Make sure LatestUpdate is always in the list.
|
||||
|
||||
foreach (var version in keyVersions.OrderBy(package => package.Version).Reverse())
|
||||
{
|
||||
var item = new VersionItem {Version = version};
|
||||
VersionItems.Add(item);
|
||||
|
||||
if (version == package.LatestUpdate)
|
||||
VersionPopup.value = item;
|
||||
}
|
||||
|
||||
//
|
||||
// Add all versions
|
||||
foreach (var version in package.Versions.Reverse())
|
||||
{
|
||||
var item = new VersionItem {Version = version};
|
||||
item.MenuName = "All Versions/";
|
||||
VersionItems.Add(item);
|
||||
}
|
||||
|
||||
if (VersionItems.Count == 0)
|
||||
{
|
||||
VersionItems.Add(EmptyVersion);
|
||||
VersionPopup.value = EmptyVersion;
|
||||
VersionPopup.SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPackage(Package package)
|
||||
{
|
||||
if (this.package != null)
|
||||
{
|
||||
if (this.package.AddSignal.Operation != null)
|
||||
{
|
||||
this.package.AddSignal.Operation.OnOperationError -= OnAddOperationError;
|
||||
this.package.AddSignal.Operation.OnOperationSuccess -= OnAddOperationSuccess;
|
||||
}
|
||||
this.package.AddSignal.ResetEvents();
|
||||
|
||||
if (this.package.RemoveSignal.Operation != null)
|
||||
{
|
||||
this.package.RemoveSignal.Operation.OnOperationSuccess -= OnRemoveOperationSuccess;
|
||||
this.package.RemoveSignal.Operation.OnOperationError -= OnRemoveOperationError;
|
||||
}
|
||||
this.package.RemoveSignal.ResetEvents();
|
||||
}
|
||||
|
||||
UIUtils.SetElementDisplay(this, true);
|
||||
|
||||
this.package = package;
|
||||
var displayPackage = package != null ? package.VersionToDisplay : null;
|
||||
ResetVersionItems(displayPackage);
|
||||
SetDisplayPackage(displayPackage);
|
||||
}
|
||||
|
||||
private void SetError(Error error)
|
||||
{
|
||||
DetailError.AdjustSize(DetailView.verticalScroller.visible);
|
||||
DetailError.SetError(error);
|
||||
DetailError.OnCloseError = () =>
|
||||
{
|
||||
PackageCollection.Instance.RemovePackageErrors(package);
|
||||
PackageCollection.Instance.UpdatePackageCollection();
|
||||
};
|
||||
}
|
||||
|
||||
private void OnAddOperation(IAddOperation operation)
|
||||
{
|
||||
operation.OnOperationError += OnAddOperationError;
|
||||
operation.OnOperationSuccess += OnAddOperationSuccess;
|
||||
}
|
||||
|
||||
private void OnAddOperationError(Error error)
|
||||
{
|
||||
if (package != null && package.AddSignal.Operation != null)
|
||||
{
|
||||
package.AddSignal.Operation.OnOperationSuccess -= OnAddOperationSuccess;
|
||||
package.AddSignal.Operation.OnOperationError -= OnAddOperationError;
|
||||
package.AddSignal.Operation = null;
|
||||
}
|
||||
|
||||
PackageCollection.Instance.AddPackageError(package, error);
|
||||
|
||||
SetError(error);
|
||||
if (package != null)
|
||||
ResetVersionItems(package.VersionToDisplay);
|
||||
PackageCollection.Instance.UpdatePackageCollection();
|
||||
}
|
||||
|
||||
private void OnAddOperationSuccess(PackageInfo packageInfo)
|
||||
{
|
||||
if (package != null && package.AddSignal.Operation != null)
|
||||
{
|
||||
package.AddSignal.Operation.OnOperationSuccess -= OnAddOperationSuccess;
|
||||
package.AddSignal.Operation.OnOperationError -= OnAddOperationError;
|
||||
package.AddSignal.Operation = null;
|
||||
}
|
||||
|
||||
foreach (var extension in PackageManagerExtensions.Extensions)
|
||||
extension.OnPackageAddedOrUpdated(packageInfo.Info);
|
||||
}
|
||||
|
||||
private void OnRemoveOperation(IRemoveOperation operation)
|
||||
{
|
||||
// Make sure we are not already registered
|
||||
operation.OnOperationError -= OnRemoveOperationError;
|
||||
operation.OnOperationSuccess -= OnRemoveOperationSuccess;
|
||||
|
||||
operation.OnOperationError += OnRemoveOperationError;
|
||||
operation.OnOperationSuccess += OnRemoveOperationSuccess;
|
||||
}
|
||||
|
||||
private void OnRemoveOperationError(Error error)
|
||||
{
|
||||
if (package != null && package.RemoveSignal.Operation != null)
|
||||
{
|
||||
package.RemoveSignal.Operation.OnOperationSuccess -= OnRemoveOperationSuccess;
|
||||
package.RemoveSignal.Operation.OnOperationError -= OnRemoveOperationError;
|
||||
package.RemoveSignal.Operation = null;
|
||||
}
|
||||
|
||||
PackageCollection.Instance.AddPackageError(package, error);
|
||||
|
||||
SetError(error);
|
||||
PackageCollection.Instance.UpdatePackageCollection();
|
||||
}
|
||||
|
||||
private void OnRemoveOperationSuccess(PackageInfo packageInfo)
|
||||
{
|
||||
if (package != null && package.RemoveSignal.Operation != null)
|
||||
{
|
||||
package.RemoveSignal.Operation.OnOperationSuccess -= OnRemoveOperationSuccess;
|
||||
package.RemoveSignal.Operation.OnOperationError -= OnRemoveOperationError;
|
||||
package.RemoveSignal.Operation = null;
|
||||
}
|
||||
|
||||
foreach (var extension in PackageManagerExtensions.Extensions)
|
||||
extension.OnPackageRemoved(packageInfo.Info);
|
||||
}
|
||||
|
||||
private void RefreshAddButton()
|
||||
{
|
||||
if (package.Current != null && package.Current.IsInDevelopment)
|
||||
{
|
||||
UIUtils.SetElementDisplay(UpdateBuiltIn, false);
|
||||
UIUtils.SetElementDisplay(UpdateCombo, false);
|
||||
UIUtils.SetElementDisplay(UpdateButton, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetVersion = SelectedPackage;
|
||||
if (targetVersion == null)
|
||||
return;
|
||||
|
||||
var enableButton = !Package.AddRemoveOperationInProgress;
|
||||
var enableVersionButton = true;
|
||||
|
||||
var action = PackageAction.Update;
|
||||
var inprogress = false;
|
||||
var isBuiltIn = package.IsBuiltIn;
|
||||
SemVersion version = null;
|
||||
|
||||
if (package.AddSignal.Operation != null)
|
||||
{
|
||||
if (isBuiltIn)
|
||||
{
|
||||
action = PackageAction.Enable;
|
||||
inprogress = true;
|
||||
enableButton = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var addOperationVersion = package.AddSignal.Operation.PackageInfo.Version;
|
||||
if (package.Current == null)
|
||||
{
|
||||
action = PackageAction.Add;
|
||||
inprogress = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
action = addOperationVersion.CompareByPrecedence(package.Current.Version) >= 0
|
||||
? PackageAction.Update : PackageAction.Downgrade;
|
||||
inprogress = true;
|
||||
}
|
||||
|
||||
enableButton = false;
|
||||
enableVersionButton = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (package.Current != null)
|
||||
{
|
||||
// Installed
|
||||
if (package.Current.IsVersionLocked)
|
||||
{
|
||||
if (package.Current.Origin == PackageSource.Embedded)
|
||||
action = PackageAction.Embedded;
|
||||
else if (package.Current.Origin == PackageSource.Git)
|
||||
action = PackageAction.Git;
|
||||
|
||||
enableButton = false;
|
||||
enableVersionButton = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetVersion.IsCurrent)
|
||||
{
|
||||
if (targetVersion == package.LatestUpdate)
|
||||
action = PackageAction.UpToDate;
|
||||
else
|
||||
action = PackageAction.Current;
|
||||
|
||||
enableButton = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
action = targetVersion.Version.CompareByPrecedence(package.Current.Version) >= 0
|
||||
? PackageAction.Update : PackageAction.Downgrade;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not Installed
|
||||
if (package.Versions.Any())
|
||||
{
|
||||
if (isBuiltIn)
|
||||
action = PackageAction.Enable;
|
||||
else
|
||||
action = PackageAction.Add;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (package.RemoveSignal.Operation != null)
|
||||
enableButton = false;
|
||||
|
||||
if (EditorApplication.isCompiling)
|
||||
{
|
||||
enableButton = false;
|
||||
enableVersionButton = false;
|
||||
|
||||
EditorApplication.update -= CheckCompilationStatus;
|
||||
EditorApplication.update += CheckCompilationStatus;
|
||||
}
|
||||
|
||||
var button = isBuiltIn ? UpdateBuiltIn : UpdateButton;
|
||||
button.SetEnabled(enableButton);
|
||||
VersionPopup.SetEnabled(enableVersionButton);
|
||||
button.text = GetButtonText(action, inprogress, version);
|
||||
|
||||
var visibleFlag = !(package.Current != null && package.Current.IsVersionLocked);
|
||||
UIUtils.SetElementDisplay(UpdateBuiltIn, isBuiltIn && visibleFlag);
|
||||
UIUtils.SetElementDisplay(UpdateCombo, !isBuiltIn && visibleFlag);
|
||||
UIUtils.SetElementDisplay(UpdateButton, !isBuiltIn && visibleFlag);
|
||||
}
|
||||
|
||||
private void RefreshRemoveButton()
|
||||
{
|
||||
var visibleFlag = false;
|
||||
|
||||
var current = package.Current;
|
||||
|
||||
// Show only if there is a current package installed
|
||||
if (current != null)
|
||||
{
|
||||
visibleFlag = current.CanBeRemoved && !package.IsPackageManagerUI;
|
||||
|
||||
var action = current.IsBuiltIn ? PackageAction.Disable : PackageAction.Remove;
|
||||
var inprogress = package.RemoveSignal.Operation != null;
|
||||
|
||||
var enableButton = visibleFlag && !EditorApplication.isCompiling && !inprogress && !Package.AddRemoveOperationInProgress;
|
||||
|
||||
if (EditorApplication.isCompiling)
|
||||
{
|
||||
EditorApplication.update -= CheckCompilationStatus;
|
||||
EditorApplication.update += CheckCompilationStatus;
|
||||
}
|
||||
|
||||
RemoveButton.SetEnabled(enableButton);
|
||||
RemoveButton.text = GetButtonText(action, inprogress);
|
||||
}
|
||||
|
||||
UIUtils.SetElementDisplay(RemoveButton, visibleFlag);
|
||||
}
|
||||
|
||||
private void CheckCompilationStatus()
|
||||
{
|
||||
if (EditorApplication.isCompiling)
|
||||
return;
|
||||
|
||||
RefreshAddButton();
|
||||
RefreshRemoveButton();
|
||||
EditorApplication.update -= CheckCompilationStatus;
|
||||
}
|
||||
|
||||
private static string GetButtonText(PackageAction action, bool inProgress = false, SemVersion version = null)
|
||||
{
|
||||
return version == null ?
|
||||
string.Format("{0}", inProgress ? PackageActionInProgressVerbs[(int) action] : PackageActionVerbs[(int) action]) :
|
||||
string.Format("{0} {1}", inProgress ? PackageActionInProgressVerbs[(int) action] : PackageActionVerbs[(int) action], version);
|
||||
}
|
||||
|
||||
private void UpdateClick()
|
||||
{
|
||||
if (package.IsPackageManagerUI)
|
||||
{
|
||||
// Let's not allow updating of the UI if there are build errrors, as for now, that will prevent the UI from reloading properly.
|
||||
if (EditorUtility.scriptCompilationFailed)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Unity Package Manager", "The Package Manager UI cannot be updated while there are script compilation errors in your project. Please fix the errors and try again.", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EditorUtility.DisplayDialog("Unity Package Manager", "Updating this package will close the Package Manager window. You will have to re-open it after the update is done. Do you want to continue?", "Yes", "No"))
|
||||
return;
|
||||
|
||||
if (package.AddSignal.Operation != null)
|
||||
{
|
||||
package.AddSignal.Operation.OnOperationSuccess -= OnAddOperationSuccess;
|
||||
package.AddSignal.Operation.OnOperationError -= OnAddOperationError;
|
||||
package.AddSignal.ResetEvents();
|
||||
package.AddSignal.Operation = null;
|
||||
}
|
||||
|
||||
DetailError.ClearError();
|
||||
EditorApplication.update += CloseAndUpdate;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DetailError.ClearError();
|
||||
package.Add(SelectedPackage);
|
||||
RefreshAddButton();
|
||||
RefreshRemoveButton();
|
||||
}
|
||||
|
||||
private void CloseAndUpdate()
|
||||
{
|
||||
EditorApplication.update -= CloseAndUpdate;
|
||||
package.Add(SelectedPackage);
|
||||
|
||||
var windows = UnityEngine.Resources.FindObjectsOfTypeAll<PackageManagerWindow>();
|
||||
if (windows.Length > 0)
|
||||
{
|
||||
windows[0].Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RemoveClick()
|
||||
{
|
||||
DetailError.ClearError();
|
||||
package.Remove();
|
||||
RefreshRemoveButton();
|
||||
RefreshAddButton();
|
||||
}
|
||||
|
||||
|
||||
private void ViewDocClick()
|
||||
{
|
||||
Application.OpenURL(DisplayPackage.GetDocumentationUrl());
|
||||
}
|
||||
|
||||
private void ViewChangelogClick()
|
||||
{
|
||||
Application.OpenURL(DisplayPackage.GetChangelogUrl());
|
||||
}
|
||||
|
||||
private void ViewLicensesClick()
|
||||
{
|
||||
Application.OpenURL(DisplayPackage.GetLicensesUrl());
|
||||
}
|
||||
|
||||
private Label DetailDesc { get { return root.Q<Label>("detailDesc"); } }
|
||||
internal Button UpdateButton { get { return root.Q<Button>("update"); } }
|
||||
private Button RemoveButton { get { return root.Q<Button>("remove"); } }
|
||||
private Button ViewDocButton { get { return root.Q<Button>("viewDocumentation"); } }
|
||||
private VisualElement DocumentationContainer { get { return root.Q<VisualElement>("documentationContainer"); } }
|
||||
private Button ViewChangelogButton { get { return root.Q<Button>("viewChangelog"); } }
|
||||
private VisualElement ChangelogContainer { get { return root.Q<VisualElement>("changeLogContainer"); } }
|
||||
private VisualElement ViewLicensesContainer { get { return root.Q<VisualElement>("viewLicensesContainer"); } }
|
||||
private Button ViewLicenses { get { return root.Q<Button>("viewLicenses"); } }
|
||||
private VisualElement UpdateContainer { get { return root.Q<VisualElement>("updateContainer"); } }
|
||||
private Alert DetailError { get { return root.Q<Alert>("detailError"); } }
|
||||
private ScrollView DetailView { get { return root.Q<ScrollView>("detailView"); } }
|
||||
private Label DetailModuleReference { get { return root.Q<Label>("detailModuleReference"); } }
|
||||
private Label DetailVersion { get { return root.Q<Label>("detailVersion"); }}
|
||||
private Label DetailAuthor { get { return root.Q<Label>("detailAuthor"); }}
|
||||
private Label VerifyLabel { get { return root.Q<Label>("tagVerify"); } }
|
||||
private VisualElement CustomContainer { get { return root.Q<VisualElement>("detailCustomContainer"); } }
|
||||
internal VisualElement GetTag(PackageTag tag) {return root.Q<VisualElement>("tag-" + tag); }
|
||||
private VisualElement UpdateDropdownContainer { get { return root.Q<VisualElement>("updateDropdownContainer"); } }
|
||||
internal VisualElement UpdateCombo { get { return root.Q<VisualElement>("updateCombo"); } }
|
||||
internal Button UpdateBuiltIn { get { return root.Q<Button>("updateBuiltIn"); } }
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f3e22b18940a4e828a5170574a3617e
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
internal static class PackageFiltering
|
||||
{
|
||||
private static bool FilterByText(PackageInfo info, string text)
|
||||
{
|
||||
if (info == null)
|
||||
return false;
|
||||
|
||||
if (info.Name.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)
|
||||
return true;
|
||||
|
||||
if (!string.IsNullOrEmpty(info.DisplayName) && info.DisplayName.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)
|
||||
return true;
|
||||
|
||||
if (!info.IsBuiltIn)
|
||||
{
|
||||
var prerelease = text.StartsWith("-") ? text.Substring(1) : text;
|
||||
if (info.Version != null && info.Version.Prerelease.IndexOf(prerelease, StringComparison.CurrentCultureIgnoreCase) >= 0)
|
||||
return true;
|
||||
|
||||
if (info.VersionWithoutTag.StartsWith(text, StringComparison.CurrentCultureIgnoreCase))
|
||||
return true;
|
||||
|
||||
if (info.IsPreview)
|
||||
{
|
||||
if (PackageTag.preview.ToString().IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (info.IsVerified)
|
||||
{
|
||||
if (PackageTag.verified.ToString().IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool FilterByText(Package package, string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return true;
|
||||
|
||||
var trimText = text.Trim(' ', '\t');
|
||||
trimText = Regex.Replace(trimText, @"[ ]{2,}", " ");
|
||||
return string.IsNullOrEmpty(trimText) || FilterByText(package.Current ?? package.Latest, trimText);
|
||||
}
|
||||
|
||||
private static bool FilterByText(PackageItem item, string text)
|
||||
{
|
||||
return item.package != null && FilterByText(item.package, text);
|
||||
}
|
||||
|
||||
public static void FilterPackageList(PackageList packageList)
|
||||
{
|
||||
PackageItem firstItem = null;
|
||||
PackageItem lastItem = null;
|
||||
var selectedItemInFilter = false;
|
||||
var selectedItem = packageList.selectedItem;
|
||||
var packageItems = packageList.Query<PackageItem>().ToList();
|
||||
foreach (var item in packageItems)
|
||||
{
|
||||
if (FilterByText(item, PackageSearchFilter.Instance.SearchText))
|
||||
{
|
||||
if (firstItem == null)
|
||||
firstItem = item;
|
||||
if (item == selectedItem)
|
||||
selectedItemInFilter = true;
|
||||
|
||||
UIUtils.SetElementDisplay(item, true);
|
||||
|
||||
if (lastItem != null)
|
||||
lastItem.nextItem = item;
|
||||
|
||||
item.previousItem = lastItem;
|
||||
item.nextItem = null;
|
||||
|
||||
lastItem = item;
|
||||
}
|
||||
else
|
||||
UIUtils.SetElementDisplay(item, false);
|
||||
}
|
||||
|
||||
if (firstItem == null)
|
||||
packageList.ShowNoResults();
|
||||
else
|
||||
packageList.ShowResults(selectedItemInFilter ? selectedItem : firstItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ffd2adf615994485991e37bacbf735c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
using System.Linq;
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class PackageGroupFactory : UxmlFactory<PackageGroup>
|
||||
{
|
||||
protected override PackageGroup DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new PackageGroup(bag.GetPropertyString("name"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class PackageGroup : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<PackageGroup> { }
|
||||
#endif
|
||||
|
||||
private readonly VisualElement root;
|
||||
internal readonly PackageGroupOrigins Origin;
|
||||
|
||||
public PackageGroup previousGroup;
|
||||
public PackageGroup nextGroup;
|
||||
|
||||
public PackageItem firstPackage;
|
||||
public PackageItem lastPackage;
|
||||
|
||||
public PackageGroup() : this(string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public PackageGroup(string groupName)
|
||||
{
|
||||
name = groupName;
|
||||
root = Resources.GetTemplate("PackageGroup.uxml");
|
||||
Add(root);
|
||||
|
||||
if (string.IsNullOrEmpty(groupName) || groupName != PackageGroupOrigins.BuiltInPackages.ToString())
|
||||
{
|
||||
HeaderTitle.text = "Packages";
|
||||
Origin = PackageGroupOrigins.Packages;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderTitle.text = "Built In Packages";
|
||||
Origin = PackageGroupOrigins.BuiltInPackages;
|
||||
}
|
||||
}
|
||||
|
||||
internal PackageItem AddPackage(Package package)
|
||||
{
|
||||
var packageItem = new PackageItem(package) {packageGroup = this};
|
||||
var lastItem = List.Children().LastOrDefault() as PackageItem;
|
||||
if (lastItem != null)
|
||||
{
|
||||
lastItem.nextItem = packageItem;
|
||||
packageItem.previousItem = lastItem;
|
||||
packageItem.nextItem = null;
|
||||
}
|
||||
|
||||
List.Add(packageItem);
|
||||
|
||||
if (firstPackage == null) firstPackage = packageItem;
|
||||
lastPackage = packageItem;
|
||||
|
||||
return packageItem;
|
||||
}
|
||||
|
||||
private VisualElement List { get { return root.Q<VisualElement>("groupContainer"); } }
|
||||
private Label HeaderTitle { get { return root.Q<Label>("headerTitle"); } }
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 760934a36e5f490db3c9fcaf497625a4
|
||||
timeCreated: 1508509771
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class PackageItemFactory : UxmlFactory<PackageItem>
|
||||
{
|
||||
protected override PackageItem DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new PackageItem();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class PackageItem : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<PackageItem> { }
|
||||
#endif
|
||||
|
||||
public static string SelectedClassName = "selected";
|
||||
|
||||
public event Action<PackageItem> OnSelected = delegate { };
|
||||
|
||||
private readonly VisualElement root;
|
||||
private string currentStateClass;
|
||||
public Package package { get; private set; }
|
||||
|
||||
public PackageItem previousItem;
|
||||
public PackageItem nextItem;
|
||||
|
||||
public PackageGroup packageGroup;
|
||||
|
||||
public PackageItem() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public PackageItem(Package package)
|
||||
{
|
||||
root = Resources.GetTemplate("PackageItem.uxml");
|
||||
Add(root);
|
||||
|
||||
root.AddManipulator(new Clickable(Select));
|
||||
SetItem(package);
|
||||
}
|
||||
|
||||
private void Select()
|
||||
{
|
||||
OnSelected(this);
|
||||
}
|
||||
|
||||
public void SetSelected(bool value)
|
||||
{
|
||||
if (value)
|
||||
PackageContainer.AddToClassList(SelectedClassName);
|
||||
else
|
||||
PackageContainer.RemoveFromClassList(SelectedClassName);
|
||||
|
||||
Spinner.InvertColor = value;
|
||||
}
|
||||
|
||||
private void SetItem(Package package)
|
||||
{
|
||||
var displayPackage = package != null ? package.VersionToDisplay : null;
|
||||
if (displayPackage == null)
|
||||
return;
|
||||
|
||||
this.package = package;
|
||||
OnPackageChanged();
|
||||
this.package.AddSignal.WhenOperation(OnPackageAdd);
|
||||
this.package.RemoveSignal.WhenOperation(OnPackageRemove);
|
||||
}
|
||||
|
||||
private void OnPackageRemove(IRemoveOperation operation)
|
||||
{
|
||||
operation.OnOperationError += error => StopSpinner();
|
||||
OnPackageUpdate();
|
||||
}
|
||||
|
||||
private void OnPackageAdd(IAddOperation operation)
|
||||
{
|
||||
operation.OnOperationError += error => StopSpinner();
|
||||
OnPackageUpdate();
|
||||
}
|
||||
|
||||
private void OnPackageChanged()
|
||||
{
|
||||
var displayPackage = package != null ? package.VersionToDisplay : null;
|
||||
if (displayPackage == null)
|
||||
return;
|
||||
|
||||
NameLabel.text = displayPackage.DisplayName;
|
||||
VersionLabel.text = displayPackage.Version.ToString();
|
||||
|
||||
var stateClass = GetIconStateId(displayPackage);
|
||||
if (displayPackage.State == PackageState.Outdated && package.LatestUpdate == package.Current)
|
||||
stateClass = GetIconStateId(PackageState.UpToDate);
|
||||
if (PackageCollection.Instance.GetPackageError(package) != null)
|
||||
stateClass = GetIconStateId(PackageState.Error);
|
||||
if (stateClass == GetIconStateId(PackageState.UpToDate) && package.Current != null)
|
||||
stateClass = "installed";
|
||||
|
||||
StateLabel.RemoveFromClassList(currentStateClass);
|
||||
StateLabel.AddToClassList(stateClass);
|
||||
|
||||
UIUtils.SetElementDisplay(VersionLabel, !displayPackage.IsBuiltIn);
|
||||
|
||||
currentStateClass = stateClass;
|
||||
if (displayPackage.State != PackageState.InProgress && Spinner.Started)
|
||||
StopSpinner();
|
||||
}
|
||||
|
||||
private void OnPackageUpdate()
|
||||
{
|
||||
StartSpinner();
|
||||
}
|
||||
|
||||
private void StartSpinner()
|
||||
{
|
||||
Spinner.Start();
|
||||
StateLabel.AddToClassList("no-icon");
|
||||
}
|
||||
|
||||
private void StopSpinner()
|
||||
{
|
||||
Spinner.Stop();
|
||||
StateLabel.RemoveFromClassList("no-icon");
|
||||
}
|
||||
|
||||
private Label NameLabel { get { return root.Q<Label>("packageName"); } }
|
||||
private Label StateLabel { get { return root.Q<Label>("packageState"); } }
|
||||
private Label VersionLabel { get { return root.Q<Label>("packageVersion"); } }
|
||||
private VisualElement PackageContainer { get { return root.Q<VisualElement>("packageContainer"); } }
|
||||
private LoadingSpinner Spinner { get { return root.Q<LoadingSpinner>("packageSpinner"); } }
|
||||
|
||||
public static string GetIconStateId(PackageInfo packageInfo)
|
||||
{
|
||||
if (packageInfo == null)
|
||||
return "";
|
||||
|
||||
return GetIconStateId(packageInfo.State);
|
||||
}
|
||||
|
||||
public static string GetIconStateId(PackageState state)
|
||||
{
|
||||
return state.ToString().ToLower();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c68ba5b432ef64e67ae0bf74960908a8
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
using UnityEngine.Experimental.UIElements;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
internal class PackageListFactory : UxmlFactory<PackageList>
|
||||
{
|
||||
protected override PackageList DoCreate(IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
return new PackageList();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class PackageList : VisualElement
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
internal new class UxmlFactory : UxmlFactory<PackageList> { }
|
||||
#endif
|
||||
|
||||
public event Action<Package> OnSelected = delegate { };
|
||||
public event Action OnLoaded = delegate { };
|
||||
public event Action OnFocusChange = delegate { };
|
||||
|
||||
private readonly VisualElement root;
|
||||
internal PackageItem selectedItem;
|
||||
private List<PackageGroup> Groups;
|
||||
|
||||
public PackageList()
|
||||
{
|
||||
Groups = new List<PackageGroup>();
|
||||
|
||||
root = Resources.GetTemplate("PackageList.uxml");
|
||||
Add(root);
|
||||
root.StretchToParentSize();
|
||||
|
||||
UIUtils.SetElementDisplay(Empty, false);
|
||||
UIUtils.SetElementDisplay(NoResult, false);
|
||||
|
||||
PackageCollection.Instance.OnPackagesChanged += SetPackages;
|
||||
|
||||
RegisterCallback<AttachToPanelEvent>(OnEnterPanel);
|
||||
RegisterCallback<DetachFromPanelEvent>(OnLeavePanel);
|
||||
|
||||
Reload();
|
||||
}
|
||||
|
||||
public void GrabFocus()
|
||||
{
|
||||
if (selectedItem == null)
|
||||
return;
|
||||
|
||||
selectedItem.Focus();
|
||||
}
|
||||
|
||||
public void ShowResults(PackageItem item)
|
||||
{
|
||||
NoResultText.text = string.Empty;
|
||||
UIUtils.SetElementDisplay(NoResult, false);
|
||||
|
||||
Select(item);
|
||||
|
||||
EditorApplication.delayCall += ScrollIfNeeded;
|
||||
|
||||
UpdateGroups();
|
||||
}
|
||||
|
||||
public void ShowNoResults()
|
||||
{
|
||||
NoResultText.text = string.Format("No results for \"{0}\"", PackageSearchFilter.Instance.SearchText);
|
||||
UIUtils.SetElementDisplay(NoResult, true);
|
||||
foreach (var group in Groups)
|
||||
{
|
||||
UIUtils.SetElementDisplay(group, false);
|
||||
}
|
||||
Select(null);
|
||||
OnSelected(null);
|
||||
}
|
||||
|
||||
private void UpdateGroups()
|
||||
{
|
||||
foreach (var group in Groups)
|
||||
{
|
||||
PackageItem firstPackage = null;
|
||||
PackageItem lastPackage = null;
|
||||
|
||||
var listGroup = group.Query<PackageItem>().ToList();
|
||||
foreach (var item in listGroup)
|
||||
{
|
||||
if (!item.visible)
|
||||
continue;
|
||||
|
||||
if (firstPackage == null) firstPackage = item;
|
||||
lastPackage = item;
|
||||
}
|
||||
|
||||
if (firstPackage == null && lastPackage == null)
|
||||
{
|
||||
UIUtils.SetElementDisplay(group, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
UIUtils.SetElementDisplay(group, true);
|
||||
group.firstPackage = firstPackage;
|
||||
group.lastPackage = lastPackage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnterPanel(AttachToPanelEvent e)
|
||||
{
|
||||
panel.visualTree.RegisterCallback<KeyDownEvent>(OnKeyDownShortcut);
|
||||
}
|
||||
|
||||
private void OnLeavePanel(DetachFromPanelEvent e)
|
||||
{
|
||||
panel.visualTree.UnregisterCallback<KeyDownEvent>(OnKeyDownShortcut);
|
||||
}
|
||||
|
||||
private void ScrollIfNeeded()
|
||||
{
|
||||
EditorApplication.delayCall -= ScrollIfNeeded;
|
||||
|
||||
if (selectedItem == null)
|
||||
return;
|
||||
|
||||
var minY = List.worldBound.yMin;
|
||||
var maxY = List.worldBound.yMax;
|
||||
var itemMinY = selectedItem.worldBound.yMin;
|
||||
var itemMaxY = selectedItem.worldBound.yMax;
|
||||
var scroll = List.scrollOffset;
|
||||
|
||||
if (itemMinY < minY)
|
||||
{
|
||||
scroll.y -= minY - itemMinY;
|
||||
if (scroll.y <= minY)
|
||||
scroll.y = 0;
|
||||
List.scrollOffset = scroll;
|
||||
}
|
||||
else if (itemMaxY > maxY)
|
||||
{
|
||||
scroll.y += itemMaxY - maxY;
|
||||
List.scrollOffset = scroll;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnKeyDownShortcut(KeyDownEvent evt)
|
||||
{
|
||||
if (selectedItem == null)
|
||||
return;
|
||||
|
||||
if (evt.keyCode == KeyCode.Tab)
|
||||
{
|
||||
OnFocusChange();
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.keyCode == KeyCode.UpArrow)
|
||||
{
|
||||
if (selectedItem.previousItem != null)
|
||||
{
|
||||
Select(selectedItem.previousItem);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem.packageGroup.previousGroup != null && selectedItem.packageGroup.previousGroup.visible)
|
||||
{
|
||||
Select(selectedItem.packageGroup.previousGroup.lastPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.keyCode == KeyCode.DownArrow)
|
||||
{
|
||||
if (selectedItem.nextItem != null)
|
||||
{
|
||||
Select(selectedItem.nextItem);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem.packageGroup.nextGroup != null && selectedItem.packageGroup.nextGroup.visible)
|
||||
{
|
||||
Select(selectedItem.packageGroup.nextGroup.firstPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.keyCode == KeyCode.PageUp)
|
||||
{
|
||||
if (selectedItem.packageGroup != null)
|
||||
{
|
||||
if (selectedItem == selectedItem.packageGroup.lastPackage && selectedItem != selectedItem.packageGroup.firstPackage)
|
||||
{
|
||||
Select(selectedItem.packageGroup.firstPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem == selectedItem.packageGroup.firstPackage && selectedItem.packageGroup.previousGroup != null && selectedItem.packageGroup.previousGroup.visible)
|
||||
{
|
||||
Select(selectedItem.packageGroup.previousGroup.lastPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem != selectedItem.packageGroup.lastPackage && selectedItem != selectedItem.packageGroup.firstPackage)
|
||||
{
|
||||
Select(selectedItem.packageGroup.firstPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
}
|
||||
evt.StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.keyCode == KeyCode.PageDown)
|
||||
{
|
||||
if (selectedItem.packageGroup != null)
|
||||
{
|
||||
if (selectedItem == selectedItem.packageGroup.firstPackage && selectedItem != selectedItem.packageGroup.lastPackage)
|
||||
{
|
||||
Select(selectedItem.packageGroup.lastPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem == selectedItem.packageGroup.lastPackage && selectedItem.packageGroup.nextGroup != null && selectedItem.packageGroup.nextGroup.visible)
|
||||
{
|
||||
Select(selectedItem.packageGroup.nextGroup.firstPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
else if (selectedItem != selectedItem.packageGroup.firstPackage && selectedItem != selectedItem.packageGroup.lastPackage)
|
||||
{
|
||||
Select(selectedItem.packageGroup.lastPackage);
|
||||
ScrollIfNeeded();
|
||||
}
|
||||
}
|
||||
evt.StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
private void Reload()
|
||||
{
|
||||
// Force a re-init to initial condition
|
||||
PackageCollection.Instance.UpdatePackageCollection();
|
||||
SelectLastSelection();
|
||||
}
|
||||
|
||||
private void ClearAll()
|
||||
{
|
||||
List.Clear();
|
||||
Groups.Clear();
|
||||
|
||||
UIUtils.SetElementDisplay(Empty, false);
|
||||
UIUtils.SetElementDisplay(NoResult, false);
|
||||
}
|
||||
|
||||
private void SetPackages(IEnumerable<Package> packages)
|
||||
{
|
||||
if (PackageCollection.Instance.Filter == PackageFilter.Modules)
|
||||
{
|
||||
packages = packages.Where(pkg => pkg.IsBuiltIn);
|
||||
}
|
||||
else if (PackageCollection.Instance.Filter== PackageFilter.All)
|
||||
{
|
||||
packages = packages.Where(pkg => !pkg.IsBuiltIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
packages = packages.Where(pkg => !pkg.IsBuiltIn);
|
||||
packages = packages.Where(pkg => pkg.Current != null);
|
||||
}
|
||||
|
||||
OnLoaded();
|
||||
ClearAll();
|
||||
|
||||
var packagesGroup = new PackageGroup(PackageGroupOrigins.Packages.ToString());
|
||||
Groups.Add(packagesGroup);
|
||||
List.Add(packagesGroup);
|
||||
packagesGroup.previousGroup = null;
|
||||
|
||||
var builtInGroup = new PackageGroup(PackageGroupOrigins.BuiltInPackages.ToString());
|
||||
Groups.Add(builtInGroup);
|
||||
List.Add(builtInGroup);
|
||||
|
||||
if ((PackageCollection.Instance.Filter & PackageFilter.Modules) == PackageFilter.Modules)
|
||||
{
|
||||
packagesGroup.nextGroup = builtInGroup;
|
||||
builtInGroup.previousGroup = packagesGroup;
|
||||
builtInGroup.nextGroup = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
packagesGroup.nextGroup = null;
|
||||
UIUtils.SetElementDisplay(builtInGroup, false);
|
||||
}
|
||||
|
||||
var lastSelection = PackageCollection.Instance.SelectedPackage;
|
||||
Select(null);
|
||||
|
||||
PackageItem defaultSelection = null;
|
||||
|
||||
foreach (var package in packages.OrderBy(pkg => pkg.Versions.FirstOrDefault() == null ? pkg.Name : pkg.Versions.FirstOrDefault().DisplayName))
|
||||
{
|
||||
var item = AddPackage(package);
|
||||
|
||||
if (null == selectedItem && defaultSelection == null)
|
||||
defaultSelection = item;
|
||||
|
||||
if (null == selectedItem && !string.IsNullOrEmpty(lastSelection) && package.Name.Equals(lastSelection))
|
||||
Select(item);
|
||||
}
|
||||
|
||||
if (selectedItem == null)
|
||||
Select(defaultSelection);
|
||||
|
||||
PackageFiltering.FilterPackageList(this);
|
||||
}
|
||||
|
||||
public void SelectLastSelection()
|
||||
{
|
||||
var lastSelection = PackageCollection.Instance.SelectedPackage;
|
||||
if (lastSelection == null)
|
||||
return;
|
||||
|
||||
var list = List.Query<PackageItem>().ToList();
|
||||
PackageItem defaultSelection = null;
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (defaultSelection == null)
|
||||
defaultSelection = item;
|
||||
|
||||
if (!string.IsNullOrEmpty(lastSelection) && item.package.Name.Equals(lastSelection))
|
||||
{
|
||||
defaultSelection = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
selectedItem = null;
|
||||
Select(defaultSelection);
|
||||
}
|
||||
|
||||
private PackageItem AddPackage(Package package)
|
||||
{
|
||||
var groupName = package.Latest != null ? package.Latest.Group : package.Current.Group;
|
||||
var group = GetOrCreateGroup(groupName);
|
||||
var packageItem = group.AddPackage(package);
|
||||
|
||||
packageItem.OnSelected += Select;
|
||||
|
||||
return packageItem;
|
||||
}
|
||||
|
||||
private PackageGroup GetOrCreateGroup(string groupName)
|
||||
{
|
||||
foreach (var g in Groups)
|
||||
{
|
||||
if (g.name == groupName)
|
||||
return g;
|
||||
}
|
||||
|
||||
var group = new PackageGroup(groupName);
|
||||
var latestGroup = Groups.LastOrDefault();
|
||||
Groups.Add(group);
|
||||
List.Add(group);
|
||||
|
||||
group.previousGroup = null;
|
||||
if (latestGroup != null)
|
||||
{
|
||||
latestGroup.nextGroup = group;
|
||||
group.previousGroup = latestGroup;
|
||||
group.nextGroup = null;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
private void Select(PackageItem packageItem)
|
||||
{
|
||||
if (packageItem == selectedItem)
|
||||
return;
|
||||
|
||||
var selectedPackageName = packageItem != null ? packageItem.package.Name : null;
|
||||
PackageCollection.Instance.SelectedPackage = selectedPackageName;
|
||||
|
||||
if (selectedItem != null)
|
||||
selectedItem.SetSelected(false); // Clear Previous selection
|
||||
|
||||
selectedItem = packageItem;
|
||||
if (selectedItem == null)
|
||||
{
|
||||
OnSelected(null);
|
||||
return;
|
||||
}
|
||||
|
||||
selectedItem.SetSelected(true);
|
||||
ScrollIfNeeded();
|
||||
OnSelected(selectedItem.package);
|
||||
}
|
||||
|
||||
private ScrollView List { get { return root.Q<ScrollView>("scrollView"); } }
|
||||
private VisualElement Empty { get { return root.Q<VisualElement>("emptyArea"); } }
|
||||
private VisualElement NoResult { get { return root.Q<VisualElement>("noResult"); } }
|
||||
private Label NoResultText { get { return root.Q<Label>("noResultText"); } }
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d77b2d58287d46a6a61f12c861bfc2f
|
||||
timeCreated: 1502224642
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UnityEditor.PackageManager.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Package Manager UI Extensions
|
||||
/// </summary>
|
||||
public static class PackageManagerExtensions
|
||||
{
|
||||
internal static List<IPackageManagerExtension> Extensions { get { return extensions ?? (extensions = new List<IPackageManagerExtension>()); } }
|
||||
private static List<IPackageManagerExtension> extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new Package Manager UI extension
|
||||
/// </summary>
|
||||
/// <param name="extension">A Package Manager UI extension</param>
|
||||
public static void RegisterExtension(IPackageManagerExtension extension)
|
||||
{
|
||||
if (extension == null)
|
||||
return;
|
||||
|
||||
Extensions.Add(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user