464 lines
16 KiB
C#
464 lines
16 KiB
C#
// 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 );
|
|
}
|
|
}
|
|
}
|
|
}
|