Files
KopMap/Assets/AmplifyShaderEditor/Plugins/Editor/Utils/ASEPackageManagerHelper.cs

464 lines
16 KiB
C#
Raw Normal View History

2025-04-03 02:30:16 +08:00
// Amplify Shader Editor - Visual Shader Editing Tool
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
namespace AmplifyShaderEditor
{
public enum ASEImportFlags
{
None = 0,
URP = 1 << 0,
HDRP = 1 << 1,
Both = URP | HDRP
}
public static class AssetDatabaseEX
{
private static System.Type type = null;
public static System.Type Type { get { return ( type == null ) ? type = System.Type.GetType( "UnityEditor.AssetDatabase, UnityEditor" ) : type; } }
public static void ImportPackageImmediately( string packagePath )
{
AssetDatabaseEX.Type.InvokeMember( "ImportPackageImmediately", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, new object[] { packagePath } );
}
}
public enum ASESRPBaseline
{
ASE_SRP_INVALID = 0,
ASE_SRP_10 = 100000,
ASE_SRP_11 = 110000,
ASE_SRP_12 = 120000,
ASE_SRP_13 = 130000,
ASE_SRP_14 = 140000,
ASE_SRP_15 = 150000,
ASE_SRP_16 = 160000,
ASE_SRP_17 = 170000
}
public class ASESRPPackageDesc
{
public ASESRPBaseline baseline = ASESRPBaseline.ASE_SRP_INVALID;
public string guidURP = string.Empty;
public string guidHDRP = string.Empty;
public ASESRPPackageDesc( ASESRPBaseline baseline, string guidURP, string guidHDRP )
{
this.baseline = baseline;
this.guidURP = guidURP;
this.guidHDRP = guidHDRP;
}
}
[Serializable]
[InitializeOnLoad]
public static class ASEPackageManagerHelper
{
private static string URPPackageId = "com.unity.render-pipelines.universal";
private static string HDRPPackageId = "com.unity.render-pipelines.high-definition";
private static string NewVersionDetectedFormat = "A new {0} version {1} was detected and new templates are being imported.\nPlease hit the Update button on your ASE canvas to recompile your shader under the newest version.";
private static string PackageBaseFormat = "ASE_PkgBase_{0}_{1}";
private static string PackageCRCFormat = "ASE_PkgCRC_{0}_{1}";
private static string SRPKeywordFormat = "ASE_SRP_VERSION {0}";
private static string ASEVersionKeywordFormat = "ASE_VERSION {0}";
private static Dictionary<int, ASESRPPackageDesc> m_srpPackageSupport = new Dictionary<int,ASESRPPackageDesc>()
{
{ ( int )ASESRPBaseline.ASE_SRP_10, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_10, "b460b52e6c1feae45b70b7ddc2c45bd6", "2243c8b4e1ab6914995699133f67ab5a" ) },
{ ( int )ASESRPBaseline.ASE_SRP_11, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_11, "b460b52e6c1feae45b70b7ddc2c45bd6", "2243c8b4e1ab6914995699133f67ab5a" ) },
{ ( int )ASESRPBaseline.ASE_SRP_12, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_12, "57fcea0ed8b5eb347923c4c21fa31b57", "9a5e61a8b3421b944863d0946e32da0a" ) },
{ ( int )ASESRPBaseline.ASE_SRP_13, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_13, "57fcea0ed8b5eb347923c4c21fa31b57", "9a5e61a8b3421b944863d0946e32da0a" ) },
{ ( int )ASESRPBaseline.ASE_SRP_14, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_14, "2e9da72e7e3196146bf7d27450013734", "89f0b84148d149d4d96b838d7ef60e92" ) },
{ ( int )ASESRPBaseline.ASE_SRP_15, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_15, "0904cdf24ddcd5042b024326476220d5", "19939ee2cdb76e0489b1b8cd4bed7f3d" ) },
{ ( int )ASESRPBaseline.ASE_SRP_16, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_16, "929783250050f8a448821b6ca1f2c578", "70777e8ce9f3c8d4a8182ca2f965cdb2" ) },
{ ( int )ASESRPBaseline.ASE_SRP_17, new ASESRPPackageDesc( ASESRPBaseline.ASE_SRP_17, "89da50d95d149b744bf10bd27babcf79", "daf511a6dae20e641a9d69d025f023e4" ) },
};
private static Shader m_lateShader;
private static Material m_lateMaterial;
private static AmplifyShaderFunction m_lateShaderFunction;
private static ListRequest m_packageListRequest = null;
private static UnityEditor.PackageManager.PackageInfo m_urpPackageInfo;
private static UnityEditor.PackageManager.PackageInfo m_hdrpPackageInfo;
public static bool FoundURPVersion { get { return m_urpPackageInfo != null; } }
public static bool FoundHDRPVersion { get { return m_hdrpPackageInfo != null; } }
private static bool m_lateImport = false;
private static string m_latePackageToImport;
private static bool m_requireUpdateList = false;
private static ASEImportFlags m_importingPackage = ASEImportFlags.None;
public static bool CheckImporter { get { return m_importingPackage != ASEImportFlags.None; } }
public static bool IsProcessing { get { return m_requireUpdateList && m_importingPackage == ASEImportFlags.None; } }
private static ASESRPBaseline m_currentURPBaseline = ASESRPBaseline.ASE_SRP_INVALID;
private static ASESRPBaseline m_currentHDRPBaseline = ASESRPBaseline.ASE_SRP_INVALID;
public static ASESRPBaseline CurrentURPBaseline { get { return m_currentURPBaseline; } }
public static ASESRPBaseline CurrentHDRPBaseline { get { return m_currentHDRPBaseline; } }
private static int m_packageURPVersion = -1; // @diogo: starts as missing
private static int m_packageHDRPVersion = -1;
public static int PackageSRPVersion { get { return ( m_packageHDRPVersion >= m_packageURPVersion ) ? m_packageHDRPVersion : m_packageURPVersion; } }
public static int CurrentSRPVersion { get { return UIUtils.CurrentWindow.MainGraphInstance.IsSRP ? PackageSRPVersion : -1; } }
private static string m_projectName = null;
private static string ProjectName
{
get
{
if ( string.IsNullOrEmpty( m_projectName ) )
{
string[] s = Application.dataPath.Split( '/' );
m_projectName = s[ s.Length - 2 ];
}
return m_projectName;
}
}
static ASEPackageManagerHelper()
{
RequestInfo( true );
}
static void WaitForPackageListBeforeUpdating()
{
if ( m_packageListRequest.IsCompleted )
{
Update();
EditorApplication.update -= WaitForPackageListBeforeUpdating;
}
}
public static void RequestInfo( bool updateWhileWaiting = false )
{
if ( !m_requireUpdateList && m_importingPackage == ASEImportFlags.None )
{
m_requireUpdateList = true;
m_packageListRequest = UnityEditor.PackageManager.Client.List( true );
if ( updateWhileWaiting )
{
EditorApplication.update += WaitForPackageListBeforeUpdating;
}
}
}
static void FailedPackageImport( string packageName, string errorMessage )
{
FinishImporter();
}
static void CancelledPackageImport( string packageName )
{
FinishImporter();
}
static void CompletedPackageImport( string packageName )
{
FinishImporter();
}
public static void CheckLatePackageImport()
{
if ( !Application.isPlaying && m_lateImport && !string.IsNullOrEmpty( m_latePackageToImport ) )
{
m_lateImport = false;
StartImporting( m_latePackageToImport );
m_latePackageToImport = string.Empty;
}
}
public static void StartImporting( string packagePath )
{
if ( !Preferences.Project.AutoSRP )
{
m_importingPackage = ASEImportFlags.None;
return;
}
if ( Application.isPlaying )
{
if ( !m_lateImport )
{
m_lateImport = true;
m_latePackageToImport = packagePath;
Debug.LogWarning( "Amplify Shader Editor requires the \"" + packagePath + "\" package to be installed in order to continue. Please exit Play mode to proceed." );
}
return;
}
AssetDatabase.importPackageCancelled += CancelledPackageImport;
AssetDatabase.importPackageCompleted += CompletedPackageImport;
AssetDatabase.importPackageFailed += FailedPackageImport;
AssetDatabase.ImportPackage( packagePath, false );
//AssetDatabaseEX.ImportPackageImmediately( packagePath );
}
public static void FinishImporter()
{
m_importingPackage = ASEImportFlags.None;
AssetDatabase.importPackageCancelled -= CancelledPackageImport;
AssetDatabase.importPackageCompleted -= CompletedPackageImport;
AssetDatabase.importPackageFailed -= FailedPackageImport;
}
public static void SetupLateShader( Shader shader )
{
if ( shader == null )
return;
//If a previous delayed object is pending discard it and register the new one
// So the last selection will be the choice of opening
//This can happen when trying to open an ASE canvas while importing templates or in play mode
if ( m_lateShader != null )
{
EditorApplication.delayCall -= LateShaderOpener;
}
RequestInfo();
m_lateShader = shader;
EditorApplication.delayCall += LateShaderOpener;
}
public static void LateShaderOpener()
{
Update();
if ( IsProcessing )
{
EditorApplication.delayCall += LateShaderOpener;
}
else
{
AmplifyShaderEditorWindow.ConvertShaderToASE( m_lateShader );
m_lateShader = null;
}
}
public static void SetupLateMaterial( Material material )
{
if ( material == null )
return;
//If a previous delayed object is pending discard it and register the new one
// So the last selection will be the choice of opening
//This can happen when trying to open an ASE canvas while importing templates or in play mode
if ( m_lateMaterial != null )
{
EditorApplication.delayCall -= LateMaterialOpener;
}
RequestInfo();
m_lateMaterial = material;
EditorApplication.delayCall += LateMaterialOpener;
}
public static void LateMaterialOpener()
{
Update();
if ( IsProcessing )
{
EditorApplication.delayCall += LateMaterialOpener;
}
else
{
AmplifyShaderEditorWindow.LoadMaterialToASE( m_lateMaterial );
m_lateMaterial = null;
}
}
public static void SetupLateShaderFunction( AmplifyShaderFunction shaderFunction )
{
if ( shaderFunction == null )
return;
//If a previous delayed object is pending discard it and register the new one
// So the last selection will be the choice of opening
//This can happen when trying to open an ASE canvas while importing templates or in play mode
if ( m_lateShaderFunction != null )
{
EditorApplication.delayCall -= LateShaderFunctionOpener;
}
RequestInfo();
m_lateShaderFunction = shaderFunction;
EditorApplication.delayCall += LateShaderFunctionOpener;
}
public static void LateShaderFunctionOpener()
{
Update();
if ( IsProcessing )
{
EditorApplication.delayCall += LateShaderFunctionOpener;
}
else
{
AmplifyShaderEditorWindow.LoadShaderFunctionToASE( m_lateShaderFunction, false );
m_lateShaderFunction = null;
}
}
private static readonly string SemVerPattern = @"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$";
private static int PackageVersionStringToCode( string version, out int major, out int minor, out int patch )
{
MatchCollection matches = Regex.Matches( version, SemVerPattern, RegexOptions.Multiline );
bool validMatch = ( matches.Count > 0 && matches[ 0 ].Groups.Count >= 4 );
major = validMatch ? int.Parse( matches[ 0 ].Groups[ 1 ].Value ) : 99;
minor = validMatch ? int.Parse( matches[ 0 ].Groups[ 2 ].Value ) : 99;
patch = validMatch ? int.Parse( matches[ 0 ].Groups[ 3 ].Value ) : 99;
int versionCode;
versionCode = major * 10000;
versionCode += minor * 100;
versionCode += patch;
return versionCode;
}
private static void CodeToPackageVersionElements( int versionCode, out int major, out int minor, out int patch )
{
major = versionCode / 10000;
minor = versionCode / 100 - major * 100;
patch = versionCode - ( versionCode / 100 ) * 100;
}
private static int PackageVersionElementsToCode( int major, int minor, int patch )
{
return major * 10000 + minor * 100 + patch;
}
private static void CheckPackageImport( ASEImportFlags flag, ASESRPBaseline baseline, string guid, string version )
{
Debug.Assert( flag == ASEImportFlags.HDRP || flag == ASEImportFlags.URP );
string path = AssetDatabase.GUIDToAssetPath( guid );
if ( !string.IsNullOrEmpty( path ) && File.Exists( path ) )
{
uint currentCRC = IOUtils.CRC32( File.ReadAllBytes( path ) );
string srpName = flag.ToString();
string packageBaseKey = string.Format( PackageBaseFormat, srpName, ProjectName );
string packageCRCKey = string.Format( PackageCRCFormat, srpName, ProjectName );
ASESRPBaseline savedBaseline = ( ASESRPBaseline )EditorPrefs.GetInt( packageBaseKey );
uint savedCRC = ( uint )EditorPrefs.GetInt( packageCRCKey, 0 );
bool foundNewVersion = ( savedBaseline != baseline ) || ( savedCRC != currentCRC );
EditorPrefs.SetInt( packageBaseKey, ( int )baseline );
EditorPrefs.SetInt( packageCRCKey, ( int )currentCRC );
string testPath0 = string.Empty;
string testPath1 = string.Empty;
switch ( flag )
{
case ASEImportFlags.URP:
{
testPath0 = AssetDatabase.GUIDToAssetPath( TemplatesManager.URPLitGUID );
testPath1 = AssetDatabase.GUIDToAssetPath( TemplatesManager.URPUnlitGUID );
break;
}
case ASEImportFlags.HDRP:
{
testPath0 = AssetDatabase.GUIDToAssetPath( TemplatesManager.HDRPLitGUID );
testPath1 = AssetDatabase.GUIDToAssetPath( TemplatesManager.HDRPUnlitGUID );
break;
}
}
if ( !File.Exists( testPath0 ) || !File.Exists( testPath1 ) || foundNewVersion )
{
if ( foundNewVersion )
{
Debug.Log( string.Format( NewVersionDetectedFormat, srpName, version ) );
}
m_importingPackage |= flag;
StartImporting( path );
}
}
}
public static void Update()
{
CheckLatePackageImport();
if ( m_requireUpdateList && m_importingPackage == ASEImportFlags.None )
{
if ( m_packageListRequest != null && m_packageListRequest.IsCompleted && m_packageListRequest.Result != null )
{
m_requireUpdateList = false;
foreach ( UnityEditor.PackageManager.PackageInfo pi in m_packageListRequest.Result )
{
int version = PackageVersionStringToCode( pi.version, out int major, out int minor, out int patch );
int baseline = PackageVersionElementsToCode( major, 0, 0 );
ASESRPPackageDesc match;
if ( pi.name.Equals( URPPackageId ) && m_srpPackageSupport.TryGetValue( baseline, out match ) )
{
// Universal Rendering Pipeline
m_currentURPBaseline = match.baseline;
m_packageURPVersion = version;
m_urpPackageInfo = pi;
CheckPackageImport( ASEImportFlags.URP, match.baseline, match.guidURP, pi.version );
}
else if ( pi.name.Equals( HDRPPackageId ) && m_srpPackageSupport.TryGetValue( baseline, out match ) )
{
// High-Definition Rendering Pipeline
m_currentHDRPBaseline = match.baseline;
m_packageHDRPVersion = version;
m_hdrpPackageInfo = pi;
CheckPackageImport( ASEImportFlags.HDRP, match.baseline, match.guidHDRP, pi.version );
}
}
}
}
}
public static void SetASEVersionInfoOnDataCollector( ref MasterNodeDataCollector dataCollector )
{
if ( m_requireUpdateList )
{
Update();
}
dataCollector.AddToDirectives( string.Format( ASEVersionKeywordFormat, VersionInfo.FullNumber ), -1, AdditionalLineType.Define );
}
public static void SetSRPInfoOnDataCollector( ref MasterNodeDataCollector dataCollector )
{
if ( m_requireUpdateList )
{
Update();
}
if ( dataCollector.CurrentSRPType == TemplateSRPType.HDRP )
{
dataCollector.AddToDirectives( string.Format( SRPKeywordFormat, m_packageHDRPVersion ), -1, AdditionalLineType.Define );
}
else if ( dataCollector.CurrentSRPType == TemplateSRPType.URP )
{
dataCollector.AddToDirectives( string.Format( SRPKeywordFormat, m_packageURPVersion ), -1, AdditionalLineType.Define );
}
}
}
}