summaryrefslogtreecommitdiff
path: root/Assets/AmplifyShaderEditor/Plugins/Editor/Templates
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/AmplifyShaderEditor/Plugins/Editor/Templates')
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs31
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs837
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs31
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs193
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs31
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs102
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs184
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs125
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs1178
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs2056
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs217
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs391
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs274
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs2374
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs236
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs234
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs59
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs258
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs750
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs50
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs497
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs62
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs541
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs1248
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs3113
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs328
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs272
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs958
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs69
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs174
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs300
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs862
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs631
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs167
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs157
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs121
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs107
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs44
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs650
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs168
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs440
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs190
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs272
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs782
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs904
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta12
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs662
-rw-r--r--Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta12
92 files changed, 23882 insertions, 0 deletions
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs
new file mode 100644
index 00000000..fb4d7569
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs
@@ -0,0 +1,31 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateAdditionalDefinesHelper : TemplateAdditionalParentHelper
+ {
+ public TemplateAdditionalDefinesHelper() : base( "Additional Defines" )
+ {
+ m_helpBoxMessage = "Please add your defines without the #define keywords";
+ }
+
+ public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer )
+ {
+ for( int i = 0; i < m_additionalItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasDefine( m_additionalItems[ i ] ) )
+ dataCollector.AddToDefines( -1, m_additionalItems[ i ] );
+ }
+
+ for( int i = 0; i < m_outsideItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasDefine( m_outsideItems[ i ] ) )
+ dataCollector.AddToDefines( -1, m_outsideItems[ i ] );
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta
new file mode 100644
index 00000000..3194a2ab
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDefinesHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 35a7fdfdb9a6b0048aa322a9fe58a371
+timeCreated: 1520275148
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs
new file mode 100644
index 00000000..31c03b59
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs
@@ -0,0 +1,837 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using UnityEditorInternal;
+
+namespace AmplifyShaderEditor
+{
+ public enum AdditionalLineType
+ {
+ Include,
+ Define,
+ Pragma,
+ Custom
+ }
+
+ public enum AdditionalContainerOrigin
+ {
+ Native,
+ ShaderFunction,
+ Custom
+ }
+
+
+ [Serializable]
+ public class AdditionalDirectiveContainerSaveItem
+ {
+ public AdditionalLineType LineType = AdditionalLineType.Include;
+ public string LineValue = string.Empty;
+ public bool GUIDToggle = false;
+ public string GUIDValue = string.Empty;
+ public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom;
+ public AdditionalDirectiveContainerSaveItem( AdditionalLineType lineType, string lineValue, bool guidToggle, string guidValue, AdditionalContainerOrigin origin )
+ {
+ LineType = lineType;
+ LineValue = lineValue;
+ GUIDToggle = guidToggle;
+ GUIDValue = guidValue;
+ Origin = origin;
+ }
+
+ public AdditionalDirectiveContainerSaveItem( AdditionalDirectiveContainer container )
+ {
+ LineType = container.LineType;
+ LineValue = container.LineValue;
+ GUIDToggle = container.GUIDToggle;
+ GUIDValue = container.GUIDValue;
+ Origin = container.Origin;
+ }
+ }
+
+ [Serializable]
+ public class AdditionalDirectiveContainer : ScriptableObject
+ {
+ public AdditionalLineType LineType = AdditionalLineType.Include;
+ public string LineValue = string.Empty;
+ public bool GUIDToggle = false;
+ public string GUIDValue = string.Empty;
+ public AdditionalContainerOrigin Origin = AdditionalContainerOrigin.Custom;
+ public TextAsset LibObject = null;
+ public string OwnerId = string.Empty;
+
+ public void Init( string ownerId, AdditionalDirectiveContainer item )
+ {
+ LineType = item.LineType;
+ LineValue = item.LineValue;
+ GUIDToggle = item.GUIDToggle;
+ GUIDValue = item.GUIDValue;
+ Origin = item.Origin;
+ LibObject = item.LibObject;
+ OwnerId = ownerId;
+ }
+
+ public void Init( AdditionalDirectiveContainerSaveItem item )
+ {
+ LineType = item.LineType;
+ LineValue = item.LineValue;
+ GUIDToggle = item.GUIDToggle;
+ GUIDValue = item.GUIDValue;
+ Origin = item.Origin;
+ if( GUIDToggle )
+ {
+ LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( GUIDValue ) );
+ }
+ }
+
+ public void OnDestroy()
+ {
+ //Debug.Log( "Destoying directives" );
+ LibObject = null;
+ }
+
+ public string Value
+ {
+ get
+ {
+ switch( LineType )
+ {
+ case AdditionalLineType.Include:
+ {
+ if( GUIDToggle )
+ {
+ string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue );
+ if( !string.IsNullOrEmpty( shaderPath ) )
+ return shaderPath;
+ }
+ return LineValue;
+ }
+ case AdditionalLineType.Define: return LineValue;
+ case AdditionalLineType.Pragma: return LineValue;
+ }
+ return LineValue;
+ }
+ }
+
+ public string FormattedValue
+ {
+ get
+ {
+ switch( LineType )
+ {
+ case AdditionalLineType.Include:
+ {
+ if( GUIDToggle )
+ {
+ string shaderPath = AssetDatabase.GUIDToAssetPath( GUIDValue );
+ if( !string.IsNullOrEmpty( shaderPath ) )
+ return string.Format( Constants.IncludeFormat, shaderPath );
+ }
+
+ return string.Format( Constants.IncludeFormat, LineValue );
+ }
+ case AdditionalLineType.Define:
+ return string.Format( Constants.DefineFormat, LineValue );
+ case AdditionalLineType.Pragma:
+ return string.Format( Constants.PragmaFormat, LineValue );
+ }
+ return LineValue;
+ }
+ }
+ }
+
+
+
+ public enum ReordableAction
+ {
+ None,
+ Add,
+ Remove
+ }
+
+ [Serializable]
+ public sealed class TemplateAdditionalDirectivesHelper : TemplateModuleParent
+ {
+ private string NativeFoldoutStr = "Native";
+
+ [SerializeField]
+ private List<AdditionalDirectiveContainer> m_additionalDirectives = new List<AdditionalDirectiveContainer>();
+
+ [SerializeField]
+ private List<AdditionalDirectiveContainer> m_shaderFunctionDirectives = new List<AdditionalDirectiveContainer>();
+
+ [SerializeField]
+ private List<string> m_nativeDirectives = new List<string>();
+
+ [SerializeField]
+ private int m_nativeDirectivesIndex = -1;
+
+ [SerializeField]
+ private bool m_nativeDirectivesFoldout = false;
+
+ //ONLY USED BY SHADER FUNCTIONS
+ // Since AdditionalDirectiveContainer must be a ScriptableObject because of serialization shenanigans it will not serialize the info correctly into the shader function when saving it into a file ( it only saves the id )
+ // For it to properly work, each AdditionalDirectiveContainer should be added to the SF asset, but that would make it to have children ( which are seen on the project inspector )
+ // Must revisit this later on and come up with a proper solution
+ [SerializeField]
+ private List<AdditionalDirectiveContainerSaveItem> m_directivesSaveItems = new List<AdditionalDirectiveContainerSaveItem>();
+
+
+ private ReordableAction m_actionType = ReordableAction.None;
+ private int m_actionIndex = 0;
+ private ReorderableList m_reordableList = null;
+ private GUIStyle m_propertyAdjustment;
+ private UndoParentNode m_currOwner;
+ private Rect m_nativeRect = Rect.zero;
+
+ public TemplateAdditionalDirectivesHelper( string moduleName ) : base( moduleName ) { }
+
+ //public void AddShaderFunctionItem( AdditionalLineType type, string item )
+ //{
+ // UpdateShaderFunctionDictionary();
+ // string id = type + item;
+ // if( !m_shaderFunctionDictionary.ContainsKey( id ) )
+ // {
+ // AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ // newItem.LineType = type;
+ // newItem.LineValue = item;
+ // newItem.hideFlags = HideFlags.HideAndDontSave;
+ // m_shaderFunctionDirectives.Add( newItem );
+ // m_shaderFunctionDictionary.Add( id, newItem );
+ // }
+ //}
+
+ public void AddShaderFunctionItems( string ownerOutputId, List<AdditionalDirectiveContainer> functionList )
+ {
+ RemoveShaderFunctionItems( ownerOutputId );
+ if( functionList.Count > 0 )
+ {
+ for( int i = 0; i < functionList.Count; i++ )
+ {
+ AdditionalDirectiveContainer item = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ item.Init( ownerOutputId, functionList[ i ] );
+ m_shaderFunctionDirectives.Add( item );
+ }
+ }
+ //if( functionList.Count > 0 )
+ //{
+
+ // m_shaderFunctionDirectives.AddRange( functionList );
+ //}
+ }
+
+ public void RemoveShaderFunctionItems( string ownerOutputId/*, List<AdditionalDirectiveContainer> functionList */)
+ {
+ List<AdditionalDirectiveContainer> list = m_shaderFunctionDirectives.FindAll( ( x ) => x.OwnerId.Equals( ownerOutputId ));
+ for( int i = 0; i < list.Count; i++ )
+ {
+ m_shaderFunctionDirectives.Remove( list[ i ] );
+ ScriptableObject.DestroyImmediate( list[ i ] );
+ }
+ list.Clear();
+ list = null;
+
+ //for( int i = 0; i < functionList.Count; i++ )
+ //{
+ // m_shaderFunctionDirectives.Remove( functionList[ i ] );
+ //}
+ }
+
+ //public void RemoveShaderFunctionItem( AdditionalLineType type, string item )
+ //{
+ // m_shaderFunctionDirectives.RemoveAll( x => x.LineType == type && x.LineValue.Equals( item ) );
+ //}
+
+ public void AddItems( AdditionalLineType type, List<string> items )
+ {
+ int count = items.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.LineType = type;
+ newItem.LineValue = items[ i ];
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ m_additionalDirectives.Add( newItem );
+ }
+ UpdateNativeIndex();
+ }
+
+ public void AddNativeContainer()
+ {
+ if( m_nativeDirectives.Count > 0 )
+ {
+ if( m_additionalDirectives.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) ) == -1 )
+ {
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.Origin = AdditionalContainerOrigin.Native;
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ //m_additionalDirectives.Add( newItem );
+ //m_nativeDirectivesIndex = m_additionalDirectives.Count - 1;
+ m_additionalDirectives.Insert( 0, newItem );
+ m_nativeDirectivesIndex = 0;
+ }
+ }
+ }
+
+ public void FillNativeItems( List<string> nativeItems )
+ {
+ m_nativeDirectives.Clear();
+ m_nativeDirectives.AddRange( nativeItems );
+ AddNativeContainer();
+ }
+
+ void DrawNativeItems()
+ {
+ EditorGUILayout.Separator();
+ EditorGUI.indentLevel++;
+ int count = m_nativeDirectives.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ EditorGUILayout.LabelField( m_nativeDirectives[ i ] );
+ }
+ EditorGUI.indentLevel--;
+ EditorGUILayout.Separator();
+ }
+
+ void DrawNativeItemsRect()
+ {
+ int count = m_nativeDirectives.Count;
+ m_nativeRect.y += EditorGUIUtility.singleLineHeight;
+ for( int i = 0; i < count; i++ )
+ {
+ EditorGUI.LabelField( m_nativeRect, m_nativeDirectives[ i ] );
+ m_nativeRect.y += EditorGUIUtility.singleLineHeight;
+ }
+ }
+
+ void DrawButtons()
+ {
+ EditorGUILayout.Separator();
+
+ // Add keyword
+ if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) )
+ {
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ m_additionalDirectives.Add( newItem );
+ UpdateNativeIndex();
+ EditorGUI.FocusTextInControl( null );
+ m_isDirty = true;
+ }
+
+ //Remove keyword
+ if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( Constants.PlusMinusButtonLayoutWidth ) ) )
+ {
+ if( m_additionalDirectives.Count > 0 )
+ {
+ AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_additionalDirectives.Count - 1 ];
+ m_additionalDirectives.RemoveAt( m_additionalDirectives.Count - 1 );
+ ScriptableObject.DestroyImmediate( itemToDelete );
+ EditorGUI.FocusTextInControl( null );
+ }
+ m_isDirty = true;
+ }
+ }
+
+ public override void Draw( UndoParentNode currOwner, bool style = true )
+ {
+ m_currOwner = currOwner;
+ if( m_reordableList == null )
+ {
+ m_reordableList = new ReorderableList( m_additionalDirectives, typeof( AdditionalDirectiveContainer ), true, false, false, false )
+ {
+ headerHeight = 0,
+ footerHeight = 0,
+ showDefaultBackground = false,
+ elementHeightCallback = ( index ) =>
+ {
+ if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout )
+ {
+ return ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5;
+ }
+
+ return EditorGUIUtility.singleLineHeight + 5;
+ },
+ drawElementCallback = ( Rect rect, int index, bool isActive, bool isFocused ) =>
+ {
+ if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native && m_nativeDirectivesFoldout )
+ {
+ rect.height = ( m_nativeDirectives.Count + 1 ) * ( EditorGUIUtility.singleLineHeight ) + 5;
+ }
+
+ if( m_additionalDirectives[ index ] != null )
+ {
+ float labelWidthStyleAdjust = 0;
+ if( style )
+ {
+ rect.xMin -= 10;
+ labelWidthStyleAdjust = 15;
+ }
+ else
+ {
+ rect.xMin -= 1;
+ }
+
+ float popUpWidth = style ? 75 : 60f;
+ float widthAdjust = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? -14 : 0;
+ Rect popupPos = new Rect( rect.x, rect.y, popUpWidth, EditorGUIUtility.singleLineHeight );
+ Rect GUIDTogglePos = m_additionalDirectives[ index ].LineType == AdditionalLineType.Include ? new Rect( rect.x + rect.width - 3 * Constants.PlusMinusButtonLayoutWidth, rect.y, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth ) : new Rect();
+ Rect buttonPlusPos = new Rect( rect.x + rect.width - 2 * Constants.PlusMinusButtonLayoutWidth, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth );
+ Rect buttonMinusPos = new Rect( rect.x + rect.width - Constants.PlusMinusButtonLayoutWidth, rect.y - 2, Constants.PlusMinusButtonLayoutWidth, Constants.PlusMinusButtonLayoutWidth );
+ float labelWidthBuffer = EditorGUIUtility.labelWidth;
+ Rect labelPos = new Rect( rect.x + popupPos.width - labelWidthStyleAdjust, rect.y, labelWidthStyleAdjust + rect.width - popupPos.width - buttonPlusPos.width - buttonMinusPos.width + widthAdjust, EditorGUIUtility.singleLineHeight );
+
+ if( m_additionalDirectives[ index ].Origin == AdditionalContainerOrigin.Native )
+ {
+ m_nativeRect = rect;
+#if UNITY_2019_3_OR_NEWER
+ m_nativeRect.y -= ( m_nativeRect.height - ( EditorGUIUtility.singleLineHeight + 5 ) ) * 0.5f;
+#endif
+ m_nativeRect.xMin += 2;
+ m_nativeRect.xMax -= 2;
+ m_nativeRect.yMax -= 2;
+
+ NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, rect, NativeFoldoutStr, DrawNativeItemsRect, 4 );
+ return;
+ }
+
+ m_additionalDirectives[ index ].LineType = (AdditionalLineType)m_currOwner.EditorGUIEnumPopup( popupPos, m_additionalDirectives[ index ].LineType );
+
+ if( m_additionalDirectives[ index ].LineType == AdditionalLineType.Include )
+ {
+ if( m_additionalDirectives[ index ].GUIDToggle )
+ {
+ //if( m_additionalDirectives[ index ].LibObject == null && !string.IsNullOrEmpty( m_additionalDirectives[ index ].GUIDValue ) )
+ //{
+ // m_additionalDirectives[ index ].LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( m_additionalDirectives[ index ].GUIDValue ) );
+ //}
+
+ EditorGUI.BeginChangeCheck();
+ TextAsset obj = m_currOwner.EditorGUIObjectField( labelPos, m_additionalDirectives[ index ].LibObject, typeof( TextAsset ), false ) as TextAsset;
+ if( EditorGUI.EndChangeCheck() )
+ {
+ string pathName = AssetDatabase.GetAssetPath( obj );
+ string extension = Path.GetExtension( pathName );
+ extension = extension.ToLower();
+ if( extension.Equals( ".cginc" ) || extension.Equals( ".hlsl" ) )
+ {
+ m_additionalDirectives[ index ].LibObject = obj;
+ m_additionalDirectives[ index ].GUIDValue = AssetDatabase.AssetPathToGUID( pathName );
+ }
+ }
+ }
+ else
+ {
+ m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue );
+ }
+
+ if( GUI.Button( GUIDTogglePos, m_additionalDirectives[ index ].GUIDToggle ? UIUtils.FloatIntIconOFF : UIUtils.FloatIntIconON, UIUtils.FloatIntPickerONOFF ) )
+ m_additionalDirectives[ index ].GUIDToggle = !m_additionalDirectives[ index ].GUIDToggle;
+ }
+ else
+ {
+ m_additionalDirectives[ index ].LineValue = m_currOwner.EditorGUITextField( labelPos, string.Empty, m_additionalDirectives[ index ].LineValue );
+ }
+
+ if( GUI.Button( buttonPlusPos, string.Empty, UIUtils.PlusStyle ) )
+ {
+ m_actionType = ReordableAction.Add;
+ m_actionIndex = index;
+ }
+
+ if( GUI.Button( buttonMinusPos, string.Empty, UIUtils.MinusStyle ) )
+ {
+ m_actionType = ReordableAction.Remove;
+ m_actionIndex = index;
+ }
+ }
+ },
+ onReorderCallback = ( ReorderableList list ) =>
+ {
+ UpdateNativeIndex();
+ }
+ };
+ }
+
+ if( m_actionType != ReordableAction.None )
+ {
+ switch( m_actionType )
+ {
+ case ReordableAction.Add:
+ {
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ m_additionalDirectives.Insert( m_actionIndex + 1, newItem );
+ }
+ break;
+ case ReordableAction.Remove:
+ AdditionalDirectiveContainer itemToDelete = m_additionalDirectives[ m_actionIndex ];
+ m_additionalDirectives.RemoveAt( m_actionIndex );
+ ScriptableObject.DestroyImmediate( itemToDelete );
+ break;
+ }
+ m_isDirty = true;
+ m_actionType = ReordableAction.None;
+ EditorGUI.FocusTextInControl( null );
+ }
+ bool foldoutValue = currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives;
+ if( style )
+ {
+ NodeUtils.DrawPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
+ }
+ else
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref foldoutValue, m_moduleName, DrawReordableList, DrawButtons );
+ }
+ currOwner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDirectives = foldoutValue;
+ }
+
+ void DrawReordableList()
+ {
+ if( m_reordableList != null )
+ {
+ if( m_propertyAdjustment == null )
+ {
+ m_propertyAdjustment = new GUIStyle();
+ m_propertyAdjustment.padding.left = 17;
+ }
+ //EditorGUILayout.BeginVertical( m_propertyAdjustment );
+ EditorGUILayout.Space();
+ if( m_nativeDirectives.Count > 0 )
+ {
+ //NodeUtils.DrawNestedPropertyGroup( ref m_nativeDirectivesFoldout, NativeFoldoutStr, DrawNativeItems, 4 );
+ }
+ if( m_additionalDirectives.Count == 0 )
+ {
+ EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info );
+ }
+ else
+ {
+ m_reordableList.DoLayoutList();
+ }
+ EditorGUILayout.Space();
+ //EditorGUILayout.EndVertical();
+ }
+ }
+
+ public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer )
+ {
+ //List<AdditionalDirectiveContainer> list = m_additionalDirectives;
+ //int count = list.FindIndex( x => x.Origin.Equals( AdditionalContainerOrigin.Native ) );
+ //for( int i = 0; i < count; i++ )
+ //{
+ // switch( list[ i ].LineType )
+ // {
+ // case AdditionalLineType.Include:
+ // {
+ // string value = list[ i ].Value;
+ // if( !string.IsNullOrEmpty( value ) &&
+ // !nativesContainer.HasInclude( value ) )
+ // {
+ // dataCollector.AddToMisc( list[ i ].FormattedValue );
+ // }
+ // }
+ // break;
+ // case AdditionalLineType.Define:
+ // {
+ // if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
+ // !nativesContainer.HasDefine( list[ i ].LineValue ) )
+ // {
+ // dataCollector.AddToMisc( list[ i ].FormattedValue );
+ // }
+ // }
+ // break;
+ // case AdditionalLineType.Pragma:
+ // {
+ // if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
+ // !nativesContainer.HasPragma( list[ i ].LineValue ) )
+ // {
+ // dataCollector.AddToMisc( list[ i ].FormattedValue );
+ // }
+ // }
+ // break;
+ // default:
+ // case AdditionalLineType.Custom:
+ // dataCollector.AddToMisc( list[ i ].LineValue );
+ // break;
+ // }
+ //}
+
+ AddToDataCollector( ref dataCollector, nativesContainer, false );
+ AddToDataCollector( ref dataCollector, nativesContainer, true );
+ }
+
+ public void AddAllToDataCollector( ref MasterNodeDataCollector dataCollector )
+ {
+ AddToDataCollector( ref dataCollector, false );
+ AddToDataCollector( ref dataCollector, true );
+ }
+
+ void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer, bool fromSF )
+ {
+ List<AdditionalDirectiveContainer> list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives;
+ int count = list.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ int orderIdx = fromSF ? 1 : ( i > m_nativeDirectivesIndex ? 1 : -1 );
+ switch( list[ i ].LineType )
+ {
+ case AdditionalLineType.Include:
+ {
+ string value = list[ i ].Value;
+ if( !string.IsNullOrEmpty( value ) &&
+ !nativesContainer.HasInclude( value ) )
+ {
+ dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx );
+ }
+ }
+ break;
+ case AdditionalLineType.Define:
+ {
+ if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
+ !nativesContainer.HasDefine( list[ i ].LineValue ) )
+ {
+ dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx );
+ }
+ }
+ break;
+ case AdditionalLineType.Pragma:
+ {
+ if( !string.IsNullOrEmpty( list[ i ].LineValue ) &&
+ !nativesContainer.HasPragma( list[ i ].LineValue ) )
+ {
+ dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx );
+ }
+ }
+ break;
+ default:
+ case AdditionalLineType.Custom:
+ dataCollector.AddToDirectives( list[ i ].LineValue, orderIdx );
+ break;
+ }
+ }
+ }
+
+ void AddToDataCollector( ref MasterNodeDataCollector dataCollector, bool fromSF )
+ {
+ List<AdditionalDirectiveContainer> list = fromSF ? m_shaderFunctionDirectives : m_additionalDirectives;
+ int orderIdx = 1;
+ int count = list.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ switch( list[ i ].LineType )
+ {
+ case AdditionalLineType.Include:
+ {
+ string value = list[ i ].FormattedValue;
+ if( !string.IsNullOrEmpty( value ) )
+ {
+ dataCollector.AddToDirectives( value, orderIdx );
+ }
+ }
+ break;
+ case AdditionalLineType.Define:
+ {
+ if( !string.IsNullOrEmpty( list[ i ].LineValue ) )
+ {
+ dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx );
+ }
+ }
+ break;
+ case AdditionalLineType.Pragma:
+ {
+ if( !string.IsNullOrEmpty( list[ i ].LineValue ) )
+ {
+ dataCollector.AddToDirectives( list[ i ].FormattedValue, orderIdx );
+ }
+ }
+ break;
+ default:
+ case AdditionalLineType.Custom:
+ dataCollector.AddToDirectives( list[ i ].LineValue, orderIdx );
+ break;
+ }
+ }
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ try
+ {
+ m_nativeDirectivesIndex = -1;
+ int count = Convert.ToInt32( nodeParams[ index++ ] );
+ m_additionalDirectives.Clear();
+ for( int i = 0; i < count; i++ )
+ {
+ AdditionalLineType lineType = (AdditionalLineType)Enum.Parse( typeof( AdditionalLineType ), nodeParams[ index++ ] );
+ string lineValue = nodeParams[ index++ ];
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ newItem.LineType = lineType;
+ newItem.LineValue = lineValue.Replace( Constants.SemiColonSeparator, ';' );
+ if( UIUtils.CurrentShaderVersion() > 15607 )
+ {
+ newItem.GUIDToggle = Convert.ToBoolean( nodeParams[ index++ ] );
+ newItem.GUIDValue = nodeParams[ index++ ];
+ if( newItem.GUIDToggle )
+ {
+ newItem.LibObject = AssetDatabase.LoadAssetAtPath<TextAsset>( AssetDatabase.GUIDToAssetPath( newItem.GUIDValue ) );
+ if( newItem.LibObject == null )
+ {
+ Debug.LogWarning( "Include file not found with GUID " + newItem.GUIDValue );
+ }
+ }
+ }
+ AdditionalContainerOrigin origin = AdditionalContainerOrigin.Custom;
+ if( UIUtils.CurrentShaderVersion() > 16902 )
+ {
+ origin = (AdditionalContainerOrigin)Enum.Parse( typeof( AdditionalContainerOrigin ), nodeParams[ index++ ] );
+ newItem.Origin = origin;
+ }
+
+ m_additionalDirectives.Add( newItem );
+
+ if( origin == AdditionalContainerOrigin.Native )
+ {
+ m_nativeDirectivesIndex = i;
+ }
+ }
+ AddNativeContainer();
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ if( m_additionalDirectives.Count == 1 && m_additionalDirectives[ 0 ].Origin == AdditionalContainerOrigin.Native )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, 0 );
+ return;
+ }
+
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives.Count );
+ for( int i = 0; i < m_additionalDirectives.Count; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineType );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].LineValue.Replace( ';', Constants.SemiColonSeparator ) );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDToggle );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].GUIDValue );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalDirectives[ i ].Origin );
+ }
+ }
+
+ // read comment on m_directivesSaveItems declaration
+ public void UpdateSaveItemsFromDirectives()
+ {
+ bool foundNull = false;
+ m_directivesSaveItems.Clear();
+ for( int i = 0; i < m_additionalDirectives.Count; i++ )
+ {
+ if( m_additionalDirectives[ i ] != null )
+ {
+ m_directivesSaveItems.Add( new AdditionalDirectiveContainerSaveItem( m_additionalDirectives[ i ] ) );
+ }
+ else
+ {
+ foundNull = true;
+ }
+ }
+
+ if( foundNull )
+ {
+ m_additionalDirectives.RemoveAll( item => item == null );
+ }
+ }
+
+ public void CleanNullDirectives()
+ {
+ m_additionalDirectives.RemoveAll( item => item == null );
+ }
+
+ public void ResetDirectivesOrigin()
+ {
+ for( int i = 0; i < m_directivesSaveItems.Count; i++ )
+ {
+ m_directivesSaveItems[ i ].Origin = AdditionalContainerOrigin.Custom;
+ }
+ }
+
+ // read comment on m_directivesSaveItems declaration
+ public void UpdateDirectivesFromSaveItems()
+ {
+ if( m_directivesSaveItems.Count > 0 )
+ {
+ for( int i = 0; i < m_additionalDirectives.Count; i++ )
+ {
+ if( m_additionalDirectives[ i ] != null )
+ ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] );
+ }
+
+ m_additionalDirectives.Clear();
+
+ for( int i = 0; i < m_directivesSaveItems.Count; i++ )
+ {
+ AdditionalDirectiveContainer newItem = ScriptableObject.CreateInstance<AdditionalDirectiveContainer>();
+ newItem.hideFlags = HideFlags.HideAndDontSave;
+ newItem.Init( m_directivesSaveItems[ i ] );
+ m_additionalDirectives.Add( newItem );
+ }
+ UpdateNativeIndex();
+ //m_directivesSaveItems.Clear();
+ }
+ }
+
+ void UpdateNativeIndex()
+ {
+ m_nativeDirectivesIndex = -1;
+ int count = m_additionalDirectives.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_additionalDirectives[ i ].Origin == AdditionalContainerOrigin.Native )
+ {
+ m_nativeDirectivesIndex = i;
+ break;
+ }
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+
+ m_nativeDirectives.Clear();
+ m_nativeDirectives = null;
+
+ for( int i = 0; i < m_additionalDirectives.Count; i++ )
+ {
+ ScriptableObject.DestroyImmediate( m_additionalDirectives[ i ] );
+ }
+
+ m_additionalDirectives.Clear();
+ m_additionalDirectives = null;
+
+ for( int i = 0; i < m_shaderFunctionDirectives.Count; i++ )
+ {
+ ScriptableObject.DestroyImmediate( m_shaderFunctionDirectives[ i ] );
+ }
+
+ m_shaderFunctionDirectives.Clear();
+ m_shaderFunctionDirectives = null;
+
+
+ m_propertyAdjustment = null;
+ m_reordableList = null;
+ }
+
+
+ public List<AdditionalDirectiveContainer> DirectivesList { get { return m_additionalDirectives; } }
+ public bool IsValid { get { return m_validData; } set { m_validData = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta
new file mode 100644
index 00000000..43fdc898
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalDirectivesHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c6b57deeb826a674f9715fab4dfb4cb1
+timeCreated: 1528278077
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs
new file mode 100644
index 00000000..7d58666b
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs
@@ -0,0 +1,31 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateAdditionalIncludesHelper : TemplateAdditionalParentHelper
+ {
+ public TemplateAdditionalIncludesHelper() : base( "Additional Includes" )
+ {
+ m_helpBoxMessage = "Please add your includes without the #include \"\" keywords";
+ }
+
+ public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector , TemplateIncludePragmaContainter nativesContainer )
+ {
+ for( int i = 0; i < m_additionalItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasInclude( m_additionalItems[ i ] ) )
+ dataCollector.AddToIncludes( -1, m_additionalItems[ i ] );
+ }
+
+ for( int i = 0; i < m_outsideItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasInclude( m_outsideItems[ i ] ) )
+ dataCollector.AddToIncludes( -1, m_outsideItems[ i ] );
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta
new file mode 100644
index 00000000..9a454744
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalIncludesHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0ab4c474dfddce2429da08f56e651ed4
+timeCreated: 1520275148
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs
new file mode 100644
index 00000000..da765cca
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs
@@ -0,0 +1,193 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateAdditionalParentHelper : TemplateModuleParent
+ {
+ private string NativeFoldoutStr = "Native";
+
+ protected string m_helpBoxMessage = string.Empty;
+ private const float ShaderKeywordButtonLayoutWidth = 15;
+ private ParentNode m_currentOwner;
+
+ [SerializeField]
+ protected List<string> m_nativeItems = new List<string>();
+
+ [SerializeField]
+ protected bool m_nativeItemsFoldout = false;
+
+ [SerializeField]
+ protected List<string> m_additionalItems = new List<string>();
+
+ [SerializeField]
+ protected List<string> m_outsideItems = new List<string>();
+
+ public TemplateAdditionalParentHelper( string moduleName ) : base( moduleName ) { }
+ public bool IsValid { set{ m_validData = value; } get{ return m_validData; } }
+
+ public void FillNativeItems( List<string> nativeItems )
+ {
+ m_nativeItems.Clear();
+ m_nativeItems.AddRange( nativeItems );
+ }
+
+ public void Draw( ParentNode owner )
+ {
+ m_currentOwner = owner;
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines;
+ NodeUtils.DrawNestedPropertyGroup( ref foldout, m_moduleName, DrawMainBody, DrawButtons );
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedAdditionalDefines = foldout;
+ }
+
+ public void CopyFrom( TemplateAdditionalParentHelper other )
+ {
+ m_additionalItems.Clear();
+ m_outsideItems.Clear();
+ int otherAdditionalItemsCount = other.ItemsList.Count;
+ for( int i = 0; i < otherAdditionalItemsCount; i++ )
+ {
+ m_additionalItems.Add( other.ItemsList[ i ] );
+ }
+
+ int otherOusideItemsCount = other.OutsideList.Count;
+ for( int i = 0; i < otherOusideItemsCount; i++ )
+ {
+ m_outsideItems.Add( other.OutsideList[ i ] );
+ }
+ }
+
+ void DrawButtons()
+ {
+ EditorGUILayout.Separator();
+
+ // Add keyword
+ if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ m_additionalItems.Add( string.Empty );
+ EditorGUI.FocusTextInControl( null );
+ m_isDirty = true;
+ }
+
+ //Remove keyword
+ if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ if( m_additionalItems.Count > 0 )
+ {
+ m_additionalItems.RemoveAt( m_additionalItems.Count - 1 );
+ EditorGUI.FocusTextInControl( null );
+ }
+ m_isDirty = true;
+ }
+ }
+ void DrawNativeItems()
+ {
+ EditorGUILayout.Separator();
+ EditorGUI.indentLevel++;
+ int count = m_nativeItems.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ EditorGUILayout.LabelField( m_nativeItems[i] );
+ }
+ EditorGUI.indentLevel--;
+ EditorGUILayout.Separator();
+ }
+ void DrawMainBody()
+ {
+ EditorGUILayout.Separator();
+
+ if( m_nativeItems.Count > 0 )
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref m_nativeItemsFoldout, NativeFoldoutStr, DrawNativeItems ,4);
+ }
+
+ int itemCount = m_additionalItems.Count;
+ int markedToDelete = -1;
+ for( int i = 0; i < itemCount; i++ )
+ {
+ EditorGUILayout.BeginHorizontal();
+ {
+ EditorGUI.BeginChangeCheck();
+ m_additionalItems[ i ] = EditorGUILayout.TextField( m_additionalItems[ i ] );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_additionalItems[ i ] = UIUtils.RemoveShaderInvalidCharacters( m_additionalItems[ i ] );
+ m_isDirty = true;
+ }
+
+ // Add new port
+ if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ m_additionalItems.Insert( i + 1, string.Empty );
+ EditorGUI.FocusTextInControl( null );
+ m_isDirty = true;
+ }
+
+ //Remove port
+ if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ markedToDelete = i;
+ m_isDirty = true;
+ }
+ }
+ EditorGUILayout.EndHorizontal();
+ }
+
+ if( markedToDelete > -1 )
+ {
+ if( m_additionalItems.Count > markedToDelete )
+ {
+ m_additionalItems.RemoveAt( markedToDelete );
+ EditorGUI.FocusTextInControl( null );
+ }
+ }
+ EditorGUILayout.Separator();
+ EditorGUILayout.HelpBox( m_helpBoxMessage, MessageType.Info );
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ try
+ {
+ int count = Convert.ToInt32( nodeParams[ index++ ] );
+ for( int i = 0; i < count; i++ )
+ {
+ m_additionalItems.Add( nodeParams[ index++ ] );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalItems.Count );
+ for( int i = 0; i < m_additionalItems.Count; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_additionalItems[ i ] );
+ }
+ }
+
+ public virtual void AddToDataCollector( ref MasterNodeDataCollector dataCollector , TemplateIncludePragmaContainter nativesContainer ) { }
+
+ public override void Destroy()
+ {
+ m_additionalItems.Clear();
+ m_additionalItems = null;
+ m_currentOwner = null;
+ m_nativeItems.Clear();
+ m_nativeItems = null;
+ }
+
+ public List<string> ItemsList { get { return m_additionalItems; } set { m_additionalItems = value; } }
+ public List<string> OutsideList { get { return m_outsideItems; } set { m_outsideItems = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta
new file mode 100644
index 00000000..6d0983fe
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalParentHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5360ba11600eeb44786246ca70212e25
+timeCreated: 1520332262
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs
new file mode 100644
index 00000000..3c08f1a0
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs
@@ -0,0 +1,31 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateAdditionalPragmasHelper : TemplateAdditionalParentHelper
+ {
+ public TemplateAdditionalPragmasHelper() : base( "Additional Pragmas" )
+ {
+ m_helpBoxMessage = "Please add your pragmas without the #pragma keywords";
+ }
+
+ public override void AddToDataCollector( ref MasterNodeDataCollector dataCollector, TemplateIncludePragmaContainter nativesContainer )
+ {
+ for( int i = 0; i < m_additionalItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_additionalItems[ i ] ) && !nativesContainer.HasPragma( m_additionalItems[ i ] ))
+ dataCollector.AddToPragmas( -1, m_additionalItems[ i ] );
+ }
+
+ for( int i = 0; i < m_outsideItems.Count; i++ )
+ {
+ if( !string.IsNullOrEmpty( m_outsideItems[ i ] ) && !nativesContainer.HasPragma( m_outsideItems[ i ] ) )
+ dataCollector.AddToPragmas( -1, m_outsideItems[ i ] );
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta
new file mode 100644
index 00000000..4abd0233
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateAdditionalPragmasHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: de89b62c2bd8eec4b915a0decba936fb
+timeCreated: 1520275148
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs
new file mode 100644
index 00000000..ea717e62
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs
@@ -0,0 +1,102 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ public enum TemplateCodeSnippetType
+ {
+ Toggle
+ };
+
+
+ public enum TemplateCodeSnippetInfoIdx
+ {
+ Name = 0,
+ Type
+ };
+
+ [Serializable]
+ public class TemplateCodeSnippetElement
+ {
+ public string Id;
+ public string Snippet;
+ public TemplateCodeSnippetElement( string id, string snippet )
+ {
+ Id = id;
+ Snippet = snippet;
+ }
+ }
+
+ [Serializable]
+ public class TemplateCodeSnippetBase : ScriptableObject
+ {
+ [SerializeField]
+ private string m_nameId;
+
+ [SerializeField]
+ private TemplateCodeSnippetType m_type;
+
+ [SerializeField]
+ private List<TemplateCodeSnippetElement> m_elements = new List<TemplateCodeSnippetElement>();
+
+ public void Init( string nameId, TemplateCodeSnippetType type )
+ {
+ m_nameId = nameId;
+ m_type = type;
+ }
+
+ public void AddSnippet( TemplateCodeSnippetElement element )
+ {
+ m_elements.Add( element );
+ }
+
+ public void Destroy()
+ {
+ for ( int i = 0; i < m_elements.Count; i++ )
+ {
+ m_elements[ i ].Snippet = null;
+ }
+ m_elements.Clear();
+ m_elements = null;
+ }
+
+ public virtual void DrawProperties( ParentNode owner ) { }
+ public virtual bool CheckSnippet() { return true; }
+
+ public void InsertSnippet( ref string shaderBody )
+ {
+ bool insertSnippet = CheckSnippet();
+ for ( int i = 0; i < m_elements.Count; i++ )
+ {
+ shaderBody = shaderBody.Replace( m_elements[ i ].Id, ( insertSnippet ? m_elements[ i ].Snippet : string.Empty ) );
+ }
+ }
+ public string NameId { get { return m_nameId; } }
+ public TemplateCodeSnippetType Type { get { return m_type; } }
+ public List<TemplateCodeSnippetElement> Elements { get { return m_elements; } }
+ }
+
+ [Serializable]
+ public class TemplateCodeSnippetToggle : TemplateCodeSnippetBase
+ {
+ private const string Label = "Activate";
+ [SerializeField]
+ private bool m_value = false;
+
+
+ public override bool CheckSnippet()
+ {
+ return m_value;
+ }
+
+ public override void DrawProperties( ParentNode owner )
+ {
+ m_value = owner.EditorGUILayoutToggle( Label, m_value );
+ }
+ }
+
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta
new file mode 100644
index 00000000..612a5536
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCodeSnippetBase.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5fc48fb872ce5e74aa913f987a025ea4
+timeCreated: 1495113330
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs
new file mode 100644
index 00000000..31739972
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs
@@ -0,0 +1,184 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using System;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateColorMaskModule : TemplateModuleParent
+ {
+ private const string ColorMaskOp = "ColorMask ";
+ private const string ColorMaskOff = "ColorMask RGBA";
+ private GUIContent ColorMaskContent = new GUIContent( "Color Mask", "Sets color channel writing mask, turning all off makes the object completely invisible\nDefault: RGBA" );
+ private readonly char[] m_colorMaskChar = { 'R', 'G', 'B', 'A' };
+
+ private GUIStyle m_leftToggleColorMask;
+ private GUIStyle m_middleToggleColorMask;
+ private GUIStyle m_rightToggleColorMask;
+
+ public TemplateColorMaskModule() : base( "Color Mask" ) { }
+
+ [SerializeField]
+ private bool[] m_colorMask = { true, true, true, true };
+
+ [SerializeField]
+ private InlineProperty m_inlineColorMask = new InlineProperty();
+
+ public void CopyFrom( TemplateColorMaskModule other, bool allData )
+ {
+ if( allData )
+ m_independentModule = other.IndependentModule;
+
+ for( int i = 0; i < m_colorMask.Length; i++ )
+ {
+ m_colorMask[ i ] = other.ColorMask[ i ];
+ }
+ m_inlineColorMask.CopyFrom( other.InlineColorMask );
+ }
+
+ public void ConfigureFromTemplateData( TemplateColorMaskData data )
+ {
+ bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid );
+ if( newValidData && m_validData != newValidData )
+ {
+ m_independentModule = data.IndependentModule;
+ if( string.IsNullOrEmpty( data.InlineData ) )
+ {
+ for( int i = 0; i < 4; i++ )
+ {
+ m_colorMask[ i ] = data.ColorMaskData[ i ];
+ }
+ m_inlineColorMask.ResetProperty();
+ }
+ else
+ {
+ m_inlineColorMask.SetInlineByName( data.InlineData );
+ }
+ }
+
+ m_validData = newValidData;
+ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ EditorGUI.BeginChangeCheck();
+ {
+ m_inlineColorMask.CustomDrawer( ref owner, DrawColorMaskControls, ColorMaskContent.text );
+ }
+
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ }
+
+ private void DrawColorMaskControls( UndoParentNode owner )
+ {
+ if( m_leftToggleColorMask == null || m_leftToggleColorMask.normal.background == null )
+ {
+ m_leftToggleColorMask = GUI.skin.GetStyle( "ButtonLeft" );
+ }
+
+ if( m_middleToggleColorMask == null || m_middleToggleColorMask.normal.background == null )
+ {
+ m_middleToggleColorMask = GUI.skin.GetStyle( "ButtonMid" );
+ }
+
+ if( m_rightToggleColorMask == null || m_rightToggleColorMask.normal.background == null )
+ {
+ m_rightToggleColorMask = GUI.skin.GetStyle( "ButtonRight" );
+ }
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.LabelField( ColorMaskContent, GUILayout.Width( 90 ) );
+
+ m_colorMask[ 0 ] = owner.GUILayoutToggle( m_colorMask[ 0 ], "R", m_leftToggleColorMask );
+ m_colorMask[ 1 ] = owner.GUILayoutToggle( m_colorMask[ 1 ], "G", m_middleToggleColorMask );
+ m_colorMask[ 2 ] = owner.GUILayoutToggle( m_colorMask[ 2 ], "B", m_middleToggleColorMask );
+ m_colorMask[ 3 ] = owner.GUILayoutToggle( m_colorMask[ 3 ], "A", m_rightToggleColorMask );
+
+ EditorGUILayout.EndHorizontal();
+ }
+
+ public override string GenerateShaderData( bool isSubShader )
+ {
+ if( m_inlineColorMask.IsValid )
+ return ColorMaskOp + m_inlineColorMask.GetValueOrProperty();
+
+ int count = 0;
+ string colorMask = string.Empty;
+ for( int i = 0; i < m_colorMask.Length; i++ )
+ {
+ if( m_colorMask[ i ] )
+ {
+ count++;
+ colorMask += m_colorMaskChar[ i ];
+ }
+ }
+
+ if( count != m_colorMask.Length )
+ {
+ return ColorMaskOp + ( ( count == 0 ) ? "0" : colorMask );
+ }
+
+ return ColorMaskOff;
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validData;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ for( int i = 0; i < m_colorMask.Length; i++ )
+ {
+ m_colorMask[ i ] = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 15303 )
+ {
+ m_inlineColorMask.ReadFromString( ref index, ref nodeParams );
+ }
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validData );
+ if( m_validData )
+ {
+ for( int i = 0; i < m_colorMask.Length; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_colorMask[ i ] );
+ }
+ m_inlineColorMask.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public bool[] ColorMask
+ {
+ get { return m_colorMask; }
+ set
+ {
+ m_colorMask = value;
+ m_inlineColorMask.Active = false;
+ }
+ }
+
+ public override void Destroy()
+ {
+ m_leftToggleColorMask = null;
+ m_middleToggleColorMask = null;
+ m_rightToggleColorMask = null;
+ m_inlineColorMask = null;
+ }
+
+ public InlineProperty InlineColorMask { get { return m_inlineColorMask; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta
new file mode 100644
index 00000000..8cb1fbbb
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateColorMaskModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e1d9e34bd7946e247aa6d28b2859c6b1
+timeCreated: 1511259305
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs
new file mode 100644
index 00000000..fed77dc0
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs
@@ -0,0 +1,125 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEngine;
+using UnityEditor;
+using System;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public sealed class TemplateCullModeModule : TemplateModuleParent
+ {
+ private const string CullModeFormatStr = "Cull ";
+
+ public TemplateCullModeModule() : base("Cull Mode"){ }
+
+ private static readonly string CullModeStr = "Cull Mode";
+
+ [SerializeField]
+ private CullMode m_cullMode = CullMode.Back;
+
+ [SerializeField]
+ private InlineProperty m_inlineCullMode = new InlineProperty();
+
+ public void CopyFrom( TemplateCullModeModule other , bool allData )
+ {
+ if( allData )
+ m_independentModule = other.IndependentModule;
+
+ m_cullMode = other.CurrentCullMode;
+ m_inlineCullMode.CopyFrom( other.CullInlineProperty );
+ }
+
+ public void ConfigureFromTemplateData( TemplateCullModeData data )
+ {
+ bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid );
+
+ if( newValidData && m_validData != newValidData )
+ {
+ m_independentModule = data.IndependentModule;
+ if( string.IsNullOrEmpty( data.InlineData ) )
+ {
+ m_cullMode = data.CullModeData;
+ m_inlineCullMode.IntValue = (int)m_cullMode;
+ m_inlineCullMode.ResetProperty();
+ }
+ else
+ {
+ m_inlineCullMode.SetInlineByName( data.InlineData );
+ }
+ }
+
+ m_validData = newValidData;
+ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ EditorGUI.BeginChangeCheck();
+ //m_cullMode = (CullMode)owner.EditorGUILayoutEnumPopup( CullModeStr, m_cullMode );
+ m_inlineCullMode.CustomDrawer( ref owner, ( x ) => { m_cullMode = (CullMode)owner.EditorGUILayoutEnumPopup( CullModeStr, m_cullMode ); }, CullModeStr );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_inlineCullMode.IntValue = (int)m_cullMode;
+ m_isDirty = true;
+ }
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validData;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_cullMode = (CullMode)Enum.Parse( typeof( CullMode ), nodeParams[ index++ ] );
+ m_inlineCullMode.IntValue = (int)m_cullMode;
+ }
+ else
+ {
+ m_inlineCullMode.ReadFromString( ref index, ref nodeParams );
+ m_cullMode = (CullMode)m_inlineCullMode.IntValue;
+ }
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validData );
+ if( m_validData )
+ {
+ //IOUtils.AddFieldValueToString( ref nodeInfo, m_cullMode );
+ m_inlineCullMode.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public override string GenerateShaderData( bool isSubShader )
+ {
+ //return CullModeFormatStr + m_cullMode.ToString();
+ return CullModeFormatStr + m_inlineCullMode.GetValueOrProperty( m_cullMode.ToString());
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_inlineCullMode = null;
+ }
+
+ public CullMode CurrentCullMode
+ {
+ get { return m_cullMode; }
+ set
+ {
+ m_cullMode = value;
+ m_inlineCullMode.IntValue = (int)value;
+ m_inlineCullMode.Active = false;
+ }
+ }
+ public InlineProperty CullInlineProperty { get { return m_inlineCullMode; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta
new file mode 100644
index 00000000..7b3fa309
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateCullModeModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dcbce53ba2eeecd4a8f2c7f5f9a43b7a
+timeCreated: 1511186525
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs
new file mode 100644
index 00000000..f3c7b895
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs
@@ -0,0 +1,1178 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+// THIS FILE IS DEPRECATED AND SHOULD NOT BE USED
+
+using System;
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateDataContainer
+ {
+ public int UNITY_VERSION = -1;
+ public TemplateData TemplateDataRef;
+ }
+
+ [Serializable]
+ public class VertexDataContainer
+ {
+ [SerializeField]
+ private List<TemplateVertexData> m_vertexData;
+
+ [SerializeField]
+ private string m_vertexDataId = string.Empty;
+
+ [SerializeField]
+ private int m_vertexDataStartIdx = -1;
+
+ public void Reload()
+ {
+ if( m_vertexData != null )
+ {
+ m_vertexData.Clear();
+ }
+ }
+
+ public void Destroy()
+ {
+ if( m_vertexData != null )
+ {
+ m_vertexData.Clear();
+ m_vertexData = null;
+ }
+ }
+
+
+ public List<TemplateVertexData> VertexData { get { return m_vertexData; } set { m_vertexData = value; } }
+ public string VertexDataId { get { return m_vertexDataId; } set { m_vertexDataId = value; } }
+ public int VertexDataStartIdx { get { return m_vertexDataStartIdx; } set { m_vertexDataStartIdx = value; } }
+ }
+
+ [Serializable]
+ public sealed class TemplateData : TemplateDataParent
+ {
+ [SerializeField]
+ private string m_templateBody = string.Empty;
+
+ [SerializeField]
+ private string m_shaderNameId = string.Empty;
+
+ [SerializeField]
+ private List<TemplateProperty> m_propertyList = new List<TemplateProperty>();
+ private Dictionary<string, TemplateProperty> m_propertyDict = new Dictionary<string, TemplateProperty>();
+
+ [SerializeField]
+ private List<TemplateInputData> m_inputDataList = new List<TemplateInputData>();
+ private Dictionary<int, TemplateInputData> m_inputDataDict = new Dictionary<int, TemplateInputData>();
+
+ //[SerializeField]
+ //private List<TemplateCodeSnippetBase> m_snippetElementsList = new List<TemplateCodeSnippetBase>();
+ //private Dictionary<string, TemplateCodeSnippetBase> m_snippetElementsDict = new Dictionary<string, TemplateCodeSnippetBase>();
+
+ [SerializeField]
+ private List<TemplateLocalVarData> m_localVarsList = new List<TemplateLocalVarData>();
+
+ [SerializeField]
+ private VertexDataContainer m_vertexDataContainer = new VertexDataContainer();
+
+ [SerializeField]
+ private TemplateInterpData m_interpolatorDataContainer;
+
+ [SerializeField]
+ private List<TemplateShaderPropertyData> m_availableShaderProperties = new List<TemplateShaderPropertyData>();
+
+ [SerializeField]
+ private TemplateFunctionData m_vertexFunctionData;
+
+ [SerializeField]
+ private TemplateFunctionData m_fragmentFunctionData;
+
+ [SerializeField]
+ private TemplateBlendData m_blendData = new TemplateBlendData();
+
+ [SerializeField]
+ private TemplateCullModeData m_cullModeData = new TemplateCullModeData();
+
+ [SerializeField]
+ private TemplateColorMaskData m_colorMaskData = new TemplateColorMaskData();
+
+ [SerializeField]
+ private TemplateStencilData m_stencilData = new TemplateStencilData();
+
+ [SerializeField]
+ private TemplateDepthData m_depthData = new TemplateDepthData();
+
+ [SerializeField]
+ private TemplateTagsModuleData m_tagData = new TemplateTagsModuleData();
+
+ public TemplateData()
+ {
+ m_templateType = TemplateDataType.LegacySinglePass;
+ }
+
+ public TemplateData( string name )
+ {
+ m_templateType = TemplateDataType.LegacySinglePass;
+ Name = name;
+ }
+
+ public TemplateData( string name, string guid )
+ {
+ m_templateType = TemplateDataType.LegacySinglePass;
+ m_communityTemplate = false;
+ if( !string.IsNullOrEmpty( guid ) )
+ {
+ string datapath = AssetDatabase.GUIDToAssetPath( guid );
+ if( string.IsNullOrEmpty( datapath ) )
+ {
+ m_isValid = false;
+ return;
+ }
+
+ string body = string.Empty;
+ try
+ {
+ body = IOUtils.LoadTextFileFromDisk( datapath );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ return;
+ }
+
+ if( !string.IsNullOrEmpty( body ) )
+ {
+ LoadTemplateBody( body );
+ Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name;
+ m_guid = guid;
+ }
+ }
+ }
+
+ public TemplateData( string name, string guid, string body )
+ {
+ m_templateType = TemplateDataType.LegacySinglePass;
+ m_communityTemplate = true;
+ if( !string.IsNullOrEmpty( body ) )
+ {
+ LoadTemplateBody( body );
+ Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name;
+ m_guid = guid;
+ }
+ }
+
+ public override bool Reload()
+ {
+ if( m_vertexDataContainer != null )
+ {
+ m_vertexDataContainer.Reload();
+ }
+
+ if( m_interpolatorDataContainer != null )
+ {
+ m_interpolatorDataContainer.Destroy();
+ }
+
+ if( m_availableShaderProperties != null )
+ {
+ m_availableShaderProperties.Clear();
+ }
+
+ if( m_propertyDict != null )
+ {
+ m_propertyDict.Clear();
+ }
+
+ if( m_propertyList != null )
+ {
+ m_propertyList.Clear();
+ }
+
+ if( m_inputDataDict != null )
+ {
+ m_inputDataDict.Clear();
+ }
+
+ if( m_inputDataList != null )
+ {
+ m_inputDataList.Clear();
+ }
+
+ if( m_localVarsList != null )
+ {
+ m_localVarsList.Clear();
+ }
+
+ //if( m_snippetElementsDict != null )
+ //{
+ // m_snippetElementsDict.Clear();
+ //}
+
+ //if( m_snippetElementsList != null )
+ //{
+ // for( int i = 0; i < m_snippetElementsList.Count; i++ )
+ // {
+ // GameObject.DestroyImmediate( m_snippetElementsList[ i ] );
+ // m_snippetElementsList[ i ] = null;
+ // }
+ // m_snippetElementsList.Clear();
+ //}
+
+ string datapath = AssetDatabase.GUIDToAssetPath( m_guid );
+ string body = string.Empty;
+ try
+ {
+ body = IOUtils.LoadTextFileFromDisk( datapath );
+ body = body.Replace( "\r\n", "\n" );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ }
+ LoadTemplateBody( body );
+ if( m_communityTemplate )
+ {
+ Name = m_defaultShaderName;
+ }
+ return true;
+ }
+
+ void LoadTemplateBody( string body )
+ {
+
+ m_templateBody = body.Replace( "\r\n", "\n" ); ;
+
+ if( m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) < 0 )
+ {
+ m_isValid = false;
+ return;
+ }
+
+ //Fetching common tags
+ FetchCommonTags();
+
+ //Fetch function code areas
+ FetchCodeAreas( TemplatesManager.TemplateVertexCodeBeginArea, MasterNodePortCategory.Vertex );
+ FetchCodeAreas( TemplatesManager.TemplateFragmentCodeBeginArea, MasterNodePortCategory.Fragment );
+
+ //Fetching inputs
+ FetchInputs( MasterNodePortCategory.Fragment );
+ FetchInputs( MasterNodePortCategory.Vertex );
+
+
+ //Fetch local variables must be done after fetching code areas as it needs them to see is variable is on vertex or fragment
+ TemplateHelperFunctions.FetchLocalVars( m_templateBody, ref m_localVarsList, m_vertexFunctionData, m_fragmentFunctionData );
+
+ //Fetch snippets
+ }
+
+ void FetchSubShaderProperties()
+ {
+ Match match = Regex.Match( m_templateBody, @"Pass\s*{" );
+ if( match.Groups.Count == 0 )
+ {
+ return;
+ }
+
+ int beginSubShader = m_templateBody.IndexOf( "SubShader" );
+ int endSubShader = match.Groups[ 0 ].Index;
+ if( beginSubShader > 0 && endSubShader > 0 && endSubShader > beginSubShader )
+ {
+ // ADD A PLACE TO INSERT GRAB PASSES
+ int passIndex = m_templateBody.IndexOf( TemplatesManager.TemplatePassTag );
+ if( passIndex < 0 )
+ {
+ int currIdx = endSubShader - 1;
+ string identation = string.Empty;
+ for( ; currIdx > 0; currIdx-- )
+ {
+ if( m_templateBody[ currIdx ] != '\n' )
+ {
+ identation = m_templateBody[ currIdx ] + identation;
+ }
+ else
+ {
+ identation = m_templateBody[ currIdx ] + identation;
+ break;
+ }
+ }
+ if( currIdx > 0 )
+ {
+ m_templateBody = m_templateBody.Insert( currIdx, identation + TemplatesManager.TemplatePassTag );
+ }
+ }
+
+ // GET ALL THE MODULES
+ string subBody = m_templateBody.Substring( beginSubShader, endSubShader - beginSubShader );
+ //CULL MODE
+ {
+ int cullIdx = subBody.IndexOf( "Cull" );
+ if( cullIdx > 0 )
+ {
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, cullIdx );
+ string cullParams = subBody.Substring( cullIdx, end - cullIdx );
+ m_cullModeData.CullModeId = cullParams;
+ TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData );
+ if( m_cullModeData.DataCheck == TemplateDataCheck.Valid )
+ AddId( cullParams, false, string.Empty );
+ }
+ }
+ //COLOR MASK
+ {
+ int colorMaskIdx = subBody.IndexOf( "ColorMask" );
+ if( colorMaskIdx > 0 )
+ {
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx );
+ string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx );
+ m_colorMaskData.ColorMaskId = colorMaskParams;
+ TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData );
+ if( m_colorMaskData.DataCheck == TemplateDataCheck.Valid )
+ AddId( colorMaskParams, false );
+ }
+ }
+ //BlEND MODE
+ {
+ int blendModeIdx = subBody.IndexOf( "Blend" );
+ if( blendModeIdx > 0 )
+ {
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendModeIdx );
+ string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx );
+ m_blendData.BlendModeId = blendParams;
+ TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData );
+ if( m_blendData.ValidBlendMode )
+ {
+ AddId( blendParams, false );
+ }
+ }
+ }
+ //BLEND OP
+ {
+ int blendOpIdx = subBody.IndexOf( "BlendOp" );
+ if( blendOpIdx > 0 )
+ {
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendOpIdx );
+ string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx );
+ BlendData.BlendOpId = blendOpParams;
+ TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData );
+ if( m_blendData.ValidBlendOp )
+ {
+ AddId( blendOpParams, false );
+ }
+ }
+
+ m_blendData.DataCheck = ( m_blendData.ValidBlendMode || m_blendData.ValidBlendOp ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid;
+ }
+
+ //STENCIL
+ {
+ int stencilIdx = subBody.IndexOf( "Stencil" );
+ if( stencilIdx > -1 )
+ {
+ int stencilEndIdx = subBody.IndexOf( "}", stencilIdx );
+ if( stencilEndIdx > 0 )
+ {
+ string stencilParams = subBody.Substring( stencilIdx, stencilEndIdx + 1 - stencilIdx );
+ m_stencilData.StencilBufferId = stencilParams;
+ TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData );
+ if( m_stencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ AddId( stencilParams, true );
+ }
+ }
+ }
+ }
+
+ //ZWRITE
+ {
+ int zWriteOpIdx = subBody.IndexOf( "ZWrite" );
+ if( zWriteOpIdx > -1 )
+ {
+ int zWriteEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zWriteOpIdx );
+ if( zWriteEndIdx > 0 )
+ {
+ m_depthData.ZWriteModeId = subBody.Substring( zWriteOpIdx, zWriteEndIdx + 1 - zWriteOpIdx );
+ TemplateHelperFunctions.CreateZWriteMode( m_depthData.ZWriteModeId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ AddId( m_depthData.ZWriteModeId, true );
+ }
+ }
+ }
+ }
+
+ //ZTEST
+ {
+ int zTestOpIdx = subBody.IndexOf( "ZTest" );
+ if( zTestOpIdx > -1 )
+ {
+ int zTestEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zTestOpIdx );
+ if( zTestEndIdx > 0 )
+ {
+ m_depthData.ZTestModeId = subBody.Substring( zTestOpIdx, zTestEndIdx + 1 - zTestOpIdx );
+ TemplateHelperFunctions.CreateZTestMode( m_depthData.ZTestModeId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ AddId( m_depthData.ZTestModeId, true );
+ }
+ }
+ }
+ }
+
+ //ZOFFSET
+ {
+ int zOffsetIdx = subBody.IndexOf( "Offset" );
+ if( zOffsetIdx > -1 )
+ {
+ int zOffsetEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zOffsetIdx );
+ if( zOffsetEndIdx > 0 )
+ {
+ m_depthData.OffsetId = subBody.Substring( zOffsetIdx, zOffsetEndIdx + 1 - zOffsetIdx );
+ TemplateHelperFunctions.CreateZOffsetMode( m_depthData.OffsetId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ AddId( m_depthData.OffsetId, true );
+ }
+ }
+ }
+
+ m_depthData.SetDataCheck();
+ }
+
+ //TAGS
+ {
+ int tagsIdx = subBody.IndexOf( "Tags" );
+ if( tagsIdx > -1 )
+ {
+ int tagsEndIdx = subBody.IndexOf( "}", tagsIdx );
+ if( tagsEndIdx > -1 )
+ {
+ m_tagData.Reset();
+ m_tagData.TagsId = subBody.Substring( tagsIdx, tagsEndIdx + 1 - tagsIdx );
+ TemplateHelperFunctions.CreateTags( ref m_tagData, true );
+ m_tagData.DataCheck = TemplateDataCheck.Valid;
+ AddId( m_tagData.TagsId, false );
+ }
+ else
+ {
+ m_tagData.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ else
+ {
+ m_tagData.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+ }
+
+ void FetchCommonTags()
+ {
+ // Name
+ try
+ {
+ int nameBegin = m_templateBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag );
+ if( nameBegin < 0 )
+ {
+ // Not a template
+ return;
+ }
+
+ int nameEnd = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, nameBegin );
+ int defaultBegin = nameBegin + TemplatesManager.TemplateShaderNameBeginTag.Length;
+ int defaultLength = nameEnd - defaultBegin;
+ m_defaultShaderName = m_templateBody.Substring( defaultBegin, defaultLength );
+ int[] nameIdx = m_defaultShaderName.AllIndexesOf( "\"" );
+ nameIdx[ 0 ] += 1; // Ignore the " character from the string
+ m_defaultShaderName = m_defaultShaderName.Substring( nameIdx[ 0 ], nameIdx[ 1 ] - nameIdx[ 0 ] );
+ m_shaderNameId = m_templateBody.Substring( nameBegin, nameEnd + TemplatesManager.TemplateFullEndTag.Length - nameBegin );
+ AddId( m_shaderNameId, false );
+
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ }
+
+ FetchSubShaderProperties();
+ // Vertex Data
+ {
+ int vertexDataTagBegin = m_templateBody.IndexOf( TemplatesManager.TemplateVertexDataTag );
+ if( vertexDataTagBegin > -1 )
+ {
+ m_vertexDataContainer.VertexDataStartIdx = vertexDataTagBegin;
+ int vertexDataTagEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, vertexDataTagBegin );
+ m_vertexDataContainer.VertexDataId = m_templateBody.Substring( vertexDataTagBegin, vertexDataTagEnd + TemplatesManager.TemplateEndOfLine.Length - vertexDataTagBegin );
+ int dataBeginIdx = m_templateBody.LastIndexOf( '{', vertexDataTagBegin, vertexDataTagBegin );
+ string vertexData = m_templateBody.Substring( dataBeginIdx + 1, vertexDataTagBegin - dataBeginIdx );
+
+ int parametersBegin = vertexDataTagBegin + TemplatesManager.TemplateVertexDataTag.Length;
+ string parameters = m_templateBody.Substring( parametersBegin, vertexDataTagEnd - parametersBegin );
+ m_vertexDataContainer.VertexData = TemplateHelperFunctions.CreateVertexDataList( vertexData, parameters );
+ AddId( m_vertexDataContainer.VertexDataId );
+ }
+ }
+
+ // Available interpolators
+ try
+ {
+ int interpDataBegin = m_templateBody.IndexOf( TemplatesManager.TemplateInterpolatorBeginTag );
+ if( interpDataBegin > -1 )
+ {
+ int interpDataEnd = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, interpDataBegin );
+ string interpDataId = m_templateBody.Substring( interpDataBegin, interpDataEnd + TemplatesManager.TemplateEndOfLine.Length - interpDataBegin );
+
+ int dataBeginIdx = m_templateBody.LastIndexOf( '{', interpDataBegin, interpDataBegin );
+ string interpData = m_templateBody.Substring( dataBeginIdx + 1, interpDataBegin - dataBeginIdx );
+
+ m_interpolatorDataContainer = TemplateHelperFunctions.CreateInterpDataList( interpData, interpDataId, 8 );
+ m_interpolatorDataContainer.InterpDataId = interpDataId;
+ m_interpolatorDataContainer.InterpDataStartIdx = interpDataBegin;
+ AddId( interpDataId );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ }
+
+
+ try
+ {
+ Dictionary<string, TemplateShaderPropertyData> duplicatesHelper = new Dictionary<string, TemplateShaderPropertyData>();
+ m_availableShaderProperties = new List<TemplateShaderPropertyData>();
+
+ // Common Tags
+ for( int i = 0; i < TemplatesManager.CommonTags.Length; i++ )
+ {
+ int idx = m_templateBody.IndexOf( TemplatesManager.CommonTags[ i ].Id );
+ if( idx > -1 )
+ {
+ string currentId = TemplatesManager.CommonTags[ i ].Id;
+
+ TemplateCommonTagId commonTagId = (TemplateCommonTagId)i;
+ switch( commonTagId )
+ {
+ // Properties
+ case TemplateCommonTagId.Property:
+ {
+ TemplateHelperFunctions.CreateShaderPropertiesList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper );
+ }
+ break;
+ // Globals
+ case TemplateCommonTagId.Global:
+ {
+ TemplateHelperFunctions.CreateShaderGlobalsList( m_templateBody.Substring( 0, idx + TemplatesManager.CommonTags[ i ].Id.Length ), ref m_availableShaderProperties, ref duplicatesHelper );
+ }
+ break;
+
+ //Tags
+ //case TemplateCommonTagId.Tag:
+ //{
+ // m_propertyList[ m_propertyList.Count - 1 ].Indentation = " ";
+ //}
+ //break;
+ //case TemplateCommonTagId.CullMode:
+ //{
+ // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
+ // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
+ // string cullParams = m_templateBody.Substring( newId, end - newId );
+ // currentId = m_templateBody.Substring( idx, end - idx );
+ // m_cullModeData.CullModeId = currentId;
+ // TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData );
+ //}
+ //break;
+ //Blend Mode
+ //case TemplateCommonTagId.BlendMode:
+ //{
+ // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
+ // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
+ // string blendParams = m_templateBody.Substring( newId, end - newId );
+ // currentId = m_templateBody.Substring( idx, end - idx );
+ // m_blendData.BlendModeId = currentId;
+ // TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData );
+ //}break;
+ //case TemplateCommonTagId.BlendOp:
+ //{
+ // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
+ // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
+ // currentId = m_templateBody.Substring( idx, end - idx );
+ // BlendData.BlendOpId = currentId;
+ // TemplateHelperFunctions.CreateBlendOp( m_templateBody.Substring( newId, end - newId ), ref m_blendData );
+ //}break;
+ //case TemplateCommonTagId.ColorMask:
+ //{
+ // int newId = idx + TemplatesManager.CommonTags[ i ].Id.Length;
+ // int end = m_templateBody.IndexOf( TemplatesManager.TemplateNewLine, newId );
+ // string colorMaskParams = m_templateBody.Substring( newId, end - newId );
+ // currentId = m_templateBody.Substring( idx, end - idx );
+ // m_colorMaskData.ColorMaskId = currentId;
+ // TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData );
+ //}
+ //break;
+ //case TemplateCommonTagId.StencilOp:
+ //{
+ // int id = m_templateBody.LastIndexOf( "Stencil" );
+ // if( id > -1 )
+ // {
+ // string stencilParams = m_templateBody.Substring( id, idx - id );
+ // currentId = stencilParams + TemplatesManager.TemplateStencilOpTag;
+ // m_stencilData.StencilBufferId = currentId;
+ // TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData );
+ // }
+
+ //}
+ //break;
+ default:
+ break;
+ }
+
+ //AddId( TemplatesManager.CommonTags[ i ] );
+ AddId( currentId, TemplatesManager.CommonTags[ i ].SearchIndentation, TemplatesManager.CommonTags[ i ].CustomIndentation );
+ }
+ }
+
+ duplicatesHelper.Clear();
+ duplicatesHelper = null;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ }
+ }
+
+ void FetchCodeAreas( string begin, MasterNodePortCategory category )
+ {
+ int areaBeginIndexes = m_templateBody.IndexOf( begin );
+
+ if( areaBeginIndexes > -1 )
+ {
+ int beginIdx = areaBeginIndexes + begin.Length;
+ int endIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx );
+ int length = endIdx - beginIdx;
+
+ string parameters = m_templateBody.Substring( beginIdx, length );
+
+ string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR );
+
+ string id = m_templateBody.Substring( areaBeginIndexes, endIdx + TemplatesManager.TemplateEndOfLine.Length - areaBeginIndexes );
+ string inParameters = parametersArr[ 0 ];
+ string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty;
+ if( category == MasterNodePortCategory.Fragment )
+ {
+ m_fragmentFunctionData = new TemplateFunctionData(-1, string.Empty, id, areaBeginIndexes, inParameters, outParameters, category );
+ }
+ else
+ {
+ m_vertexFunctionData = new TemplateFunctionData( -1, string.Empty,id, areaBeginIndexes, inParameters, outParameters, category );
+ }
+ AddId( id, true );
+ }
+ }
+
+ void FetchInputs( MasterNodePortCategory portCategory )
+ {
+ string beginTag = ( portCategory == MasterNodePortCategory.Fragment ) ? TemplatesManager.TemplateInputsFragBeginTag : TemplatesManager.TemplateInputsVertBeginTag;
+ int[] inputBeginIndexes = m_templateBody.AllIndexesOf( beginTag );
+ if( inputBeginIndexes != null && inputBeginIndexes.Length > 0 )
+ {
+ for( int i = 0; i < inputBeginIndexes.Length; i++ )
+ {
+ int inputEndIdx = m_templateBody.IndexOf( TemplatesManager.TemplateEndSectionTag, inputBeginIndexes[ i ] );
+ int defaultValueBeginIdx = inputEndIdx + TemplatesManager.TemplateEndSectionTag.Length;
+ int endLineIdx = m_templateBody.IndexOf( TemplatesManager.TemplateFullEndTag, defaultValueBeginIdx );
+
+ string defaultValue = m_templateBody.Substring( defaultValueBeginIdx, endLineIdx - defaultValueBeginIdx );
+ string tagId = m_templateBody.Substring( inputBeginIndexes[ i ], endLineIdx + TemplatesManager.TemplateFullEndTag.Length - inputBeginIndexes[ i ] );
+
+ int beginIndex = inputBeginIndexes[ i ] + beginTag.Length;
+ int length = inputEndIdx - beginIndex;
+ string inputData = m_templateBody.Substring( beginIndex, length );
+ string[] inputDataArray = inputData.Split( IOUtils.FIELD_SEPARATOR );
+ if( inputDataArray != null && inputDataArray.Length > 0 )
+ {
+ try
+ {
+ string portName = inputDataArray[ (int)TemplatePortIds.Name ];
+ WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), inputDataArray[ (int)TemplatePortIds.DataType ].ToUpper() );
+
+ int portUniqueIDArrIdx = (int)TemplatePortIds.UniqueId;
+ int portUniqueId = ( portUniqueIDArrIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portUniqueIDArrIdx ] ) : -1;
+ if( portUniqueId < 0 )
+ portUniqueId = m_inputDataList.Count;
+
+ int portOrderArrayIdx = (int)TemplatePortIds.OrderId;
+ int portOrderId = ( portOrderArrayIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portOrderArrayIdx ] ) : -1;
+ if( portOrderId < 0 )
+ portOrderId = m_inputDataList.Count;
+
+ AddInput( inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ }
+ }
+ }
+
+ //void FetchSnippets()
+ //{
+ // int[] codeSnippetAttribBeginIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribBegin );
+ // int[] codeSnippetAttribEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetAttribEnd );
+ // int[] codeSnippetEndIndexes = m_templateBody.AllIndexesOf( TemplatesManager.TemplateCodeSnippetEnd );
+
+ // if( codeSnippetAttribBeginIndexes != null && codeSnippetAttribBeginIndexes.Length > 0 &&
+ // codeSnippetAttribEndIndexes != null && codeSnippetAttribEndIndexes.Length > 0 &&
+ // codeSnippetEndIndexes != null && codeSnippetEndIndexes.Length > 0 &&
+ // codeSnippetEndIndexes.Length == codeSnippetAttribBeginIndexes.Length &&
+ // codeSnippetAttribBeginIndexes.Length == codeSnippetAttribEndIndexes.Length )
+ // {
+ // for( int i = 0; i < codeSnippetAttribBeginIndexes.Length; i++ )
+ // {
+ // // get attributes
+ // int startAttribIndex = codeSnippetAttribBeginIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribBegin.Length;
+ // int lengthAttrib = codeSnippetAttribEndIndexes[ i ] - startAttribIndex;
+ // string snippetAttribs = m_templateBody.Substring( startAttribIndex, lengthAttrib );
+ // string[] snippetAttribsArr = snippetAttribs.Split( IOUtils.FIELD_SEPARATOR );
+ // if( snippetAttribsArr != null && snippetAttribsArr.Length > 0 )
+ // {
+ // string attribName = snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Name ];
+ // TemplateCodeSnippetType attribType = (TemplateCodeSnippetType)Enum.Parse( typeof( TemplateCodeSnippetType ), snippetAttribsArr[ (int)TemplateCodeSnippetInfoIdx.Type ] );
+ // if( m_snippetElementsDict.ContainsKey( attribName ) )
+ // {
+ // if( m_snippetElementsDict[ attribName ].Type != attribType )
+ // {
+ // if( DebugConsoleWindow.DeveloperMode )
+ // Debug.LogWarning( "Found incompatible types for snippet " + attribName );
+ // }
+ // }
+ // else
+ // {
+ // switch( attribType )
+ // {
+ // case TemplateCodeSnippetType.Toggle:
+ // {
+ // //Register must be done by first instantiang the correct type and register it on both containers
+ // //Overrides don't work if we use the container reference into the other
+ // TemplateCodeSnippetToggle newSnippet = ScriptableObject.CreateInstance<TemplateCodeSnippetToggle>();
+ // newSnippet.Init( attribName, attribType );
+ // m_snippetElementsDict.Add( attribName, newSnippet );
+ // m_snippetElementsList.Add( newSnippet );
+ // }
+ // break;
+ // }
+
+ // }
+ // // Add initial tag indentation
+ // int indentationIndex = codeSnippetAttribBeginIndexes[ i ];
+ // int lengthAdjust = 0;
+ // for( ; indentationIndex > 0; indentationIndex--, lengthAdjust++ )
+ // {
+ // if( m_templateBody[ indentationIndex ] == TemplatesManager.TemplateNewLine )
+ // {
+ // indentationIndex += 1;
+ // lengthAdjust -= 1;
+ // break;
+ // }
+ // }
+
+ // if( indentationIndex > 0 )
+ // {
+ // string snippetId = m_templateBody.Substring( indentationIndex,
+ // codeSnippetEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetEnd.Length - codeSnippetAttribBeginIndexes[ i ] + lengthAdjust );
+
+ // int snippetCodeStart = codeSnippetAttribEndIndexes[ i ] + TemplatesManager.TemplateCodeSnippetAttribEnd.Length;
+ // int snippetCodeLength = codeSnippetEndIndexes[ i ] - snippetCodeStart;
+ // //Remove possible identation characters present between tag and last instruction
+ // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] != TemplatesManager.TemplateNewLine )
+ // {
+ // for( ; snippetCodeLength > 0; snippetCodeLength-- )
+ // {
+ // if( m_templateBody[ snippetCodeStart + snippetCodeLength - 1 ] == TemplatesManager.TemplateNewLine )
+ // break;
+ // }
+ // }
+
+ // if( snippetCodeLength > 0 )
+ // {
+ // string snippetCode = m_templateBody.Substring( snippetCodeStart, snippetCodeLength );
+ // TemplateCodeSnippetElement element = new TemplateCodeSnippetElement( snippetId, snippetCode );
+ // m_snippetElementsDict[ attribName ].AddSnippet( element );
+ // }
+ // }
+ // }
+ // }
+ // }
+ //}
+
+ //void RefreshSnippetInfo()
+ //{
+ // if( m_snippetElementsDict == null )
+ // {
+ // m_snippetElementsDict = new Dictionary<string, TemplateCodeSnippetBase>();
+ // }
+
+ // if( m_snippetElementsDict.Count != m_snippetElementsList.Count )
+ // {
+ // m_snippetElementsDict.Clear();
+ // for( int i = 0; i < m_snippetElementsList.Count; i++ )
+ // {
+ // m_snippetElementsDict.Add( m_snippetElementsList[ i ].NameId, m_snippetElementsList[ i ] );
+ // }
+ // }
+ //}
+
+ //public void DrawSnippetProperties( ParentNode owner )
+ //{
+ // for( int i = 0; i < m_snippetElementsList.Count; i++ )
+ // {
+ // m_snippetElementsList[ i ].DrawProperties( owner );
+ // }
+ //}
+
+ //public void InsertSnippets( ref string shaderBody )
+ //{
+ // for( int i = 0; i < m_snippetElementsList.Count; i++ )
+ // {
+ // m_snippetElementsList[ i ].InsertSnippet( ref shaderBody );
+ // }
+ //}
+
+ public void AddId( string ID, bool searchIndentation = true )
+ {
+ AddId( ID, searchIndentation, string.Empty );
+ }
+
+ public void AddId( string ID, bool searchIndentation, string customIndentation )
+ {
+ int propertyIndex = m_templateBody.IndexOf( ID );
+ if( propertyIndex > -1 )
+ {
+ if( searchIndentation )
+ {
+ int indentationIndex = -1;
+ for( int i = propertyIndex; i > 0; i-- )
+ {
+ if( m_templateBody[ i ] == TemplatesManager.TemplateNewLine )
+ {
+ indentationIndex = i + 1;
+ break;
+ }
+ }
+ if( indentationIndex > -1 )
+ {
+ int length = propertyIndex - indentationIndex;
+ string indentation = ( length > 0 ) ? m_templateBody.Substring( indentationIndex, length ) : string.Empty;
+ m_propertyList.Add( new TemplateProperty( ID, indentation, false ) );
+ }
+ }
+ else
+ {
+ m_propertyList.Add( new TemplateProperty( ID, customIndentation, true ) );
+ }
+ }
+ }
+
+ void BuildInfo()
+ {
+ if( m_propertyDict == null )
+ {
+ m_propertyDict = new Dictionary<string, TemplateProperty>();
+ }
+
+ if( m_propertyList.Count != m_propertyDict.Count )
+ {
+ m_propertyDict.Clear();
+ for( int i = 0; i < m_propertyList.Count; i++ )
+ {
+ m_propertyDict.Add( m_propertyList[ i ].Id, m_propertyList[ i ] );
+ }
+ }
+ }
+
+ public void ResetTemplateUsageData()
+ {
+ BuildInfo();
+ for( int i = 0; i < m_propertyList.Count; i++ )
+ {
+ m_propertyList[ i ].Used = false;
+ }
+ }
+
+ public void AddInput( int tagStartIdx, string tagId, string portName, string defaultValue, WirePortDataType dataType, MasterNodePortCategory portCategory, int portUniqueId, int portOrderId )
+ {
+ TemplateInputData inputData = new TemplateInputData( tagStartIdx, tagStartIdx, tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, string.Empty );
+ m_inputDataList.Add( inputData );
+ m_inputDataDict.Add( inputData.PortUniqueId, inputData );
+ AddId( tagId, false );
+ }
+
+ public override void Destroy()
+ {
+ if( m_vertexDataContainer != null )
+ {
+ m_vertexDataContainer.Destroy();
+ m_vertexDataContainer = null;
+ }
+
+ if( m_interpolatorDataContainer != null )
+ {
+ m_interpolatorDataContainer.Destroy();
+ m_interpolatorDataContainer = null;
+ }
+
+ if( m_availableShaderProperties != null )
+ {
+ m_availableShaderProperties.Clear();
+ m_availableShaderProperties = null;
+ }
+
+ if( m_propertyDict != null )
+ {
+ m_propertyDict.Clear();
+ m_propertyDict = null;
+ }
+
+ if( m_propertyList != null )
+ {
+ m_propertyList.Clear();
+ m_propertyList = null;
+ }
+
+ if( m_inputDataDict != null )
+ {
+ m_inputDataDict.Clear();
+ m_inputDataDict = null;
+ }
+
+ if( m_inputDataList != null )
+ {
+ m_inputDataList.Clear();
+ m_inputDataList = null;
+ }
+
+ if( m_localVarsList != null )
+ {
+ m_localVarsList.Clear();
+ m_localVarsList = null;
+ }
+ //if( m_snippetElementsDict != null )
+ //{
+ // m_snippetElementsDict.Clear();
+ // m_snippetElementsDict = null;
+ //}
+
+ //if( m_snippetElementsList != null )
+ //{
+ // for( int i = 0; i < m_snippetElementsList.Count; i++ )
+ // {
+ // GameObject.DestroyImmediate( m_snippetElementsList[ i ] );
+ // m_snippetElementsList[ i ] = null;
+ // }
+ // m_snippetElementsList.Clear();
+ // m_snippetElementsList = null;
+ //}
+
+ m_cullModeData = null;
+ m_blendData = null;
+ m_colorMaskData = null;
+ m_stencilData = null;
+ if( m_tagData != null )
+ {
+ m_tagData.Destroy();
+ m_tagData = null;
+ }
+ }
+
+ public void FillEmptyTags( ref string body )
+ {
+ body = body.Replace( TemplatesManager.TemplateLocalVarTag, string.Empty );
+ for( int i = 0; i < m_propertyList.Count; i++ )
+ {
+ if( !m_propertyList[ i ].Used )
+ {
+ if( m_propertyList[ i ].UseCustomIndentation )
+ {
+ body = body.Replace( m_propertyList[ i ].Id, string.Empty );
+ }
+ else
+ {
+ body = body.Replace( m_propertyList[ i ].Indentation + m_propertyList[ i ].Id, string.Empty );
+ }
+ }
+ }
+ }
+
+ public bool FillVertexInstructions( ref string body, params string[] values )
+ {
+ if( m_vertexFunctionData != null && !string.IsNullOrEmpty( m_vertexFunctionData.Id ) )
+ {
+ return FillTemplateBody( m_vertexFunctionData.Id, ref body, values );
+ }
+
+ if( values.Length > 0 )
+ {
+ UIUtils.ShowMessage( "Attemping to add vertex instructions on a template with no assigned vertex code area", MessageSeverity.Error );
+ return false;
+ }
+ return true;
+ }
+
+ public bool FillFragmentInstructions( ref string body, params string[] values )
+ {
+ if( m_fragmentFunctionData != null && !string.IsNullOrEmpty( m_fragmentFunctionData.Id ) )
+ {
+ return FillTemplateBody( m_fragmentFunctionData.Id, ref body, values );
+ }
+
+ if( values.Length > 0 )
+ {
+ UIUtils.ShowMessage( "Attemping to add fragment instructions on a template with no assigned vertex code area", MessageSeverity.Error );
+ return false;
+ }
+ return true;
+ }
+
+ // values must be unindented an without line feed
+ public bool FillTemplateBody( string id, ref string body, params string[] values )
+ {
+ if( values.Length == 0 )
+ {
+ return true;
+ }
+
+ BuildInfo();
+
+ if( m_propertyDict.ContainsKey( id ) )
+ {
+ string finalValue = string.Empty;
+ for( int i = 0; i < values.Length; i++ )
+ {
+
+ if( m_propertyDict[ id ].AutoLineFeed )
+ {
+ string[] valuesArr = values[ i ].Split( '\n' );
+ for( int j = 0; j < valuesArr.Length; j++ )
+ {
+ //first value will be automatically indented by the string replace
+ finalValue += ( ( i == 0 && j == 0 ) ? string.Empty : m_propertyDict[ id ].Indentation ) + valuesArr[ j ];
+ finalValue += TemplatesManager.TemplateNewLine;
+ }
+
+ }
+ else
+ {
+ //first value will be automatically indented by the string replace
+ finalValue += ( i == 0 ? string.Empty : m_propertyDict[ id ].Indentation ) + values[ i ];
+ }
+ }
+
+ body = body.Replace( id, finalValue );
+ m_propertyDict[ id ].Used = true;
+ return true;
+ }
+
+ if( values.Length > 1 || !string.IsNullOrEmpty( values[ 0 ] ) )
+ {
+ UIUtils.ShowMessage( string.Format( "Attempting to write data into inexistant tag {0}. Please review the template {1} body and consider adding the missing tag.", id, m_name ), MessageSeverity.Error );
+ return false;
+ }
+
+ return true;
+
+ }
+
+ public bool FillTemplateBody( string id, ref string body, List<PropertyDataCollector> values )
+ {
+ if( values.Count == 0 )
+ {
+ return true;
+ }
+
+ string[] array = new string[ values.Count ];
+ for( int i = 0; i < values.Count; i++ )
+ {
+ array[ i ] = values[ i ].PropertyName;
+ }
+ return FillTemplateBody( id, ref body, array );
+ }
+
+ public TemplateInputData InputDataFromId( int id )
+ {
+ if( m_inputDataDict == null )
+ m_inputDataDict = new Dictionary<int, TemplateInputData>();
+
+ if( m_inputDataDict.Count != m_inputDataList.Count )
+ {
+ m_inputDataDict.Clear();
+ for( int i = 0; i < m_inputDataList.Count; i++ )
+ {
+ m_inputDataDict.Add( m_inputDataList[ i ].PortUniqueId, m_inputDataList[ i ] );
+ }
+ }
+
+ if( m_inputDataDict.ContainsKey( id ) )
+ return m_inputDataDict[ id ];
+
+ return null;
+ }
+
+ public string GetVertexData( TemplateInfoOnSematics info )
+ {
+ int count = m_vertexDataContainer.VertexData.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_vertexDataContainer.VertexData[ i ].DataInfo == info )
+ {
+ return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_vertexFunctionData.InVarName, m_vertexDataContainer.VertexData[ i ].VarName );
+ }
+ }
+ return string.Empty;
+ }
+
+ public string GetInterpolatedData( TemplateInfoOnSematics info )
+ {
+ int count = m_interpolatorDataContainer.Interpolators.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_interpolatorDataContainer.Interpolators[ i ].DataInfo == info )
+ {
+ return string.Format( TemplateHelperFunctions.TemplateVarFormat, m_fragmentFunctionData.InVarName, m_interpolatorDataContainer.Interpolators[ i ].VarName );
+ }
+ }
+ return string.Empty;
+ }
+
+ public string InterpDataId { get { return m_interpolatorDataContainer.InterpDataId; } }
+ public string VertexDataId { get { return m_vertexDataContainer.VertexDataId; } }
+ public string ShaderNameId { get { return m_shaderNameId; } set { m_shaderNameId = value; } }
+ public string TemplateBody { get { return m_templateBody; } set { m_templateBody = value; } }
+ public List<TemplateInputData> InputDataList { get { return m_inputDataList; } set { m_inputDataList = value; } }
+ public List<TemplateLocalVarData> LocalVarsList { get { return m_localVarsList; } }
+ public List<TemplateVertexData> VertexDataList { get { return m_vertexDataContainer.VertexData; } }
+ public TemplateInterpData InterpolatorData { get { return m_interpolatorDataContainer; } }
+ public TemplateFunctionData VertexFunctionData { get { return m_vertexFunctionData; } set { m_vertexFunctionData = value; } }
+ public TemplateFunctionData FragmentFunctionData { get { return m_fragmentFunctionData; } set { m_fragmentFunctionData = value; } }
+ public List<TemplateShaderPropertyData> AvailableShaderProperties { get { return m_availableShaderProperties; } set { m_availableShaderProperties = value; } }
+ public TemplateBlendData BlendData { get { return m_blendData; } set { m_blendData = value; } }
+ public TemplateCullModeData CullModeData { get { return m_cullModeData; } set { m_cullModeData = value; } }
+ public TemplateColorMaskData ColorMaskData { get { return m_colorMaskData; } set { m_colorMaskData = value; } }
+ public TemplateStencilData StencilData { get { return m_stencilData; } set { m_stencilData = value; } }
+ public TemplateDepthData DepthData { get { return m_depthData; } set { m_depthData = value; } }
+ public TemplateTagsModuleData TagData { get { return m_tagData; } set { m_tagData = value; } }
+ private List<TemplateProperty> PropertyList { get { return m_propertyList; } set { m_propertyList = value; } }
+ public VertexDataContainer VertexDataContainer { get { return m_vertexDataContainer; } set { m_vertexDataContainer = value; } }
+ public TemplateInterpData InterpolatorDataContainer { get { return m_interpolatorDataContainer; } set { m_interpolatorDataContainer = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta
new file mode 100644
index 00000000..2002009f
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b03340e569366ae4dbd502e14c62e225
+timeCreated: 1493904667
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs
new file mode 100644
index 00000000..bc772311
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs
@@ -0,0 +1,2056 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEngine;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System;
+
+namespace AmplifyShaderEditor
+{
+ public enum NormalizeType
+ {
+ Off,
+ Regular,
+ Safe
+ }
+
+ public class InterpDataHelper
+ {
+ public string VarName;
+ public WirePortDataType VarType;
+ public bool IsSingleComponent;
+ public bool SetAtCompileTime;
+ public InterpDataHelper( WirePortDataType varType, string varName, bool isSingleComponent = true , bool setAtCompileTime = false )
+ {
+ VarName = varName;
+ VarType = varType;
+ IsSingleComponent = isSingleComponent;
+ SetAtCompileTime = setAtCompileTime;
+ }
+ }
+
+ public class TemplateCustomData
+ {
+ public WirePortDataType DataType;
+ public string Name;
+ public bool IsVertex;
+ public bool IsFragment;
+ public TemplateCustomData( string name, WirePortDataType dataType )
+ {
+ name = Name;
+ DataType = dataType;
+ IsVertex = false;
+ IsFragment = false;
+ }
+ }
+
+ public class TemplateInputParameters
+ {
+ public WirePortDataType Type;
+ public string Name;
+ public string Declaration;
+ public TemplateSemantics Semantic;
+ public TemplateInputParameters( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic, string custom = null )
+ {
+ Type = type;
+ Name = name;
+ Semantic = semantic;
+ Declaration = string.Format( "{0} {1} : {2}", UIUtils.PrecisionWirePortToCgType( precision, type ), Name, Semantic );
+ if( !string.IsNullOrEmpty( custom ) )
+ Declaration = custom;
+ }
+ }
+
+ public class TemplateDataCollector
+ {
+#if UNITY_2018_2_OR_NEWER
+ private const int MaxUV = 8;
+ private int[] m_UVUsage = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#else
+ private const int MaxUV = 4;
+ private int[] m_UVUsage = { 0, 0, 0, 0 };
+#endif
+ private int m_multipassSubshaderIdx = 0;
+ private int m_multipassPassIdx = 0;
+ private TemplateMultiPass m_currentTemplate;
+ private TemplateSRPType m_currentSRPType = TemplateSRPType.BuiltIn;
+
+ private Dictionary<string, TemplateCustomData> m_customInterpolatedData;
+ private Dictionary<string, TemplateVertexData> m_registeredVertexData;
+
+ private Dictionary<TemplateInfoOnSematics, InterpDataHelper> m_availableFragData;
+ private Dictionary<TemplateInfoOnSematics, InterpDataHelper> m_availableVertData;
+ private TemplateInterpData m_interpolatorData;
+ private Dictionary<TemplateSemantics, TemplateVertexData> m_vertexDataDict;
+ private TemplateData m_currentTemplateData;
+ private MasterNodeDataCollector m_currentDataCollector;
+ public Dictionary<TemplateSemantics, TemplateInputParameters> m_vertexInputParams;
+ public Dictionary<TemplateSemantics, TemplateInputParameters> m_fragmentInputParams;
+
+ private Dictionary<TemplateInfoOnSematics, TemplateLocalVarData> m_specialVertexLocalVars;
+ private Dictionary<TemplateInfoOnSematics, TemplateLocalVarData> m_specialFragmentLocalVars;
+
+ private List<PropertyDataCollector> m_lateDirectivesList = new List<PropertyDataCollector>();
+ private Dictionary<string, PropertyDataCollector> m_lateDirectivesDict = new Dictionary<string, PropertyDataCollector>();
+
+ private List<PropertyDataCollector> m_srpBatcherPropertiesList = new List<PropertyDataCollector>();
+ private List<PropertyDataCollector> m_fullSrpBatcherPropertiesList = new List<PropertyDataCollector>();
+ private Dictionary<string, PropertyDataCollector> m_srpBatcherPropertiesDict = new Dictionary<string, PropertyDataCollector>();
+
+ public void CopySRPPropertiesFromDataCollector( int nodeId, TemplateDataCollector dataCollector )
+ {
+ for( int i = 0; i < dataCollector.SrpBatcherPropertiesList.Count; i++ )
+ {
+ AddSRPBatcherProperty( nodeId, dataCollector.SrpBatcherPropertiesList[ i ].PropertyName );
+ }
+ }
+
+ public void AddSRPBatcherProperty( int nodeID, string property )
+ {
+ if( !m_srpBatcherPropertiesDict.ContainsKey( property ) )
+ {
+ PropertyDataCollector newValue = new PropertyDataCollector( nodeID, property );
+ m_srpBatcherPropertiesDict.Add( property, newValue );
+ m_srpBatcherPropertiesList.Add( newValue );
+ }
+ }
+
+ public void SetUVUsage( int uv, WirePortDataType type )
+ {
+ if( uv >= 0 && uv < MaxUV )
+ {
+ m_UVUsage[ uv ] = Mathf.Max( m_UVUsage[ uv ], TemplateHelperFunctions.DataTypeChannelUsage[ type ] );
+ }
+ }
+
+ public void SetUVUsage( int uv, int size )
+ {
+ if( uv >= 0 && uv < MaxUV )
+ {
+ m_UVUsage[ uv ] = Mathf.Max( m_UVUsage[ uv ], size );
+ }
+ }
+
+ public void CloseLateDirectives()
+ {
+ if( m_lateDirectivesList.Count > 0 )
+ {
+ m_lateDirectivesList.Add( new PropertyDataCollector( -1, string.Empty ) );
+ }
+ }
+
+ public void AddHDLightInfo()
+ {
+#if !UNITY_2018_3_OR_NEWER
+ AddLateDirective( AdditionalLineType.Custom, "#if (SHADERPASS != SHADERPASS_FORWARD) //On forward this info is already included" );
+ AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightDefinition.cs.hlsl" );
+ AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightLoop/Shadow.hlsl" );
+ AddLateDirective( AdditionalLineType.Include, "HDRP/Lighting/LightLoop/LightLoopDef.hlsl" );
+ AddLateDirective( AdditionalLineType.Custom, "#endif // End of light info includes" );
+#endif
+ }
+
+ public void AddLateDirective( AdditionalLineType type, string value )
+ {
+
+ if( !m_lateDirectivesDict.ContainsKey( value ) )
+ {
+ string formattedValue = string.Empty;
+ switch( type )
+ {
+ case AdditionalLineType.Include: formattedValue = string.Format( Constants.IncludeFormat, value ); break;
+ case AdditionalLineType.Define: formattedValue = string.Format( Constants.DefineFormat, value ); break;
+ case AdditionalLineType.Pragma: formattedValue = string.Format( Constants.PragmaFormat, value ); break;
+ case AdditionalLineType.Custom: formattedValue = value; break;
+ }
+ PropertyDataCollector property = new PropertyDataCollector( -1, formattedValue );
+ m_lateDirectivesDict.Add( value, property );
+ m_lateDirectivesList.Add( property );
+ }
+ }
+
+ public void SetMultipassInfo( TemplateMultiPass currentTemplate, int subShaderIdx, int passIdx, TemplateSRPType currentSRPType )
+ {
+ m_currentTemplate = currentTemplate;
+ m_multipassSubshaderIdx = subShaderIdx;
+ m_multipassPassIdx = passIdx;
+ m_currentSRPType = currentSRPType;
+ }
+
+ public bool HasDirective( AdditionalLineType type, string value )
+ {
+ switch( type )
+ {
+ case AdditionalLineType.Include:
+ {
+ return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasInclude( value ) ||
+ m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasInclude( value );
+ }
+ case AdditionalLineType.Define:
+ {
+ return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasDefine( value ) ||
+ m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasDefine( value );
+ }
+ case AdditionalLineType.Pragma:
+ {
+ return m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Modules.IncludePragmaContainer.HasPragma( value ) ||
+ m_currentTemplate.SubShaders[ m_multipassSubshaderIdx ].Passes[ m_multipassPassIdx ].Modules.IncludePragmaContainer.HasPragma( value );
+ }
+ }
+
+ return false;
+ }
+
+ public void FillSpecialVariables( TemplatePass currentPass )
+ {
+ m_specialVertexLocalVars = new Dictionary<TemplateInfoOnSematics, TemplateLocalVarData>();
+ m_specialFragmentLocalVars = new Dictionary<TemplateInfoOnSematics, TemplateLocalVarData>();
+ int localVarAmount = currentPass.LocalVarsList.Count;
+ for( int i = 0; i < localVarAmount; i++ )
+ {
+ if( currentPass.LocalVarsList[ i ].IsSpecialVar )
+ {
+ if( currentPass.LocalVarsList[ i ].Category == MasterNodePortCategory.Vertex )
+ {
+ m_specialVertexLocalVars.Add( currentPass.LocalVarsList[ i ].SpecialVarType, currentPass.LocalVarsList[ i ] );
+ }
+ else
+ {
+ m_specialFragmentLocalVars.Add( currentPass.LocalVarsList[ i ].SpecialVarType, currentPass.LocalVarsList[ i ] );
+ }
+ }
+ }
+ }
+
+ public void BuildFromTemplateData( MasterNodeDataCollector dataCollector, TemplateData templateData )
+ {
+ m_registeredVertexData = new Dictionary<string, TemplateVertexData>();
+ m_customInterpolatedData = new Dictionary<string, TemplateCustomData>();
+
+
+ m_currentDataCollector = dataCollector;
+ m_currentTemplateData = templateData;
+
+ m_vertexDataDict = new Dictionary<TemplateSemantics, TemplateVertexData>();
+ if( templateData.VertexDataList != null )
+ {
+ for( int i = 0; i < templateData.VertexDataList.Count; i++ )
+ {
+ m_vertexDataDict.Add( templateData.VertexDataList[ i ].Semantics, new TemplateVertexData( templateData.VertexDataList[ i ] ) );
+ }
+ }
+
+ m_availableFragData = new Dictionary<TemplateInfoOnSematics, InterpDataHelper>();
+ if( templateData.InterpolatorData != null && templateData.FragmentFunctionData != null )
+ {
+ m_interpolatorData = new TemplateInterpData( templateData.InterpolatorData );
+ int fragCount = templateData.InterpolatorData.Interpolators.Count;
+ for( int i = 0; i < fragCount; i++ )
+ {
+ string varName = string.Empty;
+ if( templateData.InterpolatorData.Interpolators[ i ].ExcludeStructPrefix )
+ {
+ varName = templateData.InterpolatorData.Interpolators[ i ].VarName;
+ }
+ else if( templateData.InterpolatorData.Interpolators[ i ].IsSingleComponent )
+ {
+ varName = string.Format( TemplateHelperFunctions.TemplateVarFormat,
+ templateData.FragmentFunctionData.InVarName,
+ templateData.InterpolatorData.Interpolators[ i ].VarNameWithSwizzle );
+ }
+ else
+ {
+ varName = string.Format( templateData.InterpolatorData.Interpolators[ i ].VarNameWithSwizzle, templateData.FragmentFunctionData.InVarName );
+ }
+
+ m_availableFragData.Add( templateData.InterpolatorData.Interpolators[ i ].DataInfo,
+ new InterpDataHelper( templateData.InterpolatorData.Interpolators[ i ].SwizzleType,
+ varName,
+ templateData.InterpolatorData.Interpolators[ i ].IsSingleComponent ) );
+ }
+ }
+
+
+ m_availableVertData = new Dictionary<TemplateInfoOnSematics, InterpDataHelper>();
+ if( templateData.VertexFunctionData != null && templateData.VertexDataList != null )
+ {
+ int vertCount = templateData.VertexDataList.Count;
+ for( int i = 0; i < vertCount; i++ )
+ {
+ string varName = string.Empty;
+ if( templateData.VertexDataList[ i ].ExcludeStructPrefix )
+ {
+ varName = templateData.VertexDataList[ i ].VarName;
+ }
+ else
+ {
+ varName = string.Format( TemplateHelperFunctions.TemplateVarFormat, templateData.VertexFunctionData.InVarName, templateData.VertexDataList[ i ].VarNameWithSwizzle );
+ }
+
+ m_availableVertData.Add( templateData.VertexDataList[ i ].DataInfo,
+ new InterpDataHelper( templateData.VertexDataList[ i ].SwizzleType,
+ varName,
+ templateData.VertexDataList[ i ].IsSingleComponent ) );
+ }
+ }
+ }
+
+ public void RegisterFragInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic, string custom )
+ {
+ if( m_fragmentInputParams == null )
+ m_fragmentInputParams = new Dictionary<TemplateSemantics, TemplateInputParameters>();
+
+ m_fragmentInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic, custom ) );
+ }
+
+ public void RegisterFragInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic )
+ {
+ if( m_fragmentInputParams == null )
+ m_fragmentInputParams = new Dictionary<TemplateSemantics, TemplateInputParameters>();
+
+ m_fragmentInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic ) );
+ }
+
+ public void RegisterVertexInputParams( WirePortDataType type, PrecisionType precision, string name, TemplateSemantics semantic )
+ {
+ if( m_vertexInputParams == null )
+ m_vertexInputParams = new Dictionary<TemplateSemantics, TemplateInputParameters>();
+
+ m_vertexInputParams.Add( semantic, new TemplateInputParameters( type, precision, name, semantic ) );
+ }
+
+ public string GetVertexId()
+ {
+ var precision = PrecisionType.Float;
+ bool useMasterNodeCategory = true;
+ MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment;
+
+ WirePortDataType type = WirePortDataType.UINT;
+ if( HasInfo( TemplateInfoOnSematics.VERTEXID, useMasterNodeCategory, customCategory ) )
+ {
+ InterpDataHelper info = GetInfo( TemplateInfoOnSematics.VERTEXID, useMasterNodeCategory, customCategory );
+ return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type, true );
+ }
+ else
+ {
+ MasterNodePortCategory portCategory = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ string name = "ase_vertexID";
+ return RegisterInfoOnSemantic( portCategory, TemplateInfoOnSematics.VERTEXID, TemplateSemantics.SV_VertexID, name, WirePortDataType.UINT, precision, true );
+ }
+
+ // need to review this later
+ //if( m_vertexInputParams != null && m_vertexInputParams.ContainsKey( TemplateSemantics.SV_VertexID ) )
+ //{
+ // if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex )
+ // return m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name;
+ //}
+ //else
+ //{
+ // RegisterVertexInputParams( WirePortDataType.UINT, PrecisionType.Float, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.SV_VertexID ], TemplateSemantics.SV_VertexID );
+ //}
+
+ //if( m_currentDataCollector.PortCategory != MasterNodePortCategory.Vertex )
+ // RegisterCustomInterpolatedData( m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name, WirePortDataType.INT, PrecisionType.Float, m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name );
+
+ //return m_vertexInputParams[ TemplateSemantics.SV_VertexID ].Name;
+ }
+#if UNITY_EDITOR_WIN
+ public string GetPrimitiveId()
+ {
+ if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.SV_PrimitiveID ) )
+ return m_fragmentInputParams[ TemplateSemantics.SV_PrimitiveID ].Name;
+
+ RegisterFragInputParams( WirePortDataType.UINT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.SV_PrimitiveID ], TemplateSemantics.SV_PrimitiveID );
+ return m_fragmentInputParams[ TemplateSemantics.SV_PrimitiveID ].Name;
+ }
+#endif
+ public string GetVFace( int uniqueId )
+ {
+ #if UNITY_2018_3_OR_NEWER
+ if( IsHDRP && ASEPackageManagerHelper.CurrentHDVersion >= ASESRPVersions.ASE_SRP_6_9_0 )
+ {
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.VFACE, WirePortDataType.FLOAT, PrecisionType.Float, ref result, true, MasterNodePortCategory.Fragment ) )
+ {
+ m_currentDataCollector.AddToDirectives( "#if !defined(ASE_NEED_CULLFACE)" );
+ m_currentDataCollector.AddToDirectives( "#define ASE_NEED_CULLFACE 1" );
+ m_currentDataCollector.AddToDirectives( "#endif //ASE_NEED_CULLFACE" );
+ return result;
+ }
+ else
+ {
+ if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.VFACE ) )
+ return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name;
+
+ string custom = "FRONT_FACE_TYPE "+ TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ] + " : FRONT_FACE_SEMANTIC";
+ RegisterFragInputParams( WirePortDataType.FLOAT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ], TemplateSemantics.VFACE, custom );
+ return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name;
+ }
+ }
+ else
+ #endif
+ {
+ if( m_fragmentInputParams != null && m_fragmentInputParams.ContainsKey( TemplateSemantics.VFACE ) )
+ return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name;
+
+ RegisterFragInputParams( WirePortDataType.FLOAT, PrecisionType.Half, TemplateHelperFunctions.SemanticsDefaultName[ TemplateSemantics.VFACE ], TemplateSemantics.VFACE );
+ return m_fragmentInputParams[ TemplateSemantics.VFACE ].Name;
+ }
+ }
+
+ public string GetShadowCoords( int uniqueId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ // overriding precision
+ var precision = PrecisionType.Float;
+
+ string worldPos = GetWorldPos( false, m_currentDataCollector.PortCategory );
+
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.SHADOWCOORDS, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+
+ string varName = GeneratorUtils.ShadowCoordsStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+
+ string shadowCoordsValue = string.Format( "TransformWorldToShadowCoord({0})", worldPos );
+ if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment )
+ {
+ worldPos = GetWorldPos( false, MasterNodePortCategory.Vertex );
+ m_currentDataCollector.AddLocalVariable( uniqueId, "#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) //la" );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, string.Format( "TransformWorldToShadowCoord({0})", worldPos ), false, MasterNodePortCategory.Fragment );
+ m_currentDataCollector.AddLocalVariable( uniqueId, "#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS) //la" );
+ m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, shadowCoordsValue );
+ m_currentDataCollector.AddLocalVariable( uniqueId, "#else //la" );
+ m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, "0" );
+ m_currentDataCollector.AddLocalVariable( uniqueId, "#endif //la" );
+ } else
+ {
+ m_currentDataCollector.AddLocalVariable( uniqueId, precision, WirePortDataType.FLOAT4, varName, shadowCoordsValue );
+ }
+ return varName;
+ }
+
+ public bool HasUV( int uvChannel )
+ {
+ return ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData.ContainsKey( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ) : m_availableVertData.ContainsKey( TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] );
+ }
+
+ public string GetUVName( int uvChannel, WirePortDataType dataType = WirePortDataType.FLOAT2 )
+ {
+ InterpDataHelper info = ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ];
+ if( dataType != info.VarType )
+ return info.VarName + UIUtils.GetAutoSwizzle( dataType );
+ else
+ return info.VarName;
+ }
+
+ public string GetTextureCoord( int uvChannel, string propertyName, int uniqueId, PrecisionType precisionType )
+ {
+ bool isVertex = ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex || m_currentDataCollector.PortCategory == MasterNodePortCategory.Tessellation );
+ string uvChannelName = string.Empty;
+ string propertyHelperVar = propertyName + "_ST";
+ m_currentDataCollector.AddToUniforms( uniqueId, "float4", propertyHelperVar, IsSRP );
+ string uvName = string.Empty;
+ if( m_currentDataCollector.TemplateDataCollectorInstance.HasUV( uvChannel ) )
+ {
+ uvName = m_currentDataCollector.TemplateDataCollectorInstance.GetUVName( uvChannel );
+ }
+ else
+ {
+ uvName = m_currentDataCollector.TemplateDataCollectorInstance.RegisterUV( uvChannel );
+ }
+
+ uvChannelName = "uv" + propertyName;
+ if( isVertex )
+ {
+ string value = string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" );
+ string lodLevel = "0";
+
+ value = "float4( " + value + ", 0 , " + lodLevel + " )";
+ m_currentDataCollector.AddLocalVariable( uniqueId, precisionType, WirePortDataType.FLOAT4, uvChannelName, value );
+ }
+ else
+ {
+ m_currentDataCollector.AddLocalVariable( uniqueId, precisionType, WirePortDataType.FLOAT2, uvChannelName, string.Format( Constants.TilingOffsetFormat, uvName, propertyHelperVar + ".xy", propertyHelperVar + ".zw" ) );
+ }
+ return uvChannelName;
+ }
+
+ public string GenerateAutoUVs( int uvChannel, WirePortDataType size = WirePortDataType.FLOAT2 )
+ {
+ string uvName = string.Empty;
+ if( HasUV( uvChannel ) )
+ {
+ uvName = GetUVName( uvChannel, size );
+ }
+ else
+ {
+ uvName = RegisterUV( uvChannel, size );
+ }
+ return uvName;
+ }
+
+ public string GetUV( int uvChannel, MasterNodePortCategory category = MasterNodePortCategory.Fragment, WirePortDataType size = WirePortDataType.FLOAT4 )
+ {
+ if( !HasUV( uvChannel ) )
+ {
+ RegisterUV( uvChannel, size );
+ }
+
+ InterpDataHelper info = ( category == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ];
+ return info.VarName;
+ }
+
+ public InterpDataHelper GetUVInfo( int uvChannel )
+ {
+ return ( m_currentDataCollector.PortCategory == MasterNodePortCategory.Fragment ) ? m_availableFragData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ] : m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ uvChannel ] ];
+ }
+
+ public string RegisterUV( int UVChannel, WirePortDataType size = WirePortDataType.FLOAT2 )
+ {
+ int channelsSize = TemplateHelperFunctions.DataTypeChannelUsage[ size ];
+ if( m_UVUsage[ UVChannel ] > channelsSize )
+ {
+ size = TemplateHelperFunctions.ChannelToDataType[ m_UVUsage[ UVChannel ] ];
+ }
+
+ if( m_currentDataCollector.PortCategory == MasterNodePortCategory.Vertex )
+ {
+ TemplateSemantics semantic = TemplateHelperFunctions.IntToSemantic[ UVChannel ];
+
+ if( m_vertexDataDict.ContainsKey( semantic ) )
+ {
+ return m_vertexDataDict[ semantic ].VarName;
+ }
+
+ string varName = TemplateHelperFunctions.BaseInterpolatorName + ( ( UVChannel > 0 ) ? UVChannel.ToString() : string.Empty );
+ m_availableVertData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ],
+ new InterpDataHelper( WirePortDataType.FLOAT4,
+ string.Format( TemplateHelperFunctions.TemplateVarFormat,
+ m_currentTemplateData.VertexFunctionData.InVarName,
+ varName ) ) );
+
+ m_currentDataCollector.AddToVertexInput(
+ string.Format( TemplateHelperFunctions.TexFullSemantic,
+ varName,
+ semantic ) );
+ RegisterOnVertexData( semantic, size, varName );
+ string finalVarName = m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ] ].VarName;
+ switch( size )
+ {
+ case WirePortDataType.FLOAT:
+ case WirePortDataType.INT:
+ case WirePortDataType.UINT:
+ finalVarName += ".x";
+ break;
+ case WirePortDataType.FLOAT2:
+ finalVarName += ".xy";
+ break;
+ case WirePortDataType.FLOAT3:
+ finalVarName += ".xyz";
+ break;
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR:
+ case WirePortDataType.OBJECT:
+ case WirePortDataType.FLOAT4x4:
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ case WirePortDataType.FLOAT3x3:
+ default:
+ break;
+ }
+ return finalVarName;
+ }
+ else
+ {
+ //search if the correct vertex data is set ...
+ TemplateInfoOnSematics info = TemplateHelperFunctions.IntToInfo[ UVChannel ];
+ TemplateSemantics vertexSemantics = TemplateSemantics.NONE;
+ foreach( KeyValuePair<TemplateSemantics, TemplateVertexData> kvp in m_vertexDataDict )
+ {
+ if( kvp.Value.DataInfo == info )
+ {
+ vertexSemantics = kvp.Key;
+ break;
+ }
+ }
+
+ // if not, add vertex data and create interpolator
+ if( vertexSemantics == TemplateSemantics.NONE )
+ {
+ vertexSemantics = TemplateHelperFunctions.IntToSemantic[ UVChannel ];
+
+ if( !m_vertexDataDict.ContainsKey( vertexSemantics ) )
+ {
+ string varName = TemplateHelperFunctions.BaseInterpolatorName + ( ( UVChannel > 0 ) ? UVChannel.ToString() : string.Empty );
+ m_availableVertData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ],
+ new InterpDataHelper( WirePortDataType.FLOAT4,
+ string.Format( TemplateHelperFunctions.TemplateVarFormat,
+ m_currentTemplateData.VertexFunctionData.InVarName,
+ varName ) ) );
+
+ m_currentDataCollector.AddToVertexInput(
+ string.Format( TemplateHelperFunctions.TexFullSemantic,
+ varName,
+ vertexSemantics ) );
+ RegisterOnVertexData( vertexSemantics, size, varName );
+ }
+ }
+
+ // either way create interpolator
+ TemplateVertexData availableInterp = RequestNewInterpolator( size, false );
+ if( availableInterp != null )
+ {
+ bool isPosition = vertexSemantics == TemplateSemantics.POSITION || vertexSemantics == TemplateSemantics.POSITION;
+
+ string interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle;
+ InterpDataHelper vertInfo = m_availableVertData[ TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ] ];
+ string interpDecl = string.Format( TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData( vertInfo.VarName, vertInfo.VarType, size , isPosition ) );
+ m_currentDataCollector.AddToVertexInterpolatorsDecl( interpDecl );
+ string finalVarName = m_currentTemplateData.FragmentFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle;
+ m_availableFragData.Add( TemplateHelperFunctions.IntToUVChannelInfo[ UVChannel ], new InterpDataHelper( size, finalVarName ) );
+ return finalVarName;
+ }
+ }
+ return string.Empty;
+ }
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ bool IsSemanticUsedOnInterpolator( TemplateSemantics semantics )
+ {
+ for( int i = 0; i < m_interpolatorData.Interpolators.Count; i++ )
+ {
+ if( m_interpolatorData.Interpolators[ i ].Semantics == semantics )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool HasInfo( TemplateInfoOnSematics info, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ return ( category == MasterNodePortCategory.Fragment ) ? m_availableFragData.ContainsKey( info ) : m_availableVertData.ContainsKey( info );
+ }
+
+ public InterpDataHelper GetInfo( TemplateInfoOnSematics info, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ if( category == MasterNodePortCategory.Fragment )
+ {
+ if( !m_availableFragData[ info ].SetAtCompileTime )
+ {
+ string defineValue = string.Empty;
+ if( TemplateHelperFunctions.InfoToDefineFrag.TryGetValue( info, out defineValue ) )
+ m_currentDataCollector.AddToDefines( -1, defineValue );
+ }
+ return m_availableFragData[ info ];
+ }
+ else
+ {
+ if( !m_availableVertData[ info ].SetAtCompileTime )
+ {
+ string defineValue = string.Empty;
+ if( TemplateHelperFunctions.InfoToDefineVertex.TryGetValue( info, out defineValue ) )
+ m_currentDataCollector.AddToDefines( -1, defineValue );
+ }
+ return m_availableVertData[ info ];
+ }
+ }
+
+ public string RegisterInfoOnSemantic( TemplateInfoOnSematics info, TemplateSemantics semantic, string name, WirePortDataType dataType, PrecisionType precisionType, bool requestNewInterpolator, string dataName = null )
+ {
+ return RegisterInfoOnSemantic( m_currentDataCollector.PortCategory, info, semantic, name, dataType, precisionType, requestNewInterpolator, dataName );
+ }
+ // This should only be used to semantics outside the text coord set
+ public string RegisterInfoOnSemantic( MasterNodePortCategory portCategory, TemplateInfoOnSematics info, TemplateSemantics semantic, string name, WirePortDataType dataType, PrecisionType precisionType, bool requestNewInterpolator, string dataName = null )
+ {
+ if( portCategory == MasterNodePortCategory.Vertex )
+ {
+ if( m_vertexDataDict.ContainsKey( semantic ) )
+ {
+ return m_vertexDataDict[ semantic ].VarName;
+ }
+
+ m_availableVertData.Add( info,
+ new InterpDataHelper( dataType,
+ string.Format( TemplateHelperFunctions.TemplateVarFormat,
+ m_currentTemplateData.VertexFunctionData.InVarName,
+ name ),true,true ) );
+
+ string vertInputVarType = UIUtils.PrecisionWirePortToCgType( precisionType, dataType );
+ m_currentDataCollector.AddToVertexInput(
+ string.Format( TemplateHelperFunctions.InterpFullSemantic,
+ vertInputVarType,
+ name,
+ semantic ) );
+ RegisterOnVertexData( semantic, dataType, name );
+ return m_availableVertData[ info ].VarName;
+ }
+ else
+ {
+ //search if the correct vertex data is set ...
+ TemplateSemantics vertexSemantics = TemplateSemantics.NONE;
+ foreach( KeyValuePair<TemplateSemantics, TemplateVertexData> kvp in m_vertexDataDict )
+ {
+ if( kvp.Value.DataInfo == info )
+ {
+ vertexSemantics = kvp.Key;
+ break;
+ }
+ }
+
+ // if not, add vertex data and create interpolator
+ if( vertexSemantics == TemplateSemantics.NONE )
+ {
+ vertexSemantics = semantic;
+
+ if( !m_vertexDataDict.ContainsKey( vertexSemantics ) )
+ {
+ m_availableVertData.Add( info,
+ new InterpDataHelper( dataType,
+ string.Format( TemplateHelperFunctions.TemplateVarFormat,
+ m_currentTemplateData.VertexFunctionData.InVarName,
+ name ),true,true ) );
+
+ string vertInputVarType = UIUtils.PrecisionWirePortToCgType( precisionType, dataType );
+ m_currentDataCollector.AddToVertexInput(
+ string.Format( TemplateHelperFunctions.InterpFullSemantic,
+ vertInputVarType,
+ name,
+ vertexSemantics ) );
+ RegisterOnVertexData( vertexSemantics, dataType, name );
+ }
+ }
+
+ // either way create interpolator
+
+ TemplateVertexData availableInterp = null;
+ if( requestNewInterpolator || IsSemanticUsedOnInterpolator( semantic ) )
+ {
+ availableInterp = RequestNewInterpolator( dataType, false, dataName );
+ }
+ else
+ {
+ availableInterp = RegisterOnInterpolator( semantic, dataType, dataName );
+ }
+
+ if( availableInterp != null )
+ {
+ bool isPosition = vertexSemantics == TemplateSemantics.POSITION || vertexSemantics == TemplateSemantics.POSITION;
+
+ string interpVarName = m_currentTemplateData.VertexFunctionData.OutVarName + "." + availableInterp.VarNameWithSwizzle;
+ string interpDecl = string.Format( TemplateHelperFunctions.TemplateVariableDecl, interpVarName, TemplateHelperFunctions.AutoSwizzleData( m_availableVertData[ info ].VarName, m_availableVertData[ info ].VarType, dataType, isPosition ) );
+ m_currentDataCollector.AddToVertexInterpolatorsDecl( interpDecl );
+ string finalVarName = m_currentTemplateData.FragmentFunctionData.InVarName + "." + availableInterp.VarNameWithSwizzle;
+ m_availableFragData.Add( info, new InterpDataHelper( dataType, finalVarName ) );
+ return finalVarName;
+ }
+ }
+ return string.Empty;
+ }
+
+ TemplateVertexData RegisterOnInterpolator( TemplateSemantics semantics, WirePortDataType dataType, string vertexDataName = null )
+ {
+ if( vertexDataName == null )
+ {
+ if( TemplateHelperFunctions.SemanticsDefaultName.ContainsKey( semantics ) )
+ {
+ vertexDataName = TemplateHelperFunctions.SemanticsDefaultName[ semantics ];
+ }
+ else
+ {
+ vertexDataName = string.Empty;
+ Debug.LogError( "No valid name given to vertex data" );
+ }
+ }
+
+ TemplateVertexData data = new TemplateVertexData( semantics, dataType, vertexDataName );
+ m_interpolatorData.Interpolators.Add( data );
+ string interpolator = string.Format( TemplateHelperFunctions.InterpFullSemantic, UIUtils.WirePortToCgType( dataType ), data.VarName, data.Semantics );
+ m_currentDataCollector.AddToInterpolators( interpolator );
+ return data;
+ }
+
+ public void RegisterOnVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName )
+ {
+ m_vertexDataDict.Add( semantics, new TemplateVertexData( semantics, dataType, varName ) );
+ }
+
+ public TemplateVertexData RequestMacroInterpolator( string varName )
+ {
+ if( varName != null && m_registeredVertexData.ContainsKey( varName ) )
+ {
+ return m_registeredVertexData[ varName ];
+ }
+
+ for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ )
+ {
+ if( !m_interpolatorData.AvailableInterpolators[ i ].IsFull )
+ {
+ TemplateVertexData data = m_interpolatorData.AvailableInterpolators[ i ].RequestChannels( WirePortDataType.FLOAT4, false, varName );
+ if( data != null )
+ {
+ if( !m_registeredVertexData.ContainsKey( data.VarName ) )
+ {
+ m_registeredVertexData.Add( data.VarName, data );
+ }
+ if( m_interpolatorData.AvailableInterpolators[ i ].Usage == 1 )
+ {
+ string interpolator = string.Format( TemplateHelperFunctions.InterpMacro, varName, TemplateHelperFunctions.SemanticToInt[ data.Semantics ] );
+ m_currentDataCollector.AddToInterpolators( interpolator );
+ }
+ return data;
+ }
+ }
+ }
+ return null;
+ }
+
+ public bool HasRawInterpolatorOfName( string name )
+ {
+ return m_interpolatorData.HasRawInterpolatorOfName( name );
+ }
+
+ public TemplateVertexData RequestNewInterpolator( WirePortDataType dataType, bool isColor, string varName = null )
+ {
+ if( varName != null && m_registeredVertexData.ContainsKey( varName ) )
+ {
+ return m_registeredVertexData[ varName ];
+ }
+
+ for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ )
+ {
+ if( !m_interpolatorData.AvailableInterpolators[ i ].IsFull )
+ {
+ TemplateVertexData data = m_interpolatorData.AvailableInterpolators[ i ].RequestChannels( dataType, isColor, varName );
+ if( data != null )
+ {
+ if( !m_registeredVertexData.ContainsKey( data.VarName ) )
+ {
+ m_registeredVertexData.Add( data.VarName, data );
+ }
+
+ if( m_interpolatorData.AvailableInterpolators[ i ].Usage == 1 )
+ {
+ // First time using this interpolator, so we need to register it
+ string interpolator = string.Format( TemplateHelperFunctions.TexFullSemantic,
+ data.VarName, data.Semantics );
+ m_currentDataCollector.AddToInterpolators( interpolator );
+ }
+ return data;
+ }
+ }
+ }
+
+ // This area is reached if max available interpolators from shader model is reached
+ // Nevertheless, we register all new interpolators to that list so no imediate compilation errors are thrown
+ // A warning message is then thrown to warn the user about this
+ int newInterpId = 1 + TemplateHelperFunctions.SemanticToInt[ m_interpolatorData.AvailableInterpolators[ m_interpolatorData.AvailableInterpolators.Count - 1 ].Semantic ];
+ if( TemplateHelperFunctions.IntToSemantic.ContainsKey( newInterpId ) )
+ {
+ TemplateInterpElement item = new TemplateInterpElement( TemplateHelperFunctions.IntToSemantic[ newInterpId ] );
+ m_interpolatorData.AvailableInterpolators.Add( item );
+ TemplateVertexData data = item.RequestChannels( dataType, isColor, varName );
+ if( data != null )
+ {
+ if( !m_registeredVertexData.ContainsKey( data.VarName ) )
+ {
+ m_registeredVertexData.Add( data.VarName, data );
+ }
+
+ if( item.Usage == 1 )
+ {
+ string interpolator = string.Format( TemplateHelperFunctions.TexFullSemantic, data.VarName, data.Semantics );
+ m_currentDataCollector.AddToInterpolators( interpolator );
+ }
+ return data;
+ }
+ }
+
+ UIUtils.ShowMessage( "Maximum amount of interpolators exceeded", MessageSeverity.Error );
+ return null;
+ }
+
+ // Unused channels in interpolators must be set to something so the compiler doesn't generate warnings
+ public List<string> GetInterpUnusedChannels()
+ {
+ List<string> resetInstrucctions = new List<string>();
+
+ if( m_interpolatorData != null )
+ {
+ for( int i = 0; i < m_interpolatorData.AvailableInterpolators.Count; i++ )
+ {
+ if( m_interpolatorData.AvailableInterpolators[ i ].Usage > 0 && !m_interpolatorData.AvailableInterpolators[ i ].IsFull )
+ {
+ string channels = string.Empty;
+ bool[] availableChannels = m_interpolatorData.AvailableInterpolators[ i ].AvailableChannels;
+ for( int j = 0; j < availableChannels.Length; j++ )
+ {
+ if( availableChannels[ j ] )
+ {
+ channels += TemplateHelperFunctions.VectorSwizzle[ j ];
+ }
+ }
+
+ resetInstrucctions.Add( string.Format( "{0}.{1}.{2} = 0;", m_currentTemplateData.VertexFunctionData.OutVarName, m_interpolatorData.AvailableInterpolators[ i ].Name, channels ) );
+ }
+ }
+ }
+
+ if( resetInstrucctions.Count > 0 )
+ {
+ resetInstrucctions.Insert( 0, "\n//setting value to unused interpolator channels and avoid initialization warnings" );
+ }
+
+ return resetInstrucctions;
+ }
+
+ public bool GetCustomInterpolatedData( TemplateInfoOnSematics info, WirePortDataType type, PrecisionType precisionType, ref string result, bool useMasterNodeCategory, MasterNodePortCategory customCategory )
+ {
+ bool isPosition = info == TemplateInfoOnSematics.POSITION ||
+ info == TemplateInfoOnSematics.CLIP_POS ||
+ info == TemplateInfoOnSematics.SCREEN_POSITION ||
+ info == TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED ||
+ info == TemplateInfoOnSematics.WORLD_POSITION ||
+ info == TemplateInfoOnSematics.RELATIVE_WORLD_POS;
+
+
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ if( category == MasterNodePortCategory.Vertex )
+ {
+ if( m_specialVertexLocalVars.ContainsKey( info ) )
+ {
+ result = m_specialVertexLocalVars[ info ].LocalVarName;
+ if( m_specialVertexLocalVars[ info ].DataType != type )
+ {
+ result = TemplateHelperFunctions.AutoSwizzleData( result, m_specialVertexLocalVars[ info ].DataType, type , isPosition );
+ }
+
+ string defineValue = string.Empty;
+ if( TemplateHelperFunctions.InfoToDefineVertex.TryGetValue( info, out defineValue ) )
+ m_currentDataCollector.AddToDefines( -1, defineValue );
+
+ return true;
+ }
+ }
+
+ if( category == MasterNodePortCategory.Fragment )
+ {
+ if( m_specialFragmentLocalVars.ContainsKey( info ) )
+ {
+ result = m_specialFragmentLocalVars[ info ].LocalVarName;
+ if( m_specialFragmentLocalVars[ info ].DataType != type )
+ {
+ result = TemplateHelperFunctions.AutoSwizzleData( result, m_specialFragmentLocalVars[ info ].DataType, type, isPosition );
+ }
+
+ string defineValue = string.Empty;
+ if( TemplateHelperFunctions.InfoToDefineFrag.TryGetValue( info, out defineValue ))
+ m_currentDataCollector.AddToDefines( -1, defineValue );
+ return true;
+ }
+
+ if( m_availableFragData.ContainsKey( info ) )
+ {
+ if( m_availableFragData[ info ].IsSingleComponent )
+ {
+ result = m_availableFragData[ info ].VarName;
+ if( m_availableFragData[ info ].VarType != type )
+ {
+ result = TemplateHelperFunctions.AutoSwizzleData( result, m_availableFragData[ info ].VarType, type, isPosition );
+ }
+ return true;
+ }
+ else if( TemplateHelperFunctions.InfoToLocalVar.ContainsKey( info ) && TemplateHelperFunctions.InfoToWirePortType.ContainsKey( info ) )
+ {
+ result = TemplateHelperFunctions.InfoToLocalVar[ info ];
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, TemplateHelperFunctions.InfoToWirePortType[ info ], result, m_availableFragData[ info ].VarName );
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public string GetVertexPosition( WirePortDataType type, PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( HasInfo( TemplateInfoOnSematics.POSITION, useMasterNodeCategory, customCategory ) )
+ {
+ InterpDataHelper info = GetInfo( TemplateInfoOnSematics.POSITION, useMasterNodeCategory, customCategory );
+ if( type != WirePortDataType.OBJECT && type != info.VarType )
+ return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type,true );
+ else
+ return info.VarName;
+ }
+ else
+ {
+ MasterNodePortCategory portCategory = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ string name = "ase_vertex_pos";
+ string varName = RegisterInfoOnSemantic( portCategory, TemplateInfoOnSematics.POSITION, TemplateSemantics.POSITION, name, WirePortDataType.FLOAT4, precisionType, true );
+ if( type != WirePortDataType.OBJECT && type != WirePortDataType.FLOAT4 )
+ return TemplateHelperFunctions.AutoSwizzleData( varName, WirePortDataType.FLOAT4, type,true );
+ else
+ return varName;
+ }
+ }
+
+ private const string InstancingLibStandard = "UnityInstancing.cginc";
+ private const string InstancingLibSRP = "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl";
+
+ public void SetupInstancing()
+ {
+ if( !HasInfo( TemplateInfoOnSematics.INSTANCE_ID ) )
+ {
+ m_currentDataCollector.AddToPragmas( -1, IOUtils.InstancedPropertiesHeader );
+ m_currentDataCollector.AddToIncludes( -1, IsSRP ? InstancingLibSRP : InstancingLibStandard );
+ m_currentDataCollector.AddToVertexInput( Constants.InstanceIdMacro );
+ m_currentDataCollector.AddToInterpolators( Constants.InstanceIdMacro );
+ m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Vertex, -1, string.Format( "UNITY_SETUP_INSTANCE_ID({0});", m_currentTemplateData.VertexFunctionData.InVarName ) );
+ m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Vertex, -1, string.Format( "UNITY_TRANSFER_INSTANCE_ID({0}, {1});", m_currentTemplateData.VertexFunctionData.InVarName, m_currentTemplateData.VertexFunctionData.OutVarName ) );
+ m_currentDataCollector.AddToLocalVariables( MasterNodePortCategory.Fragment, -1, string.Format( "UNITY_SETUP_INSTANCE_ID({0});", m_currentTemplateData.FragmentFunctionData.InVarName ) );
+ }
+ }
+
+ public string GetVertexColor( PrecisionType precisionType )
+ {
+ if( HasInfo( TemplateInfoOnSematics.COLOR ) )
+ {
+ return GetInfo( TemplateInfoOnSematics.COLOR ).VarName;
+ }
+ else
+ {
+ string name = "ase_color";
+ return RegisterInfoOnSemantic( TemplateInfoOnSematics.COLOR, TemplateSemantics.COLOR, name, WirePortDataType.FLOAT4, precisionType, false );
+ }
+ }
+
+ public string GetVertexNormal( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( HasInfo( TemplateInfoOnSematics.NORMAL, useMasterNodeCategory, customCategory ) )
+ {
+ InterpDataHelper info = GetInfo( TemplateInfoOnSematics.NORMAL, useMasterNodeCategory, customCategory );
+ return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, WirePortDataType.FLOAT3 , false);
+ }
+ else
+ {
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ string name = "ase_normal";
+ return RegisterInfoOnSemantic( category, TemplateInfoOnSematics.NORMAL, TemplateSemantics.NORMAL, name, WirePortDataType.FLOAT3, precisionType, false );
+ }
+ }
+
+ public string GetWorldNormal( PrecisionType precisionType = PrecisionType.Float, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, bool normalize = false )
+ {
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ if( normalize )
+ return string.Format( "normalize( {0} )", result );
+ else
+ return result;
+ }
+
+ string varName = normalize ? "normalizeWorldNormal" : GeneratorUtils.WorldNormalStr;
+
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldNormalValue = string.Empty;
+
+ if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3, precisionType, ref worldNormalValue, false, MasterNodePortCategory.Vertex ) )
+ {
+ string vertexNormal = GetVertexNormal( precisionType, false, MasterNodePortCategory.Vertex );
+ string formatStr = string.Empty;
+ if( IsSRP )
+ formatStr = "TransformObjectToWorldNormal({0})";
+ else
+ formatStr = "UnityObjectToWorldNormal({0})";
+ worldNormalValue = string.Format( formatStr, vertexNormal );
+ }
+
+ if( normalize )
+ worldNormalValue = string.Format( "normalize( {0} )", worldNormalValue );
+
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, worldNormalValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetWorldNormal( int uniqueId, PrecisionType precisionType, string normal, string outputId )
+ {
+ string tanToWorld0 = string.Empty;
+ string tanToWorld1 = string.Empty;
+ string tanToWorld2 = string.Empty;
+
+ GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2, true );
+
+ string tanNormal = "tanNormal" + outputId;
+ m_currentDataCollector.AddLocalVariable( uniqueId, "float3 " + tanNormal + " = " + normal + ";" );
+ return string.Format( "float3(dot({1},{0}), dot({2},{0}), dot({3},{0}))", tanNormal, tanToWorld0, tanToWorld1, tanToWorld2 );
+ }
+
+ public string GetVertexTangent( WirePortDataType type, PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( HasInfo( TemplateInfoOnSematics.TANGENT, useMasterNodeCategory, customCategory ) )
+ {
+ InterpDataHelper info = GetInfo( TemplateInfoOnSematics.TANGENT, useMasterNodeCategory, customCategory );
+ if( type != WirePortDataType.OBJECT && type != info.VarType )
+ return TemplateHelperFunctions.AutoSwizzleData( info.VarName, info.VarType, type , false);
+ else
+ return info.VarName;
+ }
+ else
+ {
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ string name = "ase_tangent";
+ string varName = RegisterInfoOnSemantic( category, TemplateInfoOnSematics.TANGENT, TemplateSemantics.TANGENT, name, WirePortDataType.FLOAT4, precisionType, false );
+ if( type != WirePortDataType.OBJECT && type != WirePortDataType.FLOAT4 )
+ return TemplateHelperFunctions.AutoSwizzleData( varName, WirePortDataType.FLOAT4, type , false );
+ else
+ return varName;
+ }
+ }
+
+ public string GetVertexBitangent( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string varName = GeneratorUtils.VertexBitangentStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string tangentValue = GetVertexTangent( WirePortDataType.FLOAT3, precisionType, false, MasterNodePortCategory.Vertex );
+ string normalValue = GetVertexNormal( precisionType, false, MasterNodePortCategory.Vertex );
+
+ string bitangentValue = string.Format( "cross({0},{1})", normalValue, tangentValue );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, bitangentValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetWorldTangent( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+
+ string varName = GeneratorUtils.WorldTangentStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldTangentValue = string.Empty;
+ if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3, precisionType, ref worldTangentValue, false, MasterNodePortCategory.Vertex ) )
+ {
+ string vertexTangent = GetVertexTangent( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex );
+ string formatStr = string.Empty;
+
+ if( IsSRP )
+ formatStr = "TransformObjectToWorldDir({0}.xyz)";
+ else
+ formatStr = "UnityObjectToWorldDir({0})";
+
+ worldTangentValue = string.Format( formatStr, vertexTangent );
+ }
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, worldTangentValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetTangentSign( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string varName = GeneratorUtils.VertexTangentSignStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string tangentValue = GetVertexTangent( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex );
+ string tangentSignValue = string.Format( "{0}.w * unity_WorldTransformParams.w", tangentValue );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT, precisionType, tangentSignValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+
+ public string GetWorldBinormal( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3, precisionType, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+
+ string varName = GeneratorUtils.WorldBitangentStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldBinormal = string.Empty;
+ if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3, precisionType, ref worldBinormal, false, MasterNodePortCategory.Vertex ) )
+ {
+ string worldNormal = GetWorldNormal( precisionType, false, MasterNodePortCategory.Vertex );
+ string worldtangent = GetWorldTangent( precisionType, false, MasterNodePortCategory.Vertex );
+ string tangentSign = GetTangentSign( precisionType, false, MasterNodePortCategory.Vertex );
+ worldBinormal = string.Format( "cross( {0}, {1} ) * {2}", worldNormal, worldtangent, tangentSign );
+ }
+
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, worldBinormal, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetWorldReflection( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, bool normalize = false )
+ {
+ string varName = GeneratorUtils.WorldReflectionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_REFL );
+ if( normalize )
+ varName = "normalized" + varName;
+
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldNormal = GetWorldNormal( precisionType );
+ string worldViewDir = GetViewDir();
+ string worldRefl = string.Format( "reflect(-{0}, {1})", worldViewDir, worldNormal );
+
+ if( normalize )
+ worldRefl = string.Format( "normalize( {0} )", worldRefl );
+
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, varName, worldRefl );
+ return varName;
+ }
+
+ public string GetWorldReflection( PrecisionType precisionType, string normal )
+ {
+ string tanToWorld0 = string.Empty;
+ string tanToWorld1 = string.Empty;
+ string tanToWorld2 = string.Empty;
+
+ GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2 );
+ string worldRefl = GetViewDir();
+
+ return string.Format( "reflect( -{0}, float3( dot( {2}, {1} ), dot( {3}, {1} ), dot( {4}, {1} ) ) )", worldRefl, normal, tanToWorld0, tanToWorld1, tanToWorld2 );
+ }
+
+ public string GetLightAtten( int uniqueId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ //string result = string.Empty;
+ //if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, PrecisionType.Float, ref result, useMasterNodeCategory, customCategory ) )
+ //{
+ // return result;
+ //}
+
+ //string varName = GeneratorUtils.WorldPositionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_POS );
+ //if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ // return varName;
+
+ //if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) )
+ //{
+ // UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate world pos" );
+ // return "fixed3(0,0,0)";
+ //}
+
+ //string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName;
+ //string worldPosConversion = string.Format( "mul(unity_ObjectToWorld, {0}).xyz", vertexPos );
+
+ //RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, worldPosConversion, useMasterNodeCategory, customCategory );
+ //return varName;
+
+ m_currentDataCollector.AddToIncludes( uniqueId, Constants.UnityAutoLightLib );
+ m_currentDataCollector.AddToDefines( uniqueId, "ASE_SHADOWS 1" );
+#if UNITY_5_6_OR_NEWER
+ RequestMacroInterpolator( "UNITY_SHADOW_COORDS" );
+#else
+ RequestMacroInterpolator( "SHADOW_COORDS" );
+ m_currentDataCollector.AddToPragmas( uniqueId, "multi_compile_fwdbase" );
+#endif
+ //string vOutName = CurrentTemplateData.VertexFunctionData.OutVarName;
+ string fInName = CurrentTemplateData.FragmentFunctionData.InVarName;
+ string worldPos = GetWorldPos();
+ m_currentDataCollector.AddLocalVariable( uniqueId, "UNITY_LIGHT_ATTENUATION(ase_atten, " + fInName + ", " + worldPos + ")" );
+ return "ase_atten";
+
+ }
+
+ public string GenerateRotationIndependentObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId )
+ {
+ string value = string.Empty;
+
+ if( m_currentSRPType != TemplateSRPType.BuiltIn )
+ {
+ value = "float3( length( GetWorldToObjectMatrix()[ 0 ].xyz ), length( GetWorldToObjectMatrix()[ 1 ].xyz ), length( GetWorldToObjectMatrix()[ 2 ].xyz ) )";
+ }
+ else
+ {
+ value = "float3( length( unity_WorldToObject[ 0 ].xyz ), length( unity_WorldToObject[ 1 ].xyz ), length( unity_WorldToObject[ 2 ].xyz ) )";
+ }
+ value = "( 1.0 / "+ value +" )";
+ dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, GeneratorUtils.ParentObjectScaleStr, value );
+ return GeneratorUtils.ParentObjectScaleStr;
+ }
+
+ public string GenerateObjectScale( ref MasterNodeDataCollector dataCollector, int uniqueId )
+ {
+ string value = string.Empty;
+
+ if( m_currentSRPType != TemplateSRPType.BuiltIn )
+ {
+ value = "float3( length( GetObjectToWorldMatrix()[ 0 ].xyz ), length( GetObjectToWorldMatrix()[ 1 ].xyz ), length( GetObjectToWorldMatrix()[ 2 ].xyz ) )";
+ }
+ else
+ {
+ value = "float3( length( unity_ObjectToWorld[ 0 ].xyz ), length( unity_ObjectToWorld[ 1 ].xyz ), length( unity_ObjectToWorld[ 2 ].xyz ) )";
+ }
+ dataCollector.AddLocalVariable( uniqueId, PrecisionType.Float, WirePortDataType.FLOAT3, GeneratorUtils.ObjectScaleStr, value );
+ return GeneratorUtils.ObjectScaleStr;
+ }
+
+ public string GetWorldPos( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ // overriding precision
+ var precision = PrecisionType.Float;
+
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+ else if( m_currentSRPType == TemplateSRPType.HD )
+ {
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.RELATIVE_WORLD_POS, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ string worldPosVarName = GeneratorUtils.WorldPositionStr;
+ string relWorldPosConversion = string.Format( "GetAbsolutePositionWS( {0} )", result );
+ m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, worldPosVarName, relWorldPosConversion );
+ return worldPosVarName;
+ }
+ }
+
+ string varName = GeneratorUtils.WorldPositionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.WORLD_POS );
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) )
+ {
+ UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate world pos" );
+ return "half3(0,0,0)";
+ }
+
+ string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName;
+
+ string worldPosConversion = string.Empty;
+
+ //Check if world pos already defined in the vertex body
+ if( !GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3, precision, ref worldPosConversion, false, MasterNodePortCategory.Vertex ) )
+ {
+ if( m_currentSRPType == TemplateSRPType.HD )
+ {
+#if UNITY_2018_3_OR_NEWER
+ worldPosConversion = string.Format( "GetAbsolutePositionWS( TransformObjectToWorld( ({0}).xyz ) )", vertexPos );
+#else
+ worldPosConversion = string.Format( "GetAbsolutePositionWS( mul( GetObjectToWorldMatrix(), {0}).xyz )", vertexPos );
+#endif
+ }
+ else if( m_currentSRPType == TemplateSRPType.Lightweight )
+ {
+ worldPosConversion = string.Format( "mul(GetObjectToWorldMatrix(), {0}).xyz", vertexPos );
+ }
+ else
+ {
+ worldPosConversion = string.Format( "mul(unity_ObjectToWorld, {0}).xyz", vertexPos );
+ }
+ }
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precision, worldPosConversion, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetClipPosForValue( string customVertexPos, string outputId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string varName = GeneratorUtils.ClipPositionStr + outputId;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) )
+ {
+ UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate clip pos" );
+ return "half4(0,0,0,0)";
+ }
+
+ string formatStr = string.Empty;
+ switch( m_currentSRPType )
+ {
+ default:
+ case TemplateSRPType.BuiltIn:
+ formatStr = "UnityObjectToClipPos({0})";
+ break;
+ case TemplateSRPType.HD:
+ formatStr = "TransformWorldToHClip( TransformObjectToWorld({0}))";
+ break;
+ case TemplateSRPType.Lightweight:
+ formatStr = "TransformObjectToHClip(({0}).xyz)";
+ break;
+ }
+
+ string clipSpaceConversion = string.Format( formatStr, customVertexPos );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, PrecisionType.Float, clipSpaceConversion, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetClipPos( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string varName = GeneratorUtils.ClipPositionStr;// "clipPos";
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ if( !m_availableVertData.ContainsKey( TemplateInfoOnSematics.POSITION ) )
+ {
+ UIUtils.ShowMessage( "Attempting to access inexisting vertex position to calculate clip pos" );
+ return "half4(0,0,0,0)";
+ }
+
+ string vertexPos = m_availableVertData[ TemplateInfoOnSematics.POSITION ].VarName;
+
+ string formatStr = string.Empty;
+ switch( m_currentSRPType )
+ {
+ default:
+ case TemplateSRPType.BuiltIn:
+ formatStr = "UnityObjectToClipPos({0})";
+ break;
+ case TemplateSRPType.HD:
+ formatStr = "TransformWorldToHClip( TransformObjectToWorld({0}))";
+ break;
+ case TemplateSRPType.Lightweight:
+ formatStr = "TransformObjectToHClip(({0}).xyz)";
+ break;
+ }
+
+ string clipSpaceConversion = string.Format( formatStr, vertexPos );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, PrecisionType.Float, clipSpaceConversion, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetScreenPosForValue( PrecisionType precision, string customVertexPos, string outputId, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ // overriding precision
+ precision = PrecisionType.Float;
+
+ string varName = UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS ) + outputId;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string clipSpacePos = GetClipPosForValue( customVertexPos, outputId, false, MasterNodePortCategory.Vertex );
+ string screenPosConversion = string.Empty;
+ if( m_currentSRPType == TemplateSRPType.HD )
+ {
+ screenPosConversion = string.Format( "ComputeScreenPos( {0} , _ProjectionParams.x )", clipSpacePos );
+ }
+ else
+ {
+ screenPosConversion = string.Format( "ComputeScreenPos({0})", clipSpacePos );
+ }
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, screenPosConversion, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetScreenPos( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ // overriding precision
+ precision = PrecisionType.Float;
+
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+
+ string varName = UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS );
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string clipSpacePos = GetClipPos( false, MasterNodePortCategory.Vertex );
+ string screenPosConversion = string.Empty;
+ if( m_currentSRPType == TemplateSRPType.HD )
+ {
+ screenPosConversion = string.Format( "ComputeScreenPos( {0} , _ProjectionParams.x )", clipSpacePos );
+ }
+ else
+ {
+ screenPosConversion = string.Format( "ComputeScreenPos({0})", clipSpacePos );
+ }
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT4, precision, screenPosConversion, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetScreenPosNormalized( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED, WirePortDataType.FLOAT4, precision, ref result, useMasterNodeCategory, customCategory ) )
+ {
+ return result;
+ }
+
+ string varName = GeneratorUtils.ScreenPositionNormalizedStr;// "norm" + UIUtils.GetInputValueFromType( SurfaceInputs.SCREEN_POS );
+ string screenPos = GetScreenPos( precision, useMasterNodeCategory, customCategory );
+ string clipPlaneTestOp = string.Format( "{0}.z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? {0}.z : {0}.z * 0.5 + 0.5;", varName );
+ m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT4, varName, string.Format( GeneratorUtils.NormalizedScreenPosFormat, screenPos ) );
+ m_currentDataCollector.AddLocalVariable( -1, clipPlaneTestOp );
+ return varName;
+ }
+
+ public string GetViewDir( bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, NormalizeType normalizeType = NormalizeType.Regular )
+ {
+ // overriding precision
+ var precision = PrecisionType.Float;
+
+ string result = string.Empty;
+ if( GetCustomInterpolatedData( TemplateInfoOnSematics.WORLD_VIEW_DIR, WirePortDataType.FLOAT3, precision, ref result, useMasterNodeCategory, customCategory ) )
+ return result;
+
+ string varName = GeneratorUtils.WorldViewDirectionStr;//UIUtils.GetInputValueFromType( SurfaceInputs.VIEW_DIR );
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldPos = GetWorldPos();
+
+ string formatStr = string.Empty;
+ if( IsSRP )
+ formatStr = "( _WorldSpaceCameraPos.xyz - {0} )";
+ else
+ formatStr = "UnityWorldSpaceViewDir({0})";
+
+ string viewDir = string.Format( formatStr, worldPos );
+ m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, varName, viewDir );
+
+ switch( normalizeType )
+ {
+ default:
+ case NormalizeType.Off:
+ break;
+ case NormalizeType.Regular:
+ m_currentDataCollector.AddLocalVariable( -1, varName + " = normalize(" + varName + ");" );
+ break;
+ case NormalizeType.Safe:
+ m_currentDataCollector.AddLocalVariable( -1, varName + " = " + TemplateHelperFunctions.SafeNormalize( m_currentDataCollector, varName ) + ";" );
+ break;
+ }
+
+
+ //RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, PrecisionType.Float, viewDir, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetTangentViewDir( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, NormalizeType normalizeType = NormalizeType.Regular )
+ {
+ string varName = GeneratorUtils.TangentViewDirectionStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string tanToWorld0 = string.Empty;
+ string tanToWorld1 = string.Empty;
+ string tanToWorld2 = string.Empty;
+
+ GetWorldTangentTf( precisionType, out tanToWorld0, out tanToWorld1, out tanToWorld2 );
+ string viewDir = GetViewDir();
+ string tanViewDir = string.Format( " {0} * {3}.x + {1} * {3}.y + {2} * {3}.z", tanToWorld0, tanToWorld1, tanToWorld2, viewDir );
+
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, varName, tanViewDir );
+ switch( normalizeType )
+ {
+ default:
+ case NormalizeType.Off: break;
+ case NormalizeType.Regular:
+ m_currentDataCollector.AddLocalVariable( -1, varName + " = normalize(" + varName + ");" );
+ break;
+ case NormalizeType.Safe:
+ m_currentDataCollector.AddLocalVariable( -1, varName + " = " + TemplateHelperFunctions.SafeNormalize( m_currentDataCollector, varName ) + ";" );
+ break;
+ }
+
+ return varName;
+ }
+
+ public void GetWorldTangentTf( PrecisionType precisionType, out string tanToWorld0, out string tanToWorld1, out string tanToWorld2, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ tanToWorld0 = "tanToWorld0";
+ tanToWorld1 = "tanToWorld1";
+ tanToWorld2 = "tanToWorld2";
+
+ if( HasCustomInterpolatedData( tanToWorld0, useMasterNodeCategory, customCategory ) ||
+ HasCustomInterpolatedData( tanToWorld1, useMasterNodeCategory, customCategory ) ||
+ HasCustomInterpolatedData( tanToWorld2, useMasterNodeCategory, customCategory ) )
+ return;
+
+ string worldTangent = GetWorldTangent( precisionType, useMasterNodeCategory, customCategory );
+ string worldNormal = GetWorldNormal( precisionType, useMasterNodeCategory, customCategory );
+ string worldBinormal = GetWorldBinormal( precisionType, useMasterNodeCategory, customCategory );
+
+ string tanToWorldVar0 = string.Format( "float3( {0}.x, {1}.x, {2}.x )", worldTangent, worldBinormal, worldNormal );
+ string tanToWorldVar1 = string.Format( "float3( {0}.y, {1}.y, {2}.y )", worldTangent, worldBinormal, worldNormal );
+ string tanToWorldVar2 = string.Format( "float3( {0}.z, {1}.z, {2}.z )", worldTangent, worldBinormal, worldNormal );
+
+ if( customCategory == MasterNodePortCategory.Vertex )
+ {
+ RegisterCustomInterpolatedData( tanToWorld0, WirePortDataType.FLOAT3, precisionType, tanToWorldVar0, useMasterNodeCategory, customCategory );
+ RegisterCustomInterpolatedData( tanToWorld1, WirePortDataType.FLOAT3, precisionType, tanToWorldVar1, useMasterNodeCategory, customCategory );
+ RegisterCustomInterpolatedData( tanToWorld2, WirePortDataType.FLOAT3, precisionType, tanToWorldVar2, useMasterNodeCategory, customCategory );
+ }
+ else
+ {
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld0, tanToWorldVar0 );
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld1, tanToWorldVar1 );
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3, tanToWorld2, tanToWorldVar2 );
+ }
+ }
+
+ public string GetTangentToWorldMatrixFast( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string worldTangent = GetWorldTangent( precisionType );
+ string worldNormal = GetWorldNormal( precisionType );
+ string worldBinormal = GetWorldBinormal( precisionType );
+
+ string varName = GeneratorUtils.TangentToWorldFastStr;
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string result = string.Format( "float3x3({0}.x,{1}.x,{2}.x,{0}.y,{1}.y,{2}.y,{0}.z,{1}.z,{2}.z)", worldTangent, worldBinormal, worldNormal );
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, GeneratorUtils.TangentToWorldFastStr, result );
+ return GeneratorUtils.TangentToWorldFastStr;
+ }
+
+ public string GetTangentToWorldMatrixPrecise( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string worldToTangent = GetWorldToTangentMatrix( precisionType, useMasterNodeCategory, customCategory );
+ GeneratorUtils.Add3x3InverseFunction( ref m_currentDataCollector, UIUtils.PrecisionWirePortToCgType( precisionType, WirePortDataType.FLOAT ) );
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, GeneratorUtils.TangentToWorldPreciseStr, string.Format( GeneratorUtils.Inverse3x3Header, worldToTangent ) );
+ return GeneratorUtils.TangentToWorldPreciseStr;
+ }
+
+ public string GetWorldToTangentMatrix( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ string worldTangent = GetWorldTangent( precisionType );
+ string worldNormal = GetWorldNormal( precisionType );
+ string worldBinormal = GetWorldBinormal( precisionType );
+
+ string varName = GeneratorUtils.WorldToTangentStr;// "worldToTanMat";
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+ string worldTanMat = string.Format( "float3x3({0},{1},{2})", worldTangent, worldBinormal, worldNormal );
+
+ m_currentDataCollector.AddLocalVariable( -1, precisionType, WirePortDataType.FLOAT3x3, varName, worldTanMat );
+ return varName;
+ }
+
+ public string GetObjectToViewPos( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ // overriding precision
+ precision = PrecisionType.Float;
+
+ string varName = "objectToViewPos";
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+ string vertexPos = GetVertexPosition( WirePortDataType.FLOAT3, precision, false, MasterNodePortCategory.Vertex );
+
+ string formatStr = string.Empty;
+ if( IsSRP )
+ formatStr = "TransformWorldToView(TransformObjectToWorld({0}))";
+ else
+ formatStr = "UnityObjectToViewPos({0})";
+
+ string objectToViewPosValue = string.Format( formatStr, vertexPos );
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precision, objectToViewPosValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetEyeDepth( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment, int viewSpace = 0 )
+ {
+ // overriding precision
+ precision = PrecisionType.Float;
+
+ string varName = "eyeDepth";
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+ string objectToView = GetObjectToViewPos( precision, false, MasterNodePortCategory.Vertex );
+ string eyeDepthValue = string.Format( "-{0}.z", objectToView );
+ if( viewSpace == 1 )
+ {
+ eyeDepthValue += " * _ProjectionParams.w";
+ }
+
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT, precision, eyeDepthValue, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetObjectSpaceLightDir( PrecisionType precisionType, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( !IsSRP )
+ {
+ m_currentDataCollector.AddToIncludes( -1, Constants.UnityLightingLib );
+ m_currentDataCollector.AddToIncludes( -1, Constants.UnityAutoLightLib );
+ }
+
+ string varName = "objectSpaceLightDir";
+
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string vertexPos = GetVertexPosition( WirePortDataType.FLOAT4, precisionType, false, MasterNodePortCategory.Vertex );
+
+ string objectSpaceLightDir = string.Empty;
+ switch( m_currentSRPType )
+ {
+ default:
+ case TemplateSRPType.BuiltIn:
+ objectSpaceLightDir = string.Format( "ObjSpaceLightDir({0})", vertexPos );
+ break;
+ case TemplateSRPType.HD:
+ string worldSpaceLightDir = GetWorldSpaceLightDir( precisionType, useMasterNodeCategory, customCategory );
+ objectSpaceLightDir = string.Format( "mul( GetWorldToObjectMatrix(), {0} ).xyz", worldSpaceLightDir );
+ break;
+ case TemplateSRPType.Lightweight:
+ objectSpaceLightDir = "mul( GetWorldToObjectMatrix(), _MainLightPosition ).xyz";
+ break;
+ }
+
+ RegisterCustomInterpolatedData( varName, WirePortDataType.FLOAT3, precisionType, objectSpaceLightDir, useMasterNodeCategory, customCategory );
+ return varName;
+ }
+
+ public string GetWorldSpaceLightDir( PrecisionType precision, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( !IsSRP )
+ {
+ m_currentDataCollector.AddToIncludes( -1, Constants.UnityLightingLib );
+ m_currentDataCollector.AddToIncludes( -1, Constants.UnityAutoLightLib );
+ AddLateDirective( AdditionalLineType.Custom, "//This is a late directive" );
+ }
+ else
+ {
+
+ string lightVar;
+ if( m_currentSRPType == TemplateSRPType.HD )
+ {
+ AddHDLightInfo();
+ lightVar = "-" + string.Format( TemplateHelperFunctions.HDLightInfoFormat, "0", "forward" );
+ }
+ else
+ {
+ lightVar = "_MainLightPosition.xyz";
+ }
+ return m_currentDataCollector.SafeNormalizeLightDir ? string.Format( "SafeNormalize({0})", lightVar ) : lightVar;
+ }
+
+ string varName = "worldSpaceLightDir";
+ if( HasCustomInterpolatedData( varName, useMasterNodeCategory, customCategory ) )
+ return varName;
+
+ string worldPos = GetWorldPos( useMasterNodeCategory, customCategory );
+ string worldSpaceLightDir = string.Format( "UnityWorldSpaceLightDir({0})", worldPos );
+ if( m_currentDataCollector.SafeNormalizeLightDir )
+ {
+ if( IsSRP )
+ {
+ worldSpaceLightDir = string.Format( "SafeNormalize{0})", worldSpaceLightDir );
+ }
+ else
+ {
+ m_currentDataCollector.AddToIncludes( -1, Constants.UnityBRDFLib );
+ worldSpaceLightDir = string.Format( "Unity_SafeNormalize({0})", worldSpaceLightDir );
+ }
+ }
+
+ m_currentDataCollector.AddLocalVariable( -1, precision, WirePortDataType.FLOAT3, varName, worldSpaceLightDir );
+ return varName;
+ }
+
+ public void RegisterCustomInterpolatedData( string name, WirePortDataType dataType, PrecisionType precision, string vertexInstruction, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ bool addLocalVariable = !name.Equals( vertexInstruction );
+
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+
+ if( !m_customInterpolatedData.ContainsKey( name ) )
+ {
+ m_customInterpolatedData.Add( name, new TemplateCustomData( name, dataType ) );
+ }
+
+ if( !m_customInterpolatedData[ name ].IsVertex )
+ {
+ m_customInterpolatedData[ name ].IsVertex = true;
+ if( addLocalVariable )
+ m_currentDataCollector.AddToVertexLocalVariables( -1, precision, dataType, name, vertexInstruction );
+ }
+
+ if( category == MasterNodePortCategory.Fragment )
+ {
+ if( !m_customInterpolatedData[ name ].IsFragment )
+ {
+ m_customInterpolatedData[ name ].IsFragment = true;
+ TemplateVertexData interpData = RequestNewInterpolator( dataType, false );
+ if( interpData == null )
+ {
+ Debug.LogErrorFormat( "Could not assign interpolator of type {0} to variable {1}", dataType, name );
+ return;
+ }
+
+ m_currentDataCollector.AddToVertexLocalVariables( -1, m_currentTemplateData.VertexFunctionData.OutVarName + "." + interpData.VarNameWithSwizzle, name );
+ m_currentDataCollector.AddToLocalVariables( -1, precision, dataType, name, m_currentTemplateData.FragmentFunctionData.InVarName + "." + interpData.VarNameWithSwizzle );
+ }
+ }
+ }
+
+ public bool HasCustomInterpolatedData( string name, bool useMasterNodeCategory = true, MasterNodePortCategory customCategory = MasterNodePortCategory.Fragment )
+ {
+ if( m_customInterpolatedData.ContainsKey( name ) )
+ {
+ MasterNodePortCategory category = useMasterNodeCategory ? m_currentDataCollector.PortCategory : customCategory;
+ return ( category == MasterNodePortCategory.Fragment ) ? m_customInterpolatedData[ name ].IsFragment : m_customInterpolatedData[ name ].IsVertex;
+ }
+ return false;
+ }
+
+ public bool HasFragmentInputParams
+ {
+ get
+ {
+ if( m_fragmentInputParams != null )
+ return m_fragmentInputParams.Count > 0;
+
+ return false;
+ }
+ }
+
+ public string FragInputParamsStr
+ {
+ get
+ {
+ string value = string.Empty;
+ if( m_fragmentInputParams != null && m_fragmentInputParams.Count > 0 )
+ {
+ int count = m_fragmentInputParams.Count;
+ if( count > 0 )
+ {
+ value = ", ";
+ foreach( KeyValuePair<TemplateSemantics, TemplateInputParameters> kvp in m_fragmentInputParams )
+ {
+ value += kvp.Value.Declaration;
+
+ if( --count > 0 )
+ {
+ value += " , ";
+ }
+ }
+ }
+ }
+ return value;
+ }
+ }
+
+ public string VertexInputParamsStr
+ {
+ get
+ {
+ string value = string.Empty;
+ if( m_vertexInputParams != null && m_vertexInputParams.Count > 0 )
+ {
+ int count = m_vertexInputParams.Count;
+ if( count > 0 )
+ {
+ value = ", ";
+ foreach( KeyValuePair<TemplateSemantics, TemplateInputParameters> kvp in m_vertexInputParams )
+ {
+ value += kvp.Value.Declaration;
+
+ if( --count > 0 )
+ {
+ value += " , ";
+ }
+ }
+ }
+ }
+ return value;
+ }
+ }
+
+ public void Destroy()
+ {
+ m_currentTemplate = null;
+
+ m_currentTemplateData = null;
+
+ m_currentDataCollector = null;
+
+ if( m_fullSrpBatcherPropertiesList != null )
+ {
+ m_fullSrpBatcherPropertiesList.Clear();
+ m_fullSrpBatcherPropertiesList = null;
+ }
+
+ if( m_srpBatcherPropertiesList != null )
+ {
+ m_srpBatcherPropertiesList.Clear();
+ m_srpBatcherPropertiesList = null;
+ }
+
+ if( m_srpBatcherPropertiesDict != null )
+ {
+ m_srpBatcherPropertiesDict.Clear();
+ m_srpBatcherPropertiesDict = null;
+ }
+
+ if( m_lateDirectivesList != null )
+ {
+ m_lateDirectivesList.Clear();
+ m_lateDirectivesList = null;
+ }
+
+ if( m_lateDirectivesDict != null )
+ {
+ m_lateDirectivesDict.Clear();
+ m_lateDirectivesDict = null;
+ }
+
+ if( m_registeredVertexData != null )
+ {
+ m_registeredVertexData.Clear();
+ m_registeredVertexData = null;
+ }
+
+ if( m_vertexInputParams != null )
+ {
+ m_vertexInputParams.Clear();
+ m_vertexInputParams = null;
+ }
+
+ if( m_fragmentInputParams != null )
+ {
+ m_fragmentInputParams.Clear();
+ m_fragmentInputParams = null;
+ }
+
+ if( m_vertexDataDict != null )
+ {
+ m_vertexDataDict.Clear();
+ m_vertexDataDict = null;
+ }
+
+ if( m_interpolatorData != null )
+ {
+ m_interpolatorData.Destroy();
+ m_interpolatorData = null;
+ }
+
+ if( m_availableFragData != null )
+ {
+ m_availableFragData.Clear();
+ m_availableFragData = null;
+ }
+
+ if( m_availableVertData != null )
+ {
+ m_availableVertData.Clear();
+ m_availableVertData = null;
+ }
+
+ if( m_customInterpolatedData != null )
+ {
+ m_customInterpolatedData.Clear();
+ m_customInterpolatedData = null;
+ }
+
+ if( m_specialVertexLocalVars != null )
+ {
+ m_specialVertexLocalVars.Clear();
+ m_specialVertexLocalVars = null;
+ }
+
+ if( m_specialFragmentLocalVars != null )
+ {
+ m_specialFragmentLocalVars.Clear();
+ m_specialFragmentLocalVars = null;
+ }
+ }
+
+ public void BuildCBuffer( int nodeId )
+ {
+ m_fullSrpBatcherPropertiesList.Clear();
+ if( m_srpBatcherPropertiesList.Count > 0 )
+ {
+ var regex = new Regex( @"(\d)\s+\b" );
+ m_srpBatcherPropertiesList.Sort( ( a, b ) =>
+ {
+ var matchA = regex.Match( a.PropertyName );
+ int sizeA = 0;
+ if( matchA.Groups.Count > 1 && matchA.Groups[ 1 ].Value.Length > 0 )
+ sizeA = Convert.ToInt32( matchA.Groups[ 1 ].Value, System.Globalization.CultureInfo.InvariantCulture );
+
+ var matchB = regex.Match( b.PropertyName );
+ int sizeB = 0;
+ if( matchB.Groups.Count > 1 && matchB.Groups[ 1 ].Value.Length > 0 )
+ sizeB = Convert.ToInt32( matchB.Groups[ 1 ].Value, System.Globalization.CultureInfo.InvariantCulture );
+
+ return sizeB.CompareTo( sizeA );
+ } );
+
+ m_fullSrpBatcherPropertiesList.Insert(0, new PropertyDataCollector( nodeId, IOUtils.SRPCBufferPropertiesBegin ));
+ m_fullSrpBatcherPropertiesList.AddRange( m_srpBatcherPropertiesList );
+ m_fullSrpBatcherPropertiesList.Add( new PropertyDataCollector( nodeId, IOUtils.SRPCBufferPropertiesEnd ) );
+ }
+ }
+
+
+ public void DumpSRPBatcher()
+ {
+ for( int i = 0; i < m_srpBatcherPropertiesList.Count; i++ )
+ {
+ Debug.Log( i + "::" + m_srpBatcherPropertiesList[ i ].PropertyName );
+ }
+ }
+
+ public const string GlobalMaxInterpolatorReachedMsg = "Maximum amount of interpolators reached!\nPlease consider optmizing your shader!";
+ public const string MaxInterpolatorSMReachedMsg = "Maximum amount of interpolators reached for current shader model on pass {0}! Please consider increasing the shader model to {1}!";
+ public void CheckInterpolatorOverflow( string currShaderModel, string passName )
+ {
+ int maxInterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ currShaderModel ];
+ int currInterpolatorAmount = 1 + TemplateHelperFunctions.SemanticToInt[ InterpData.AvailableInterpolators[ InterpData.AvailableInterpolators.Count - 1 ].Semantic ];
+ if( currInterpolatorAmount > maxInterpolatorAmount )
+ {
+ string shaderModel = string.Empty;
+ if( TemplateHelperFunctions.GetShaderModelForInterpolatorAmount( currInterpolatorAmount, ref shaderModel ) )
+ {
+ UIUtils.ShowMessage( string.Format( MaxInterpolatorSMReachedMsg, passName, shaderModel ), MessageSeverity.Error );
+ }
+ else
+ {
+ UIUtils.ShowMessage( GlobalMaxInterpolatorReachedMsg, MessageSeverity.Error );
+ }
+ }
+ }
+
+ public Dictionary<TemplateSemantics, TemplateInputParameters> FragInputParameters { get { return m_fragmentInputParams; } }
+
+ public bool HasVertexInputParams
+ {
+ get
+ {
+ if( m_vertexInputParams != null )
+ return m_vertexInputParams.Count > 0;
+
+ return false;
+ }
+ }
+
+ public Dictionary<TemplateSemantics, TemplateInputParameters> VertexInputParameters { get { return m_vertexInputParams; } }
+ public TemplateData CurrentTemplateData { get { return m_currentTemplateData; } }
+ public int MultipassSubshaderIdx { get { return m_multipassSubshaderIdx; } }
+ public int MultipassPassIdx { get { return m_multipassPassIdx; } }
+ public TemplateSRPType CurrentSRPType { get { return m_currentSRPType; } set { m_currentSRPType = value; } }
+ public bool IsHDRP { get { return m_currentSRPType == TemplateSRPType.HD; } }
+ public bool IsLWRP { get { return m_currentSRPType == TemplateSRPType.Lightweight; } }
+ public bool IsSRP { get { return ( m_currentSRPType == TemplateSRPType.Lightweight || m_currentSRPType == TemplateSRPType.HD ); } }
+ public TemplateInterpData InterpData { get { return m_interpolatorData; } }
+ public List<PropertyDataCollector> LateDirectivesList { get { return m_lateDirectivesList; } }
+ public List<PropertyDataCollector> SrpBatcherPropertiesList { get { return m_srpBatcherPropertiesList; } }
+ public List<PropertyDataCollector> FullSrpBatcherPropertiesList { get { return m_fullSrpBatcherPropertiesList; } }
+ public Dictionary<TemplateSemantics, TemplateVertexData> VertexDataDict { get { return m_vertexDataDict; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta
new file mode 100644
index 00000000..9386f5fa
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataCollector.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c757602c408f7354b96c2a5eb21662a4
+timeCreated: 1495710491
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs
new file mode 100644
index 00000000..b7c3fd02
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs
@@ -0,0 +1,217 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ public enum TemplateDataType
+ {
+ LegacySinglePass,
+ MultiPass
+ }
+
+ [Serializable]
+ public class TemplateIncludePragmaContainter
+ {
+ [SerializeField]
+ private int m_nativeTopIndex = -1;
+
+ [SerializeField]
+ private List<string> m_nativeDirectivesList = new List<string>();
+
+ [SerializeField]
+ private List<string> m_includesList = new List<string>();
+ private Dictionary<string,string> m_includesDict = new Dictionary<string,string>();
+
+ [SerializeField]
+ private List<string> m_pragmasList = new List<string>();
+ private Dictionary<string, string> m_pragmasDict = new Dictionary<string, string>();
+
+ [SerializeField]
+ private List<string> m_definesList = new List<string>();
+ private Dictionary<string, string> m_definesDict = new Dictionary<string, string>();
+
+ public void RefreshIncludesList()
+ {
+ if ( m_includesDict.Count != m_includesList.Count )
+ {
+ m_includesDict.Clear();
+ int count = m_includesList.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ m_includesDict.Add( m_includesList[ i ], m_includesList[ i ] );
+ }
+ }
+ }
+
+ public void RefreshPragmasList()
+ {
+ if ( m_pragmasDict.Count != m_pragmasList.Count )
+ {
+ m_pragmasDict.Clear();
+ int count = m_pragmasList.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ m_pragmasDict.Add( m_pragmasList[ i ], m_pragmasList[ i ] );
+ }
+ }
+ }
+
+
+ public void RefreshDefinesList()
+ {
+ if ( m_definesDict.Count != m_definesList.Count )
+ {
+ m_definesDict.Clear();
+ int count = m_definesList.Count;
+ for ( int i = 0; i < count; i++ )
+ {
+ m_definesDict.Add( m_definesList[ i ], m_definesList[ i ] );
+ }
+ }
+ }
+
+ public bool HasInclude( string include )
+ {
+ RefreshIncludesList();
+ return m_includesDict.ContainsKey( include );
+ }
+
+ public bool HasPragma( string pragma )
+ {
+ RefreshPragmasList();
+ return m_pragmasDict.ContainsKey( pragma );
+ }
+
+ public bool HasDefine( string pragma )
+ {
+ RefreshDefinesList();
+ return m_definesDict.ContainsKey( pragma );
+ }
+
+ public void AddInclude( string include )
+ {
+ RefreshIncludesList();
+ if ( !m_includesDict.ContainsKey( include ) )
+ {
+ m_includesList.Add( include );
+ m_includesDict.Add( include, include );
+ }
+ }
+
+ public void AddPragma( string pragma )
+ {
+ RefreshPragmasList();
+ if ( !m_pragmasDict.ContainsKey( pragma ) )
+ {
+ m_pragmasList.Add( pragma );
+ m_pragmasDict.Add( pragma, pragma );
+ }
+ }
+
+ public void AddDefine( string define )
+ {
+ RefreshDefinesList();
+ if ( !m_definesDict.ContainsKey( define ) )
+ {
+ m_definesList.Add( define );
+ m_definesDict.Add( define, define );
+ }
+ }
+
+ public void AddNativeDirective( string native, int topIndex )
+ {
+ m_nativeTopIndex = topIndex;
+ m_nativeDirectivesList.Add( native );
+ }
+
+ public void Destroy()
+ {
+ m_nativeDirectivesList.Clear();
+ m_nativeDirectivesList = null;
+
+
+ m_includesList.Clear();
+ m_includesDict.Clear();
+ m_includesList = null;
+ m_includesDict = null;
+
+ m_pragmasList.Clear();
+ m_pragmasDict.Clear();
+ m_pragmasList = null;
+ m_pragmasDict = null;
+
+ m_definesList.Clear();
+ m_definesDict.Clear();
+ m_definesList = null;
+ m_definesDict = null;
+ }
+
+ public List<string> IncludesList { get { return m_includesList; } }
+ public List<string> PragmasList { get { return m_pragmasList; } }
+ public List<string> DefinesList { get { return m_definesList; } }
+ public List<string> NativeDirectivesList { get { return m_nativeDirectivesList; } }
+ public int NativeTopIndex { get { return m_nativeTopIndex; } }
+
+ }
+
+ [Serializable]
+ public class TemplateInfoContainer
+ {
+ public string Id = string.Empty;
+ public string Data = string.Empty;
+ public int Index = -1;
+ public bool IsValid { get { return Index > -1; } }
+ public void Reset()
+ {
+ Id = string.Empty;
+ Data = string.Empty;
+ Index = -1;
+ }
+ }
+
+ [Serializable]
+ public class TemplateDataParent : ScriptableObject
+ {
+ [SerializeField]
+ protected TemplateDataType m_templateType;
+
+ [SerializeField]
+ protected string m_name;
+
+ [SerializeField]
+ protected string m_guid;
+
+ [SerializeField]
+ protected int m_orderId;
+
+ [SerializeField]
+ protected string m_defaultShaderName = string.Empty;
+
+ [SerializeField]
+ protected bool m_isValid = true;
+
+ [SerializeField]
+ protected bool m_communityTemplate = false;
+
+ public virtual void Destroy() { }
+ public virtual bool Reload() { return true; }
+ public string Name
+ {
+ get { return m_name; }
+ set
+ {
+ m_name = value.StartsWith( "Hidden/" ) ? value.Replace( "Hidden/", string.Empty ) : value;
+ }
+ }
+ public string GUID { get { return m_guid; } set { m_guid = value; } }
+ public int OrderId { get { return m_orderId; } set { m_orderId = value; } }
+ public string DefaultShaderName { get { return m_defaultShaderName; } set { m_defaultShaderName = value; } }
+ public bool IsValid { get { return m_isValid; } }
+ public TemplateDataType TemplateType { get { return m_templateType; } }
+ public virtual void Init( string name, string guid, bool isCommunity ) { m_communityTemplate = isCommunity; }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta
new file mode 100644
index 00000000..49aee2ac
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDataParent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4e8f3788c7c239042b3cc3d086311227
+timeCreated: 1518720013
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs
new file mode 100644
index 00000000..0ce4a1c1
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs
@@ -0,0 +1,391 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public sealed class TemplateDepthModule : TemplateModuleParent
+ {
+ private const string ZWriteFormatter = "ZWrite {0}\n";
+ private const string ZTestFormatter = "ZTest {0}\n";
+
+ [SerializeField]
+ private bool m_validZTest = false;
+
+ [SerializeField]
+ private InlineProperty m_zTestMode = new InlineProperty( 0 );
+
+ [SerializeField]
+ private bool m_validZWrite = false;
+
+ [SerializeField]
+ private InlineProperty m_zWriteMode = new InlineProperty( 0 );
+
+ [SerializeField]
+ private InlineProperty m_offsetFactor = new InlineProperty( 0 );
+
+ [SerializeField]
+ private InlineProperty m_offsetUnits = new InlineProperty( 0 );
+
+ [SerializeField]
+ private bool m_offsetEnabled = false;
+
+ [SerializeField]
+ private bool m_validOffset = false;
+
+ public TemplateDepthModule() : base( "Depth" ) { }
+
+ public void CopyFrom( TemplateDepthModule other, bool allData )
+ {
+ if( allData )
+ {
+ m_independentModule = other.IndependentModule;
+ m_validZTest = other.ValidZTest;
+ m_validZWrite = other.ValidZWrite;
+ m_validOffset = other.ValidOffset;
+ }
+
+ m_zTestMode.CopyFrom( other.ZTestMode );
+ m_zWriteMode.CopyFrom( other.ZWriteMode );
+ m_offsetFactor.CopyFrom( other.OffsetFactor );
+ m_offsetUnits.CopyFrom( other.OffsetUnits );
+ m_offsetEnabled = other.OffsetEnabled;
+ }
+
+ public void ConfigureFromTemplateData( TemplateDepthData depthData )
+ {
+ m_independentModule = depthData.IndependentModule;
+ if( depthData.ValidZTest && m_validZTest != depthData.ValidZTest )
+ {
+ if( string.IsNullOrEmpty( depthData.ZTestInlineValue ) )
+ {
+ m_zTestMode.IntValue = ZBufferOpHelper.ZTestModeDict[ depthData.ZTestModeValue ];
+ m_zTestMode.ResetProperty();
+ }
+ else
+ {
+ m_zTestMode.SetInlineByName( depthData.ZTestInlineValue );
+ }
+ }
+
+
+
+ if( depthData.ValidZWrite && m_validZWrite != depthData.ValidZWrite )
+ {
+ if( string.IsNullOrEmpty( depthData.ZWriteInlineValue ) )
+ {
+ m_zWriteMode.IntValue = ZBufferOpHelper.ZWriteModeDict[ depthData.ZWriteModeValue ];
+ m_zWriteMode.ResetProperty();
+ }
+ else
+ {
+ m_zWriteMode.SetInlineByName( depthData.ZWriteInlineValue );
+ }
+ }
+
+ if( depthData.ValidOffset && m_validOffset != depthData.ValidOffset )
+ {
+ if( string.IsNullOrEmpty( depthData.OffsetFactorInlineValue ) )
+ {
+ m_offsetFactor.FloatValue = depthData.OffsetFactor;
+ m_offsetFactor.ResetProperty();
+ }
+ else
+ {
+ m_offsetFactor.SetInlineByName( depthData.OffsetFactorInlineValue );
+ }
+
+ if( string.IsNullOrEmpty( depthData.OffsetUnitsInlineValue ) )
+ {
+ m_offsetUnits.FloatValue = depthData.OffsetUnits;
+ m_offsetUnits.ResetProperty();
+ }
+ else
+ {
+ m_offsetUnits.SetInlineByName( depthData.OffsetUnitsInlineValue );
+ }
+ m_offsetEnabled = depthData.ValidOffset;
+ }
+
+ m_validZTest = depthData.ValidZTest;
+ m_validZWrite = depthData.ValidZWrite;
+ m_validOffset = depthData.ValidOffset;
+ m_validData = m_validZTest || m_validZWrite || m_validOffset;
+ }
+
+ public override void ShowUnreadableDataMessage( ParentNode owner )
+ {
+ bool foldoutValue = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth;
+ NodeUtils.DrawPropertyGroup( ref foldoutValue, ZBufferOpHelper.DepthParametersStr, base.ShowUnreadableDataMessage );
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth = foldoutValue;
+ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth;
+ if( style )
+ {
+ NodeUtils.DrawPropertyGroup( ref foldout, ZBufferOpHelper.DepthParametersStr, () =>
+ {
+ EditorGUI.indentLevel++;
+ DrawBlock( owner );
+ EditorGUI.indentLevel--;
+ } );
+ }
+ else
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref foldout, ZBufferOpHelper.DepthParametersStr, () =>
+ {
+ DrawBlock( owner );
+ } );
+ }
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedDepth = foldout;
+ }
+
+ void DrawBlock( UndoParentNode owner )
+ {
+ EditorGUI.BeginChangeCheck();
+ Color cachedColor = GUI.color;
+ GUI.color = new Color( cachedColor.r, cachedColor.g, cachedColor.b, ( EditorGUIUtility.isProSkin ? 0.5f : 0.25f ) );
+ //EditorGUILayout.BeginVertical( UIUtils.MenuItemBackgroundStyle );
+ GUI.color = cachedColor;
+
+ EditorGUILayout.Separator();
+
+ if( m_validZWrite )
+ m_zWriteMode.EnumTypePopup( ref owner, ZBufferOpHelper.ZWriteModeStr, ZBufferOpHelper.ZWriteModeValues );
+
+ if( m_validZTest )
+ m_zTestMode.EnumTypePopup( ref owner, ZBufferOpHelper.ZTestModeStr, ZBufferOpHelper.ZTestModeLabels );
+
+
+ if( m_validOffset )
+ {
+ m_offsetEnabled = owner.EditorGUILayoutToggle( ZBufferOpHelper.OffsetStr, m_offsetEnabled );
+ if( m_offsetEnabled )
+ {
+ EditorGUI.indentLevel++;
+ m_offsetFactor.FloatField( ref owner, ZBufferOpHelper.OffsetFactorStr );
+ m_offsetUnits.FloatField( ref owner, ZBufferOpHelper.OffsetUnitsStr );
+ EditorGUI.indentLevel--;
+ }
+ }
+ EditorGUILayout.Separator();
+
+ //EditorGUILayout.EndVertical();
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ }
+
+ public void ReadZWriteFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validZWrite;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_zWriteMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_zWriteMode.ReadFromString( ref index, ref nodeParams );
+ }
+ }
+ }
+
+ public void ReadZTestFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validZTest;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_zTestMode.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_zTestMode.ReadFromString( ref index, ref nodeParams );
+ }
+ }
+ }
+
+ public void ReadOffsetFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validOffset;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ m_offsetEnabled = Convert.ToBoolean( nodeParams[ index++ ] );
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_offsetFactor.FloatValue = Convert.ToSingle( nodeParams[ index++ ] );
+ m_offsetUnits.FloatValue = Convert.ToSingle( nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_offsetFactor.ReadFromString( ref index, ref nodeParams, false );
+ m_offsetUnits.ReadFromString( ref index, ref nodeParams, false );
+ }
+ }
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ ReadZWriteFromString( ref index, ref nodeParams );
+ ReadZTestFromString( ref index, ref nodeParams );
+ ReadOffsetFromString( ref index, ref nodeParams );
+ }
+
+ public void WriteZWriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validZWrite );
+ if( m_validZWrite )
+ m_zWriteMode.WriteToString( ref nodeInfo );
+ }
+
+ public void WriteZTestToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validZTest );
+ if( m_validZTest )
+ m_zTestMode.WriteToString( ref nodeInfo );
+ }
+
+ public void WriteOffsetToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validOffset );
+ if( m_validOffset )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_offsetEnabled );
+ m_offsetFactor.WriteToString( ref nodeInfo );
+ m_offsetUnits.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ WriteZWriteToString( ref nodeInfo );
+ WriteZTestToString( ref nodeInfo );
+ WriteOffsetToString( ref nodeInfo );
+ }
+
+ public bool IsActive { get { return ( m_zTestMode.IsValid || m_zTestMode.IntValue != 0 ) || ( m_zWriteMode.IsValid || m_zWriteMode.IntValue != 0 ) || m_offsetEnabled; } }
+ public string CurrentZWriteMode
+ {
+ get
+ {
+ if( m_zWriteMode.IsValid )
+ {
+ return string.Format( ZWriteFormatter, m_zWriteMode.GetValueOrProperty() ); ;
+ }
+
+ int finalZWrite = ( m_zWriteMode.IntValue == 0 ) ? 1 : m_zWriteMode.IntValue;
+ return string.Format( ZWriteFormatter, ZBufferOpHelper.ZWriteModeValues[ finalZWrite ] ); ;
+ }
+ }
+ public string CurrentZTestMode
+ {
+ get
+ {
+ if( m_zTestMode.IsValid )
+ return string.Format( ZTestFormatter, m_zTestMode.GetValueOrProperty() );
+
+ int finalZTestMode = ( m_zTestMode.IntValue == 0 ) ? 3 : m_zTestMode.IntValue;
+ return string.Format( ZTestFormatter, ZBufferOpHelper.ZTestModeValues[ finalZTestMode ] );
+ }
+ }
+
+ public string CurrentOffset
+ {
+ get
+ {
+ if( m_offsetEnabled )
+ return "Offset " + m_offsetFactor.GetValueOrProperty() + " , " + m_offsetUnits.GetValueOrProperty() + "\n";
+ else
+ return "Offset 0,0\n";
+ }
+ }
+
+ public bool ValidZTest { get { return m_validZTest; } }
+ public bool ValidZWrite { get { return m_validZWrite; } }
+ public bool ValidOffset { get { return m_validOffset; } }
+ public InlineProperty ZTestMode { get { return m_zTestMode; } }
+ public InlineProperty ZWriteMode { get { return m_zWriteMode; } }
+ public InlineProperty OffsetFactor { get { return m_offsetFactor; } }
+ public InlineProperty OffsetUnits { get { return m_offsetUnits; } }
+ public bool OffsetEnabled { get { return m_offsetEnabled; } }
+
+
+ public ZTestMode ZTestModeValue
+ {
+ set
+ {
+ m_zTestMode.IntValue = ZBufferOpHelper.ZTestModeDict[ value ];
+ m_zTestMode.Active = false;
+ }
+ get
+ {
+ return (ZTestMode)( m_zTestMode.IntValue - 1 );
+ }
+ }
+ public ZWriteMode ZWriteModeValue
+ {
+ set
+ {
+ m_zWriteMode.IntValue = ZBufferOpHelper.ZWriteModeDict[ value ];
+ m_zWriteMode.Active = false;
+ }
+ get
+ {
+ return (ZWriteMode)( m_zWriteMode.IntValue - 1 );
+ }
+ }
+ public float OffsetFactorValue
+ {
+ set
+ {
+ m_offsetEnabled = true;
+ m_offsetFactor.FloatValue = value;
+ m_offsetFactor.Active = false;
+ }
+ get
+ {
+ return m_offsetFactor.FloatValue;
+ }
+ }
+
+ public float OffsetUnitsValue
+ {
+ set
+ {
+ m_offsetEnabled = true;
+ m_offsetUnits.FloatValue = value;
+ m_offsetUnits.Active = false;
+ }
+ get
+ {
+ return m_offsetUnits.FloatValue;
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta
new file mode 100644
index 00000000..a559fe74
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateDepthModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 91bbf209a618780459e775d6816a4b06
+timeCreated: 1513873547
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs
new file mode 100644
index 00000000..68d5f9f3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs
@@ -0,0 +1,274 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ [NodeAttributes( "Template Fragment Data", "Surface Data", "Select and use available interpolated fragment data from the template" )]
+ public class TemplateFragmentDataNode : TemplateNodeParent
+ {
+ private List<TemplateVertexData> m_interpolatorData = null;
+
+ [SerializeField]
+ private int m_currentDataIdx = -1;
+
+ [SerializeField]
+ private string m_dataName = string.Empty;
+ [SerializeField]
+ private string m_inVarName = string.Empty;
+
+ private string[] m_dataLabels = null;
+
+ private bool m_fetchDataId = false;
+ private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper();
+
+ void FetchDataId()
+ {
+ if( m_interpolatorData != null )
+ {
+ m_currentDataIdx = 0;
+ int count = m_interpolatorData.Count;
+ m_dataLabels = new string[ count ];
+ for( int i = 0; i < count; i++ )
+ {
+ m_dataLabels[ i ] = m_interpolatorData[ i ].VarName;
+ if( m_interpolatorData[ i ].VarName.Equals( m_dataName ) )
+ {
+ m_currentDataIdx = i;
+ }
+ }
+ UpdateFromId();
+ }
+ else
+ {
+ m_currentDataIdx = -1;
+ }
+ }
+
+ void UpdateFromId()
+ {
+ if( m_interpolatorData != null )
+ {
+ if( m_interpolatorData.Count == 0 )
+ {
+ for( int i = 0; i < 4; i++ )
+ m_containerGraph.DeleteConnection( false, UniqueId, i, false, true );
+
+ m_headerColor = UIUtils.GetColorFromCategory( "Default" );
+ m_content.text = "None";
+ m_additionalContent.text = string.Empty;
+ m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false );
+ ConfigurePorts();
+ return;
+ }
+
+ bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_interpolatorData[ m_currentDataIdx ].DataType );
+ switch( m_interpolatorData[ m_currentDataIdx ].DataType )
+ {
+ default:
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT2:
+ m_outputPorts[ 0 ].ChangeProperties( "XY", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT3:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT4:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.COLOR:
+ m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ }
+
+ ConfigurePorts();
+
+ if( !areCompatible )
+ {
+ m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true );
+ }
+
+ m_dataName = m_interpolatorData[ m_currentDataIdx ].VarName;
+ m_content.text = m_dataName;
+ m_sizeIsDirty = true;
+ CheckWarningState();
+ }
+ }
+
+
+ public override void DrawProperties()
+ {
+ base.DrawProperties();
+ if( m_multiPassMode )
+ {
+ DrawMultipassProperties();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+
+ protected override void OnSubShaderChange()
+ {
+ base.OnSubShaderChange();
+ FetchInterpolator();
+ FetchDataId();
+ }
+
+ protected override void OnPassChange()
+ {
+ FetchInterpolator();
+ FetchDataId();
+ }
+
+ void DrawMultipassProperties()
+ {
+ DrawSubShaderUI();
+ DrawPassUI();
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ base.Draw( drawInfo );
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ return;
+
+ if( m_interpolatorData == null || m_interpolatorData.Count == 0 )
+ {
+ MasterNode masterNode = m_containerGraph.CurrentMasterNode;
+ FetchInterpolator( masterNode );
+ }
+
+ if( m_fetchDataId )
+ {
+ m_fetchDataId = false;
+ FetchDataId();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template )
+ {
+ UIUtils.ShowMessage( UniqueId, "Template Fragmment Data node is only intended for templates use only" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( !dataCollector.IsFragmentCategory )
+ {
+ UIUtils.ShowMessage( UniqueId, "Template Fragment Data node node is only intended for fragment use use only" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( m_multiPassMode )
+ {
+ if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx ||
+ dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx
+ )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+ }
+
+ return GetOutputVectorItem( 0, outputId, m_inVarName + m_dataName );
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ m_dataName = GetCurrentParam( ref nodeParams );
+ m_fetchDataId = true;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName );
+ }
+
+ public override void OnMasterNodeReplaced( MasterNode newMasterNode )
+ {
+ base.OnMasterNodeReplaced( newMasterNode );
+ if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ FetchInterpolator( newMasterNode );
+ }
+ else
+ {
+ m_interpolatorData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+
+ protected override bool ValidatePass( int passIdx )
+ {
+ return ( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].FragmentFunctionData != null &&
+ m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].InterpolatorDataContainer != null );
+ }
+
+ void FetchInterpolator( MasterNode masterNode = null )
+ {
+ FetchMultiPassTemplate( masterNode );
+ if( m_multiPassMode )
+ {
+ if( m_templateMPData != null )
+ {
+ m_inVarName = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].FragmentFunctionData.InVarName + ".";
+ m_interpolatorData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].InterpolatorDataContainer.RawInterpolators;
+ m_fetchDataId = true;
+ }
+ }
+ else
+ {
+ if( masterNode == null )
+ masterNode = m_containerGraph.CurrentMasterNode;
+
+ TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate;
+ if( currentTemplate != null )
+ {
+ m_inVarName = currentTemplate.FragmentFunctionData.InVarName + ".";
+ m_interpolatorData = currentTemplate.InterpolatorData.RawInterpolators;
+ FetchDataId();
+ }
+ else
+ {
+ m_interpolatorData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_dataLabels = null;
+ m_interpolatorData = null;
+ m_upperLeftWidgetHelper = null;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta
new file mode 100644
index 00000000..8e3e69fc
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateFragmentDataNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2b53cc116abb0df45b028f41b8f0305e
+timeCreated: 1506595629
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs
new file mode 100644
index 00000000..d5fc6583
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs
@@ -0,0 +1,2374 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Text.RegularExpressions;
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ public enum CustomTemplatePropertyUIEnum
+ {
+ None,
+ HDPBR
+ }
+
+ public enum TemplateSemantics
+ {
+ NONE,
+ POSITION,
+ SV_POSITION,
+ COLOR,
+ COLOR0,
+ COLOR1,
+ TEXCOORD0,
+ TEXCOORD1,
+ TEXCOORD2,
+ TEXCOORD3,
+ TEXCOORD4,
+ TEXCOORD5,
+ TEXCOORD6,
+ TEXCOORD7,
+ TEXCOORD8,
+ TEXCOORD9,
+ TEXCOORD10,
+ TEXCOORD11,
+ TEXCOORD12,
+ TEXCOORD13,
+ TEXCOORD14,
+ TEXCOORD15,
+ NORMAL,
+ TANGENT,
+ VFACE,
+ SV_VertexID,
+ SV_PrimitiveID,
+ SV_InstanceID,
+ INTERNALTESSPOS
+ }
+
+ public enum TemplateInfoOnSematics
+ {
+ NONE,
+ POSITION,
+ CLIP_POS,
+ SCREEN_POSITION,
+ SCREEN_POSITION_NORMALIZED,
+ COLOR,
+ TEXTURE_COORDINATES0,
+ TEXTURE_COORDINATES1,
+ TEXTURE_COORDINATES2,
+ TEXTURE_COORDINATES3,
+ TEXTURE_COORDINATES4,
+ TEXTURE_COORDINATES5,
+ TEXTURE_COORDINATES6,
+ TEXTURE_COORDINATES7,
+ NORMAL,
+ TANGENT,
+ WORLD_NORMAL,
+ WORLD_TANGENT,
+ WORLD_BITANGENT,
+ WORLD_VIEW_DIR,
+ WORLD_POSITION,
+ RELATIVE_WORLD_POS,
+ INSTANCE_ID,
+ OTHER,
+ VFACE,
+ SHADOWCOORDS,
+ VERTEXID
+ }
+
+ public enum TemplateShaderPropertiesIdx
+ {
+ Identation = 1,
+ Name = 3,
+ InspectorName,
+ Type
+ }
+
+ public enum TemplateShaderGlobalsIdx
+ {
+ Type = 1,
+ Name = 2
+ }
+ public enum TemplateDataCheck
+ {
+ Valid,
+ Invalid
+ }
+
+ public enum InvisibleOptionsEnum
+ {
+ SyncProperties = 1 << 0
+ }
+
+ public enum TemplateSpecialTags
+ {
+ RenderType,
+ Queue,
+ None
+ }
+
+ public class TemplateReplaceHelper
+ {
+ public TemplateMultiPassMasterNode MasterNode = null;
+ public bool Used = false;
+ public TemplateReplaceHelper( TemplateMultiPassMasterNode masterNode ) { MasterNode = masterNode; }
+ }
+
+ [Serializable]
+ public class TemplatesTagData
+ {
+ public string Name;
+ public string Value;
+ public TemplatesTagData( string name, string value )
+ {
+ Name = name;
+ Value = value;
+ }
+ }
+
+ [Serializable]
+ public class TemplateModuleData
+ {
+ public bool IndependentModule = true;
+ public TemplateDataCheck DataCheck = TemplateDataCheck.Invalid;
+ public string InlineData = string.Empty;
+ public int StartIdx;
+ public bool IsValid { get { return DataCheck == TemplateDataCheck.Valid; } }
+ public virtual void SetAllModulesDefault() { IndependentModule = false; DataCheck = TemplateDataCheck.Valid; }
+ }
+
+ [Serializable]
+ public sealed class TemplateTagsModuleData : TemplateModuleData
+ {
+ public string TagsId;
+ public List<TemplatesTagData> Tags = new List<TemplatesTagData>();
+ public void Destroy()
+ {
+ Tags.Clear();
+ Tags = null;
+ }
+
+ public void Reset()
+ {
+ Tags.Clear();
+ }
+
+ public void Dump()
+ {
+ string dump = string.Empty;
+ for( int i = 0; i < Tags.Count; i++ )
+ {
+ dump += string.Format( "[{0}] Name: {1} Value: {2}\n", i, Tags[ i ].Name, Tags[ i ].Value );
+ }
+ Debug.Log( dump );
+ }
+ }
+
+ [Serializable]
+ public class TemplateShaderModelData : TemplateModuleData
+ {
+ public string Id = string.Empty;
+ public string Value = "2.5";
+ public int InterpolatorAmount = 8;
+ public bool Encapsulate = false;
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+ Id = string.Empty;
+ Value = "3.0";
+ InterpolatorAmount = 10;
+ Encapsulate = true;
+ }
+ }
+
+ [Serializable]
+ public sealed class TemplateDepthData : TemplateModuleData
+ {
+ public bool ValidZWrite;
+ public string ZWriteModeId;
+ public ZWriteMode ZWriteModeValue;
+ public int ZWriteStartIndex;
+ public string ZWriteInlineValue;
+
+
+ public bool ValidZTest;
+ public string ZTestModeId;
+ public ZTestMode ZTestModeValue;
+ public int ZTestStartIndex;
+ public string ZTestInlineValue;
+
+ public bool ValidOffset;
+ public string OffsetId;
+ public float OffsetFactor;
+ public float OffsetUnits;
+ public int OffsetStartIndex;
+ public string OffsetFactorInlineValue;
+ public string OffsetUnitsInlineValue;
+
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+ ValidZWrite = true;
+ ZWriteModeId = string.Empty;
+ ZWriteModeValue = ZWriteMode.On;
+ ZWriteStartIndex = -1;
+ ZWriteInlineValue = string.Empty;
+
+
+ ValidZTest = true;
+ ZTestModeId = string.Empty;
+ ZTestModeValue = ZTestMode.LEqual;
+ ZTestStartIndex = -1;
+ ZTestInlineValue = string.Empty;
+
+ ValidOffset = true;
+ OffsetId = string.Empty;
+ OffsetFactor = 0;
+ OffsetUnits = 0;
+ OffsetStartIndex = -1;
+ OffsetFactorInlineValue = string.Empty;
+ OffsetUnitsInlineValue = string.Empty;
+ }
+
+ public void SetDataCheck()
+ {
+ DataCheck = ( ValidZWrite || ValidZTest || ValidOffset )?TemplateDataCheck.Valid:TemplateDataCheck.Invalid;
+ }
+ }
+
+ [Serializable]
+ public sealed class TemplateStencilData : TemplateModuleData
+ {
+ public string StencilBufferId;
+ public bool Active = true;
+
+ public int Reference;
+ public string ReferenceInline;
+
+ public int ReadMask = 255;
+ public string ReadMaskInline;
+
+ public int WriteMask = 255;
+ public string WriteMaskInline;
+
+ public string ComparisonFront;
+ public string ComparisonFrontInline;
+
+ public string PassFront;
+ public string PassFrontInline;
+
+ public string FailFront;
+ public string FailFrontInline;
+
+ public string ZFailFront;
+ public string ZFailFrontInline;
+
+ public string ComparisonBack;
+ public string ComparisonBackInline;
+
+ public string PassBack;
+ public string PassBackInline;
+
+ public string FailBack;
+ public string FailBackInline;
+
+ public string ZFailBack;
+ public string ZFailBackInline;
+
+ public void SetDefaultValues()
+ {
+ Active = false;
+
+ StencilBufferId = string.Empty;
+
+ Reference = 255;
+ ReferenceInline = string.Empty;
+
+ ReadMask = 255;
+ ReadMaskInline = string.Empty;
+
+ WriteMask = 255;
+ WriteMaskInline = string.Empty;
+
+ ComparisonFront = "always";
+ ComparisonFrontInline = string.Empty;
+
+ PassFront = "keep";
+ PassFrontInline = string.Empty;
+
+ FailFront = "keep";
+ FailFrontInline = string.Empty;
+
+ ZFailFront = "keep";
+ ZFailFrontInline = string.Empty;
+
+
+ ComparisonBack = "always";
+ ComparisonBackInline = string.Empty;
+
+ PassBack = "keep";
+ PassBackInline = string.Empty;
+
+ FailBack = "keep";
+ FailBackInline = string.Empty;
+
+ ZFailBack = "keep";
+ ZFailBackInline = string.Empty;
+ }
+
+ public void SetIndependentDefault()
+ {
+ IndependentModule = true;
+ DataCheck = TemplateDataCheck.Valid;
+ SetDefaultValues();
+ }
+
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+ SetDefaultValues();
+ }
+ }
+
+ [Serializable]
+ public sealed class TemplateBlendData : TemplateModuleData
+ {
+ public bool ValidBlendMode = false;
+ public bool BlendModeOff = true;
+
+ public string BlendModeId;
+ public bool SeparateBlendFactors = false;
+ public AvailableBlendFactor SourceFactorRGB = AvailableBlendFactor.One;
+ public string SourceFactorRGBInline;
+ public AvailableBlendFactor DestFactorRGB = AvailableBlendFactor.Zero;
+ public string DestFactorRGBInline;
+ public int BlendModeStartIndex;
+
+ public AvailableBlendFactor SourceFactorAlpha = AvailableBlendFactor.One;
+ public string SourceFactorAlphaInline;
+ public AvailableBlendFactor DestFactorAlpha = AvailableBlendFactor.Zero;
+ public string DestFactorAlphaInline;
+
+ public bool ValidBlendOp = false;
+ public string BlendOpId;
+ public bool SeparateBlendOps = false;
+ public AvailableBlendOps BlendOpRGB = AvailableBlendOps.OFF;
+ public string BlendOpRGBInline;
+ public AvailableBlendOps BlendOpAlpha = AvailableBlendOps.OFF;
+ public string BlendOpAlphaInline;
+ public int BlendOpStartIndex;
+
+ public bool IndependentAlphaToMask = false;
+ public bool ValidAlphaToMask = false;
+ public bool AlphaToMaskValue = false;
+ public string AlphaToMaskId;
+
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+
+ if( !ValidAlphaToMask )
+ {
+ ValidAlphaToMask = true;
+ AlphaToMaskValue = false;
+ AlphaToMaskId = string.Empty;
+ }
+
+ if( !ValidBlendMode )
+ {
+ ValidBlendMode = true;
+ BlendModeOff = true;
+ BlendModeId = string.Empty;
+ SeparateBlendFactors = false;
+ SourceFactorRGB = AvailableBlendFactor.One;
+ SourceFactorRGBInline = string.Empty;
+ DestFactorRGB = AvailableBlendFactor.Zero;
+ DestFactorRGBInline = string.Empty;
+ BlendModeStartIndex = -1;
+ SourceFactorAlpha = AvailableBlendFactor.One;
+ SourceFactorAlphaInline = string.Empty;
+ DestFactorAlpha = AvailableBlendFactor.Zero;
+ DestFactorAlphaInline = string.Empty;
+ }
+
+ if( !ValidBlendOp )
+ {
+ ValidBlendOp = true;
+ BlendOpId = string.Empty;
+ SeparateBlendOps = false;
+ BlendOpRGB = AvailableBlendOps.OFF;
+ BlendOpRGBInline = string.Empty;
+ BlendOpAlpha = AvailableBlendOps.OFF;
+ BlendOpAlphaInline = string.Empty;
+ BlendOpStartIndex = -1;
+ }
+
+ DataCheck = TemplateDataCheck.Valid;
+ }
+
+ }
+
+ [Serializable]
+ public sealed class TemplateCullModeData : TemplateModuleData
+ {
+ public string CullModeId;
+ public CullMode CullModeData = CullMode.Back;
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+ CullModeId = string.Empty;
+ CullModeData = CullMode.Back;
+ }
+ }
+
+ [Serializable]
+ public sealed class TemplateColorMaskData : TemplateModuleData
+ {
+ public string ColorMaskId;
+ public bool[] ColorMaskData = { true, true, true, true };
+ public override void SetAllModulesDefault()
+ {
+ base.SetAllModulesDefault();
+ ColorMaskId = string.Empty;
+ for( int i = 0; i < ColorMaskData.Length; i++ )
+ {
+ ColorMaskData[ i ] = true;
+ }
+ }
+ }
+
+ public static class TemplateHelperFunctions
+ {
+ /*
+ struct DirectionalLightData
+ {
+ uint lightLayers;
+ float3 positionRWS;
+ float3 color;
+ int cookieIndex;
+ float volumetricDimmer;
+ float3 right;
+ float3 up;
+ float3 forward;
+ int tileCookie;
+ int shadowIndex;
+ int contactShadowIndex;
+ float4 shadowMaskSelector;
+ int nonLightmappedOnly;
+ float diffuseScale;
+ float specularScale;
+ };
+ */
+ public static string HDLightInfoFormat = "_DirectionalLightDatas[{0}].{1}";
+
+ public static string[] VectorSwizzle = { "x", "y", "z", "w" };
+ public static string[] ColorSwizzle = { "r", "g", "b", "a" };
+
+ public static readonly Dictionary<string, CustomTemplatePropertyUIEnum> CustomTemplatePropertyUI = new Dictionary<string, CustomTemplatePropertyUIEnum>
+ {
+ { "None", CustomTemplatePropertyUIEnum.None},
+ { "HDPBR", CustomTemplatePropertyUIEnum.HDPBR}
+ };
+
+ public static readonly Dictionary<string, InvisibleOptionsEnum> InvisibleOptions = new Dictionary<string, InvisibleOptionsEnum>()
+ {
+ { "SyncP", InvisibleOptionsEnum.SyncProperties }
+ };
+
+ public static readonly Dictionary<string, TemplateSpecialTags> StringToReservedTags = new Dictionary<string, TemplateSpecialTags>()
+ {
+ { TemplateSpecialTags.RenderType.ToString(), TemplateSpecialTags.RenderType},
+ { TemplateSpecialTags.Queue.ToString(), TemplateSpecialTags.Queue},
+ };
+
+ public static readonly Dictionary<string, RenderType> StringToRenderType = new Dictionary<string, RenderType>
+ {
+ {"Opaque",RenderType.Opaque},
+ {"Transparent",RenderType.Transparent},
+ {"TransparentCutout",RenderType.TransparentCutout},
+ {"Background",RenderType.Background},
+ {"Overlay",RenderType.Overlay},
+ {"TreeOpaque",RenderType.TreeOpaque},
+ {"TreeTransparentCutout",RenderType.TreeTransparentCutout},
+ {"TreeBillboard",RenderType.TreeBillboard},
+ {"Grass",RenderType.Grass},
+ {"GrassBillboard",RenderType.GrassBillboard}
+ };
+
+ public static readonly Dictionary<string, RenderQueue> StringToRenderQueue = new Dictionary<string, RenderQueue>
+ {
+ {"Background",RenderQueue.Background },
+ {"Geometry",RenderQueue.Geometry },
+ {"AlphaTest",RenderQueue.AlphaTest },
+ {"Transparent",RenderQueue.Transparent },
+ {"Overlay",RenderQueue.Overlay }
+ };
+
+ public static readonly Dictionary<string, WirePortDataType> PropertyToWireType = new Dictionary<string, WirePortDataType>
+ {
+ {"Float",WirePortDataType.FLOAT},
+ {"Range",WirePortDataType.FLOAT},
+ {"Int",WirePortDataType.INT},
+ {"Color",WirePortDataType.COLOR},
+ {"Vector",WirePortDataType.FLOAT4},
+ {"2D",WirePortDataType.SAMPLER2D},
+ {"3D",WirePortDataType.SAMPLER3D},
+ {"Cube",WirePortDataType.SAMPLERCUBE}
+ };
+
+ public static readonly Dictionary<WirePortDataType, int> DataTypeChannelUsage = new Dictionary<WirePortDataType, int>
+ {
+ {WirePortDataType.OBJECT,0 },
+ {WirePortDataType.FLOAT,1 },
+ {WirePortDataType.FLOAT2,2 },
+ {WirePortDataType.FLOAT3,3 },
+ {WirePortDataType.FLOAT4,4 },
+ {WirePortDataType.FLOAT3x3,0 },
+ {WirePortDataType.FLOAT4x4,0 },
+ {WirePortDataType.COLOR,4 },
+ {WirePortDataType.INT,1 },
+ {WirePortDataType.UINT,1 },
+ {WirePortDataType.SAMPLER1D,0 },
+ {WirePortDataType.SAMPLER2D,0 },
+ {WirePortDataType.SAMPLER3D,0 },
+ {WirePortDataType.SAMPLERCUBE,0 }
+ };
+
+ public static readonly Dictionary<int, WirePortDataType> ChannelToDataType = new Dictionary<int, WirePortDataType>
+ {
+ {1,WirePortDataType.FLOAT},
+ {2,WirePortDataType.FLOAT2},
+ {3,WirePortDataType.FLOAT3},
+ {4,WirePortDataType.FLOAT4}
+ };
+
+ public static readonly Dictionary<TemplateSemantics, string> SemanticsDefaultName = new Dictionary<TemplateSemantics, string>
+ {
+ {TemplateSemantics.COLOR ,"ase_color"},
+ {TemplateSemantics.NORMAL ,"ase_normal"},
+ {TemplateSemantics.POSITION ,"ase_position"},
+ {TemplateSemantics.SV_POSITION ,"ase_sv_position"},
+ {TemplateSemantics.TANGENT ,"ase_tangent"},
+ {TemplateSemantics.VFACE ,"ase_vface"},
+ {TemplateSemantics.SV_VertexID ,"ase_vertexId"},
+ {TemplateSemantics.SV_PrimitiveID ,"ase_primitiveId"},
+ {TemplateSemantics.INTERNALTESSPOS ,"ase_internalTessPos"},
+ {TemplateSemantics.TEXCOORD0 ,"ase_tex_coord0"},
+ {TemplateSemantics.TEXCOORD1 ,"ase_tex_coord1"},
+ {TemplateSemantics.TEXCOORD2 ,"ase_tex_coord2"},
+ {TemplateSemantics.TEXCOORD3 ,"ase_tex_coord3"},
+ {TemplateSemantics.TEXCOORD4 ,"ase_tex_coord4"},
+ {TemplateSemantics.TEXCOORD5 ,"ase_tex_coord5"},
+ {TemplateSemantics.TEXCOORD6 ,"ase_tex_coord6"},
+ {TemplateSemantics.TEXCOORD7 ,"ase_tex_coord7"},
+ {TemplateSemantics.TEXCOORD8 ,"ase_tex_coord8"},
+ {TemplateSemantics.TEXCOORD9 ,"ase_tex_coord9"},
+ {TemplateSemantics.TEXCOORD10 ,"ase_tex_coord10"},
+ {TemplateSemantics.TEXCOORD11 ,"ase_tex_coord11"},
+ {TemplateSemantics.TEXCOORD12 ,"ase_tex_coord12"},
+ {TemplateSemantics.TEXCOORD13 ,"ase_tex_coord13"},
+ {TemplateSemantics.TEXCOORD14 ,"ase_tex_coord14"},
+ {TemplateSemantics.TEXCOORD15 ,"ase_tex_coord15"},
+ };
+
+ public static readonly Dictionary<int, TemplateInfoOnSematics> IntToInfo = new Dictionary<int, TemplateInfoOnSematics>
+ {
+ {0,TemplateInfoOnSematics.TEXTURE_COORDINATES0 },
+ {1,TemplateInfoOnSematics.TEXTURE_COORDINATES1 },
+ {2,TemplateInfoOnSematics.TEXTURE_COORDINATES2 },
+ {3,TemplateInfoOnSematics.TEXTURE_COORDINATES3 },
+ {4,TemplateInfoOnSematics.TEXTURE_COORDINATES4 },
+ {5,TemplateInfoOnSematics.TEXTURE_COORDINATES5 },
+ {6,TemplateInfoOnSematics.TEXTURE_COORDINATES6 },
+ {7,TemplateInfoOnSematics.TEXTURE_COORDINATES7 },
+ };
+
+ public static readonly Dictionary<string, TemplateInfoOnSematics> ShortcutToInfo = new Dictionary<string, TemplateInfoOnSematics>
+ {
+ {"p" ,TemplateInfoOnSematics.POSITION },
+ {"sp" ,TemplateInfoOnSematics.CLIP_POS },
+ {"spu" ,TemplateInfoOnSematics.SCREEN_POSITION },
+ {"spn" ,TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED },
+ {"c" ,TemplateInfoOnSematics.COLOR },
+ {"uv0" ,TemplateInfoOnSematics.TEXTURE_COORDINATES0 },
+ {"uv1" ,TemplateInfoOnSematics.TEXTURE_COORDINATES1 },
+ {"uv2" ,TemplateInfoOnSematics.TEXTURE_COORDINATES2 },
+ {"uv3" ,TemplateInfoOnSematics.TEXTURE_COORDINATES3 },
+ {"uv4" ,TemplateInfoOnSematics.TEXTURE_COORDINATES4 },
+ {"uv5" ,TemplateInfoOnSematics.TEXTURE_COORDINATES5 },
+ {"uv6" ,TemplateInfoOnSematics.TEXTURE_COORDINATES6 },
+ {"uv7" ,TemplateInfoOnSematics.TEXTURE_COORDINATES7 },
+ {"n" ,TemplateInfoOnSematics.NORMAL },
+ {"t" ,TemplateInfoOnSematics.TANGENT },
+ {"wn" ,TemplateInfoOnSematics.WORLD_NORMAL},
+ {"wt" ,TemplateInfoOnSematics.WORLD_TANGENT},
+ {"wbt" ,TemplateInfoOnSematics.WORLD_BITANGENT},
+ {"wvd" ,TemplateInfoOnSematics.WORLD_VIEW_DIR},
+ {"wp" ,TemplateInfoOnSematics.WORLD_POSITION},
+ {"rwp" ,TemplateInfoOnSematics.RELATIVE_WORLD_POS},
+ {"vf" ,TemplateInfoOnSematics.VFACE},
+ {"sc" ,TemplateInfoOnSematics.SHADOWCOORDS}
+ };
+
+ public static readonly Dictionary<TemplateInfoOnSematics, string> InfoToDefineFrag = new Dictionary<TemplateInfoOnSematics, string>
+ {
+ {TemplateInfoOnSematics.POSITION ,"ASE_NEEDS_FRAG_POSITION"},
+ {TemplateInfoOnSematics.CLIP_POS ,"ASE_NEEDS_FRAG_CLIP_POS"},
+ {TemplateInfoOnSematics.SCREEN_POSITION,"ASE_NEEDS_FRAG_SCREEN_POSITION" },
+ {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,"ASE_NEEDS_FRAG_SCREEN_POSITION_NORMALIZED" },
+ {TemplateInfoOnSematics.COLOR, "ASE_NEEDS_FRAG_COLOR"},
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES0,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES0" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES1,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES1" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES2,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES2" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES3,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES3" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES4,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES4" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES5,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES5" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES6,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES6" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES7,"ASE_NEEDS_FRAG_TEXTURE_COORDINATES7" },
+ {TemplateInfoOnSematics.NORMAL,"ASE_NEEDS_FRAG_NORMAL" },
+ {TemplateInfoOnSematics.TANGENT ,"ASE_NEEDS_FRAG_TANGENT"},
+ {TemplateInfoOnSematics.WORLD_NORMAL,"ASE_NEEDS_FRAG_WORLD_NORMAL"},
+ {TemplateInfoOnSematics.WORLD_TANGENT,"ASE_NEEDS_FRAG_WORLD_TANGENT"},
+ {TemplateInfoOnSematics.WORLD_BITANGENT,"ASE_NEEDS_FRAG_WORLD_BITANGENT"},
+ {TemplateInfoOnSematics.WORLD_VIEW_DIR,"ASE_NEEDS_FRAG_WORLD_VIEW_DIR"},
+ {TemplateInfoOnSematics.WORLD_POSITION,"ASE_NEEDS_FRAG_WORLD_POSITION"},
+ {TemplateInfoOnSematics.RELATIVE_WORLD_POS,"ASE_NEEDS_FRAG_RELATIVE_WORLD_POS"},
+ {TemplateInfoOnSematics.VFACE,"ASE_NEEDS_FRAG_VFACE"},
+ {TemplateInfoOnSematics.SHADOWCOORDS,"ASE_NEEDS_FRAG_SHADOWCOORDS"}
+ };
+
+ public static readonly Dictionary<TemplateInfoOnSematics, string> InfoToDefineVertex = new Dictionary<TemplateInfoOnSematics, string>
+ {
+ {TemplateInfoOnSematics.POSITION ,"ASE_NEEDS_VERT_POSITION"},
+ {TemplateInfoOnSematics.CLIP_POS ,"ASE_NEEDS_VERT_CLIP_POS"},
+ {TemplateInfoOnSematics.SCREEN_POSITION,"ASE_NEEDS_VERT_SCREEN_POSITION" },
+ {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,"ASE_NEEDS_VERT_SCREEN_POSITION_NORMALIZED" },
+ {TemplateInfoOnSematics.COLOR, "ASE_NEEDS_VERT_COLOR"},
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES0,"ASE_NEEDS_VERT_TEXTURE_COORDINATES0" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES1,"ASE_NEEDS_VERT_TEXTURE_COORDINATES1" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES2,"ASE_NEEDS_VERT_TEXTURE_COORDINATES2" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES3,"ASE_NEEDS_VERT_TEXTURE_COORDINATES3" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES4,"ASE_NEEDS_VERT_TEXTURE_COORDINATES4" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES5,"ASE_NEEDS_VERT_TEXTURE_COORDINATES5" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES6,"ASE_NEEDS_VERT_TEXTURE_COORDINATES6" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES7,"ASE_NEEDS_VERT_TEXTURE_COORDINATES7" },
+ {TemplateInfoOnSematics.NORMAL,"ASE_NEEDS_VERT_NORMAL" },
+ {TemplateInfoOnSematics.TANGENT ,"ASE_NEEDS_VERT_TANGENT"},
+ {TemplateInfoOnSematics.WORLD_NORMAL,"ASE_NEEDS_VERT_WORLD_NORMAL"},
+ {TemplateInfoOnSematics.WORLD_TANGENT,"ASE_NEEDS_VERT_WORLD_TANGENT"},
+ {TemplateInfoOnSematics.WORLD_BITANGENT,"ASE_NEEDS_VERT_WORLD_BITANGENT"},
+ {TemplateInfoOnSematics.WORLD_VIEW_DIR,"ASE_NEEDS_VERT_WORLD_VIEW_DIR"},
+ {TemplateInfoOnSematics.WORLD_POSITION,"ASE_NEEDS_VERT_WORLD_POSITION"},
+ {TemplateInfoOnSematics.RELATIVE_WORLD_POS,"ASE_NEEDS_VERT_RELATIVE_WORLD_POS"},
+ {TemplateInfoOnSematics.VFACE,"ASE_NEEDS_VERT_VFACE"},
+ {TemplateInfoOnSematics.SHADOWCOORDS,"ASE_NEEDS_VERT_SHADOWCOORDS"}
+ };
+
+ public static readonly Dictionary<TemplateInfoOnSematics, string> InfoToLocalVar = new Dictionary<TemplateInfoOnSematics, string>
+ {
+ {TemplateInfoOnSematics.POSITION,GeneratorUtils.VertexPosition4Str },
+ {TemplateInfoOnSematics.CLIP_POS,GeneratorUtils.ClipPositionStr },
+ {TemplateInfoOnSematics.SCREEN_POSITION,GeneratorUtils.ScreenPositionStr },
+ {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,GeneratorUtils.ScreenPositionNormalizedStr },
+ {TemplateInfoOnSematics.COLOR, "ase_color" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES0, "ase_uv0" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES1, "ase_uv1" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES2, "ase_uv2" },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES3, "ase_uv3" },
+ {TemplateInfoOnSematics.NORMAL, GeneratorUtils.VertexNormalStr },
+ {TemplateInfoOnSematics.TANGENT, GeneratorUtils.VertexTangentStr },
+ {TemplateInfoOnSematics.WORLD_NORMAL, GeneratorUtils.WorldNormalStr},
+ {TemplateInfoOnSematics.WORLD_TANGENT, GeneratorUtils.WorldTangentStr},
+ {TemplateInfoOnSematics.WORLD_BITANGENT, GeneratorUtils.WorldBitangentStr},
+ {TemplateInfoOnSematics.WORLD_VIEW_DIR, GeneratorUtils.WorldViewDirectionStr},
+ {TemplateInfoOnSematics.WORLD_POSITION, GeneratorUtils.WorldPositionStr},
+ {TemplateInfoOnSematics.RELATIVE_WORLD_POS, GeneratorUtils.RelativeWorldPositionStr},
+ {TemplateInfoOnSematics.VFACE, GeneratorUtils.VFaceStr},
+ {TemplateInfoOnSematics.SHADOWCOORDS, GeneratorUtils.ShadowCoordsStr}
+ };
+
+
+ public static readonly Dictionary<TemplateInfoOnSematics, WirePortDataType> InfoToWirePortType = new Dictionary<TemplateInfoOnSematics, WirePortDataType>
+ {
+ {TemplateInfoOnSematics.POSITION,WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.CLIP_POS,WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.SCREEN_POSITION,WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.SCREEN_POSITION_NORMALIZED,WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.COLOR, WirePortDataType.COLOR },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES0, WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES1, WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES2, WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.TEXTURE_COORDINATES3, WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.NORMAL, WirePortDataType.FLOAT3 },
+ {TemplateInfoOnSematics.TANGENT, WirePortDataType.FLOAT4 },
+ {TemplateInfoOnSematics.WORLD_NORMAL, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.WORLD_TANGENT, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.WORLD_BITANGENT, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.WORLD_VIEW_DIR, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.WORLD_POSITION, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.RELATIVE_WORLD_POS, WirePortDataType.FLOAT3},
+ {TemplateInfoOnSematics.VFACE, WirePortDataType.FLOAT},
+ {TemplateInfoOnSematics.SHADOWCOORDS, WirePortDataType.FLOAT4},
+ };
+ public static readonly Dictionary<int, TemplateInfoOnSematics> IntToUVChannelInfo = new Dictionary<int, TemplateInfoOnSematics>
+ {
+ {0,TemplateInfoOnSematics.TEXTURE_COORDINATES0 },
+ {1,TemplateInfoOnSematics.TEXTURE_COORDINATES1 },
+ {2,TemplateInfoOnSematics.TEXTURE_COORDINATES2 },
+ {3,TemplateInfoOnSematics.TEXTURE_COORDINATES3 },
+ {4,TemplateInfoOnSematics.TEXTURE_COORDINATES4 },
+ {5,TemplateInfoOnSematics.TEXTURE_COORDINATES5 },
+ {6,TemplateInfoOnSematics.TEXTURE_COORDINATES6 },
+ {7,TemplateInfoOnSematics.TEXTURE_COORDINATES7 }
+ };
+
+ public static readonly Dictionary<int, TemplateSemantics> IntToSemantic = new Dictionary<int, TemplateSemantics>
+ {
+ { 0,TemplateSemantics.TEXCOORD0 },
+ { 1,TemplateSemantics.TEXCOORD1 },
+ { 2,TemplateSemantics.TEXCOORD2 },
+ { 3,TemplateSemantics.TEXCOORD3 },
+ { 4,TemplateSemantics.TEXCOORD4 },
+ { 5,TemplateSemantics.TEXCOORD5 },
+ { 6,TemplateSemantics.TEXCOORD6 },
+ { 7,TemplateSemantics.TEXCOORD7 },
+ { 8,TemplateSemantics.TEXCOORD8 },
+ { 9,TemplateSemantics.TEXCOORD9 },
+ { 10,TemplateSemantics.TEXCOORD10 },
+ { 11,TemplateSemantics.TEXCOORD11 },
+ { 12,TemplateSemantics.TEXCOORD12 },
+ { 13,TemplateSemantics.TEXCOORD13 },
+ { 14,TemplateSemantics.TEXCOORD14 },
+ { 15,TemplateSemantics.TEXCOORD15 }
+ };
+
+ public static readonly Dictionary<TemplateSemantics, int> SemanticToInt = new Dictionary<TemplateSemantics, int>
+ {
+ { TemplateSemantics.TEXCOORD0,0 },
+ { TemplateSemantics.TEXCOORD1,1 },
+ { TemplateSemantics.TEXCOORD2,2 },
+ { TemplateSemantics.TEXCOORD3,3 },
+ { TemplateSemantics.TEXCOORD4,4 },
+ { TemplateSemantics.TEXCOORD5,5 },
+ { TemplateSemantics.TEXCOORD6,6 },
+ { TemplateSemantics.TEXCOORD7,7 },
+ { TemplateSemantics.TEXCOORD8,8 },
+ { TemplateSemantics.TEXCOORD9,9 },
+ { TemplateSemantics.TEXCOORD10,10 },
+ { TemplateSemantics.TEXCOORD11,11 },
+ { TemplateSemantics.TEXCOORD12,12 },
+ { TemplateSemantics.TEXCOORD13,13 },
+ { TemplateSemantics.TEXCOORD14,14 },
+ { TemplateSemantics.TEXCOORD15,15 },
+ };
+
+ public static readonly Dictionary<string, TemplateSemantics> ShortcutToSemantic = new Dictionary<string, TemplateSemantics>
+ {
+ { "p" ,TemplateSemantics.POSITION },
+ { "sp" ,TemplateSemantics.SV_POSITION },
+ { "c" ,TemplateSemantics.COLOR },
+ { "n" ,TemplateSemantics.NORMAL },
+ { "t" ,TemplateSemantics.TANGENT },
+ { "tc0" ,TemplateSemantics.TEXCOORD0 },
+ { "tc1" ,TemplateSemantics.TEXCOORD1 },
+ { "tc2" ,TemplateSemantics.TEXCOORD2 },
+ { "tc3" ,TemplateSemantics.TEXCOORD3 },
+ { "tc4" ,TemplateSemantics.TEXCOORD4 },
+ { "tc5" ,TemplateSemantics.TEXCOORD5 },
+ { "tc6" ,TemplateSemantics.TEXCOORD6 },
+ { "tc7" ,TemplateSemantics.TEXCOORD7 },
+ { "tc8" ,TemplateSemantics.TEXCOORD8 },
+ { "tc9" ,TemplateSemantics.TEXCOORD9 },
+ { "tc10" ,TemplateSemantics.TEXCOORD10 },
+ { "tc11" ,TemplateSemantics.TEXCOORD11 },
+ { "tc12" ,TemplateSemantics.TEXCOORD12 },
+ { "tc13" ,TemplateSemantics.TEXCOORD13 },
+ { "tc14" ,TemplateSemantics.TEXCOORD14 },
+ { "tc15" ,TemplateSemantics.TEXCOORD15 }
+ };
+
+ public static readonly Dictionary<string, WirePortDataType> CgToWirePortType = new Dictionary<string, WirePortDataType>()
+ {
+ {"float" ,WirePortDataType.FLOAT},
+ {"float2" ,WirePortDataType.FLOAT2},
+ {"float3" ,WirePortDataType.FLOAT3},
+ {"float4" ,WirePortDataType.FLOAT4},
+ {"float3x3" ,WirePortDataType.FLOAT3x3},
+ {"float4x4" ,WirePortDataType.FLOAT4x4},
+ {"half" ,WirePortDataType.FLOAT},
+ {"half2" ,WirePortDataType.FLOAT2},
+ {"half3" ,WirePortDataType.FLOAT3},
+ {"half4" ,WirePortDataType.FLOAT4},
+ {"half3x3" ,WirePortDataType.FLOAT3x3},
+ {"half4x4" ,WirePortDataType.FLOAT4x4},
+ {"fixed" ,WirePortDataType.FLOAT},
+ {"fixed2" ,WirePortDataType.FLOAT2},
+ {"fixed3" ,WirePortDataType.FLOAT3},
+ {"fixed4" ,WirePortDataType.FLOAT4},
+ {"fixed3x3" ,WirePortDataType.FLOAT3x3},
+ {"fixed4x4" ,WirePortDataType.FLOAT4x4},
+ {"int" ,WirePortDataType.INT},
+ {"uint" ,WirePortDataType.INT},
+ {"sampler1D" ,WirePortDataType.SAMPLER1D},
+ {"sampler2D" ,WirePortDataType.SAMPLER2D},
+ {"sampler2D_float" ,WirePortDataType.SAMPLER2D},
+ {"sampler3D" ,WirePortDataType.SAMPLER3D},
+ {"samplerCUBE" ,WirePortDataType.SAMPLERCUBE}
+ };
+
+ public static readonly Dictionary<string, int> AvailableInterpolators = new Dictionary<string, int>()
+ {
+ {"2.0",8 },
+ {"2.5",8 },
+ {"3.0",10},
+ {"3.5",10},
+ {"4.0",16},
+ {"4.5",16},
+ {"4.6",16},
+ {"5.0",16}
+ };
+
+ public static readonly string[] AvailableShaderModels =
+ { "2.0", "2.5", "3.0", "3.5", "4.0", "4.5", "4.6", "5.0" };
+
+ public static readonly Dictionary<string, int> ShaderModelToArrayIdx = new Dictionary<string, int>()
+ {
+ {"2.0",0},
+ {"2.5",1},
+ {"3.0",2},
+ {"3.5",3},
+ {"4.0",4},
+ {"4.5",5},
+ {"4.6",6},
+ {"5.0",7}
+ };
+
+ public static readonly string HDPBRTag = "UNITY_MATERIAL_LIT";
+ public static readonly Dictionary<string, TemplateSRPType> TagToRenderPipeline = new Dictionary<string, TemplateSRPType>()
+ {
+ { "UniversalPipeline",TemplateSRPType.Lightweight },
+ { "LightweightPipeline",TemplateSRPType.Lightweight },
+ { "HDRenderPipeline",TemplateSRPType.HD }
+ };
+#if UNITY_2018_3_OR_NEWER
+ public static string CoreColorLib = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl";
+ public static string CoreCommonLib = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl";
+#else
+ public static string CoreCommonLib = "CoreRP/ShaderLibrary/Common.hlsl";
+ public static string CoreColorLib = "CoreRP/ShaderLibrary/Color.hlsl";
+#endif
+
+ public static string FetchSubShaderBody = @"(SubShader.*)\/\*ase_lod\*\/";
+ public static string TemplateCustomUI = @"\/\*CustomNodeUI:(\w*)\*\/";
+ public static string HidePassPattern = @"\/\*ase_hide_pass[:]*([a-zA-Z:]*)\*\/";
+ public static string ASEPassPattern = @"\/\*ase_pass[:]*([a-zA-Z:]*)\*\/";
+ public static string BlendWholeWordPattern = @"\bBlend\b";
+ public static string BlendOpWholeWordPattern = @"\bBlendOp\b";
+ public static string AlphaToMaskPattern = @"\bAlphaToMask (\w*)";
+ public static string CullWholeWordPattern = @"\bCull\b";
+ public static string ColorMaskWholeWordPattern = @"\bColorMask\b";
+ public static string StencilWholeWordPattern = @"\bStencil\b";
+ public static string ZWriteWholeWordPattern = @"\bZWrite\b";
+ public static string ZTestWholeWordPattern = @"\bZTest\b";
+ public static string ZOffsetWholeWordPattern = @"\bOffset\b";
+ public static string TagsWholeWordPattern = @"\bTags\b";
+
+
+ public static string CustomInspectorPattern = "^\\s*CustomEditor\\s+\\\"([\\w\\.]*)\\\"";
+ public static string FallbackPattern = "^\\s*Fallback\\s+\\\"([\\w\\/\\\\]*)\\\"";
+ public static string DefinesPattern = @"^\s*#define\s+([\w .]*)";
+ public static string PragmasPattern = @"^\s*#pragma\s+([\w .]*)";
+ public static string IncludesPattern = "^\\s*#include\\s+\"([\\w.\\/]*)\"";
+ public static string GlobalDirectivesPattern = "[#]+(define|pragma|include)\\s+([\\w .\\/\\\"]*)";
+ public static string BeforePragmaPattern = @"(?:CGPROGRAM|HLSLPROGRAM|GLSLPROGRAM).*?\n(\s*)(.)";
+ public static string GlobalTOPDirectivesPattern = @"(CGPROGRAM|CGINCLUDE|HLSLPROGRAM|HLSLINCLUDE).*?\n\s*(.)";
+
+ public static string VertexPragmaPattern = @"#pragma vertex\s+(\w+)";
+ public static string FragmentPragmaPattern = @"#pragma fragment\s+(\w+)";
+ public static string FunctionBodyStartPattern = @"\s+{0}\s*\(";
+
+ public static string ShaderModelPattern = @"#pragma\s+target\s+([0-9]*[.]*[0-9]*)";
+
+ public static readonly string LocalVarPattern = @"\/\*ase_local_var[:]*(\w*)\*\/\s*(\w*)\s+(\w*)";
+
+ public static readonly string InlinePattern = @"\/\*ase_inline_begin\*\/(.*?)\/\*ase_inline_end\*\/";
+
+ public static readonly string SubShaderLODPattern = @"\sLOD\s+(\d+)";
+
+ public static readonly string PassNamePattern = "Name\\s+\\\"([\\w\\+\\-\\*\\/\\(\\) ]*)\\\"";
+
+ public static readonly string TagsPattern = "\"(\\w+)\"\\s*=\\s*\"(\\w+\\+*\\w*)\"";
+ public static readonly string ZTestPattern = @"^\s*ZTest\s+(\[*\w+\]*)";
+ public static readonly string ZWritePattern = @"^\s*ZWrite\s+(\[*\w+\]*)";
+ //public static readonly string ZOffsetPattern = @"\s*Offset\s+([-+]?[0-9]*\.?[0-9]+)\s*,\s*([-+]?[0-9]*\.?[0-9]+)";
+ public static readonly string ZOffsetPattern = @"^\s*Offset\s+([-+]?[0-9]*\.?[0-9]+|\[*\w+\]*)\s*,\s*([-+]?[0-9]*\.?[0-9]+|\[*\w+\]*)\s*";
+ public static readonly string VertexDataPattern = @"(\w+)\s*(\w+)\s*:\s*([A-Z0-9_]+);";
+ public static readonly string InterpRangePattern = @"ase_interp\((\d\.{0,1}\w{0,4}),(\d*)\)";
+ //public static readonly string PropertiesPatternB = "(\\w*)\\s*\\(\\s*\"([\\w ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)";
+ //public static readonly string PropertiesPatternC = "^\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)";
+ //public static readonly string PropertiesPatternD = "(\\/\\/\\s*)*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)";
+ //public static readonly string PropertiesPatternE = "(\\/\\/\\s*)*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*";
+ //public static readonly string PropertiesPatternF = "^(\\/\\/)*\\s*(\\[[\\[\\]\\w\\s\\(\\)\\_\\,]*\\])*\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*";
+ //public static readonly string PropertiesPatternG = "^(\\s*)(\\[[\\[\\]\\w\\s\\(\\)\\_\\,]*\\])*\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}]*";
+ public static readonly string PropertiesPatternG = "^(\\s*)(\\[[\\[\\]\\w\\s\\(\\)_,\\.]*\\])*\\s*(\\w*)\\s*\\(\\s*\"([\\w\\(\\)\\+\\-\\\\* ]*)\"\\s*\\,\\s*(\\w*)\\s*.*\\)\\s*=\\s*[\\w,()\" {}\\.]*";
+ public static readonly string CullModePattern = @"^\s*Cull\s+(\[*\w+\]*)";
+ public static readonly string ColorMaskPattern = @"^\s*ColorMask\s+([\d\w\[\]]+)(\s*\d)*";
+ //public static readonly string BlendModePattern = @"\s*Blend\s+(\w+)\s+(\w+)(?:[\s,]+(\w+)\s+(\w+)|)";
+ //public static readonly string BlendModePattern = @"\s*Blend\s+(\[*\w+\]*)\s+(\[*\w+\]*)(?:[\s,]+(\[*\w+\]*)\s+(\[*\w+\]*)|)";
+ public static readonly string BlendModePattern = @"^\s*Blend\s+(?:(?=\d)|(\[*\w+\]*)\s+(\[*\w+\]*)(?:[\s,]+(\[*\w+\]*)\s+(\[*\w+\]*)|))";
+ //public static readonly string BlendOpPattern = @"\s*BlendOp\s+(\w+)[\s,]*(?:(\w+)|)";
+ //public static readonly string BlendOpPattern = @"\s*BlendOp\s+(\[*\w+\]*)[\s,]*(?:(\[*\w+\]*)|)";
+ public static readonly string BlendOpPattern = @"^\s*BlendOp\s+(?:(?=\d)|(\[*\w+\]*)[\s,]*(?:(\[*\w+\]*)|))";
+
+ public static readonly string StencilOpGlobalPattern = @"Stencil\s*{([\w\W\s]*)}";
+ public static readonly string StencilOpLinePattern = @"(\w+)\s*(\[*\w+\]*)";
+
+ public static readonly string ShaderGlobalsOverallPattern = "(?:\\/\\*ase_pragma\\*\\/|[\\}\\#])[\\w\\s\\;\\/\\*\\.\\\"]*\\/\\*ase_globals\\*\\/";
+ public static readonly string ShaderGlobalsMultilinePattern = @"^\s*(?:uniform\s*)*(\w*)\s*(\w*);$";
+
+ public static readonly string TexSemantic = "float4 {0} : TEXCOORD{1};";
+ public static readonly string TexFullSemantic = "float4 {0} : {1};";
+ public static readonly string InterpFullSemantic = "{0} {1} : {2};";
+ public static readonly string BaseInterpolatorName = "ase_texcoord";
+ public static readonly string TexUVFullSemantic = "float4 ase_texcoord{0} : TEXCOORD{0};";
+ public static readonly string InterpMacro = "{0}({1})";
+
+ public static readonly string InterpolatorDecl = Constants.VertexShaderOutputStr + ".{0} = " + Constants.VertexShaderInputStr + ".{0};";
+ public static readonly string TemplateVariableDecl = "{0} = {1};";
+ public static readonly string TemplateVarFormat = "{0}.{1}";
+
+ //public static readonly string StructsRemoval = @"struct\s+\w+\s+{[\s\w;\/\*]+};";
+ public static readonly string StructsRemoval = @"struct\s+\w+\s+{[\s\w\(\).;:=,\/\*]+};";
+
+ public static readonly string SRPBatcherFindTag = @"CBUFFER_START\s*\(\s*UnityPerMaterial\s*\)\s*\n(\s*)";
+
+ public static string ReplaceAt( this string body, string oldStr, string newStr, int startIndex )
+ {
+ return body.Remove( startIndex, oldStr.Length ).Insert( startIndex, newStr );
+ }
+
+ public static bool GetPassUniqueId( TemplateTagData tagData, TemplatePropertyContainer propertyContainer, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, string subBody, ref string passUniqueID )
+ {
+ Match match = Regex.Match( subBody, ASEPassPattern );
+ if( match.Success && match.Groups.Count > 1 && match.Groups[1].Length > 0 )
+ {
+ passUniqueID = match.Groups[ 1 ].Value;
+
+ tagData.StartIdx = offsetIdx + match.Index;
+ tagData.Id = match.Value;
+
+ idManager.RegisterId( tagData.StartIdx, uniquePrefix + tagData.Id, tagData.Id );
+ propertyContainer.AddId( subBody, tagData.Id, tagData.SearchIndentation );
+ return true;
+ }
+ return false;
+ }
+
+ public static CustomTemplatePropertyUIEnum FetchCustomUI( string data )
+ {
+ Match match = Regex.Match( data, TemplateCustomUI );
+ if( match.Success && CustomTemplatePropertyUI.ContainsKey( match.Groups[ 1 ].Value ) )
+ {
+ return CustomTemplatePropertyUI[ match.Groups[ 1 ].Value ];
+ }
+ return CustomTemplatePropertyUIEnum.None;
+ }
+
+ public static bool FetchInvisibleInfo( string input, ref int optionsArr, ref string id, ref int idIndex )
+ {
+ Match match = Regex.Match( input, HidePassPattern );
+ if( match.Success )
+ {
+ id = match.Value;
+ idIndex = match.Index;
+ if( match.Groups.Count > 1 )
+ {
+ string[] properties = match.Groups[ 1 ].Value.Split( ':' );
+ for( int i = 0; i < properties.Length; i++ )
+ {
+ if( InvisibleOptions.ContainsKey( properties[ i ] ) )
+ {
+ optionsArr |= (int)InvisibleOptions[ properties[ i ] ];
+ }
+ }
+ }
+ }
+ return match.Success;
+ }
+
+ static public string GenerateTextureSemantic( ref MasterNodeDataCollector dataCollector, int uv )
+ {
+ string texCoordName = BaseInterpolatorName;
+ if( uv > 0 )
+ {
+ texCoordName += uv.ToString();
+ }
+
+ string texCoordData = string.Format( TexSemantic, texCoordName, uv );
+ dataCollector.AddToVertexInput( texCoordData );
+ dataCollector.AddToInterpolators( texCoordData );
+ dataCollector.AddToVertexInterpolatorsDecl( string.Format( InterpolatorDecl, texCoordName ) );
+ return texCoordName;
+ }
+
+ public static void CreatePragmaIncludeList( string data, TemplateIncludePragmaContainter includePragmaContainer )
+ {
+ // this finds the topmost position for including directives
+ int topIndex = -1;
+ foreach( Match match in Regex.Matches( data, GlobalTOPDirectivesPattern, RegexOptions.Singleline ) )
+ {
+ if( match.Groups.Count == 3 )
+ {
+ topIndex = match.Groups[ 2 ].Index;
+ }
+ }
+
+ foreach( Match match in Regex.Matches( data, GlobalDirectivesPattern, RegexOptions.Multiline ) )
+ {
+ if( match.Success )
+ {
+ includePragmaContainer.AddNativeDirective( match.Groups[ 0 ].Value, topIndex );
+ }
+ }
+
+ foreach( Match match in Regex.Matches( data, PragmasPattern, RegexOptions.Multiline ) )
+ {
+ if( match.Groups.Count == 2 )
+ {
+ includePragmaContainer.AddPragma( match.Groups[ 1 ].Value );
+ }
+ }
+
+ foreach( Match match in Regex.Matches( data, DefinesPattern, RegexOptions.Multiline ) )
+ {
+ if( match.Groups.Count == 2 )
+ {
+ includePragmaContainer.AddDefine( match.Groups[ 1 ].Value );
+ }
+ }
+
+ foreach( Match match in Regex.Matches( data, IncludesPattern, RegexOptions.Multiline ) )
+ {
+ if( match.Groups.Count == 2 )
+ {
+ includePragmaContainer.AddInclude( match.Groups[ 1 ].Value );
+ }
+ }
+ }
+
+ public static void CreateShaderPropertiesList( string propertyData, ref List<TemplateShaderPropertyData> propertiesList, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ int identationIdx = (int)TemplateShaderPropertiesIdx.Identation;
+ int nameIdx = (int)TemplateShaderPropertiesIdx.Name;
+ int typeIdx = (int)TemplateShaderPropertiesIdx.Type;
+ int inspectorNameIdx = (int)TemplateShaderPropertiesIdx.InspectorName;
+
+ foreach( Match match in Regex.Matches( propertyData, PropertiesPatternG,RegexOptions.Multiline ) )
+ {
+ if( match.Groups.Count > 1 )
+ {
+ if( !duplicatesHelper.ContainsKey( match.Groups[ nameIdx ].Value ) && PropertyToWireType.ContainsKey( match.Groups[ typeIdx ].Value ) )
+ {
+ TemplateShaderPropertyData newData = new TemplateShaderPropertyData( match.Index,
+ match.Value,
+ match.Groups[ identationIdx ].Value,
+ match.Groups[ inspectorNameIdx ].Value,
+ match.Groups[ nameIdx ].Value,
+ PropertyToWireType[ match.Groups[ typeIdx ].Value ],
+ PropertyType.Property );
+ propertiesList.Add( newData );
+ duplicatesHelper.Add( newData.PropertyName, newData );
+ }
+ }
+ }
+ }
+
+ public static void CreateShaderGlobalsList( string propertyData, ref List<TemplateShaderPropertyData> propertiesList, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ int typeIdx = (int)TemplateShaderGlobalsIdx.Type;
+ int nameIdx = (int)TemplateShaderGlobalsIdx.Name;
+
+ // removes structs
+ propertyData = Regex.Replace( propertyData, StructsRemoval, "" );
+ MatchCollection matchCollection = Regex.Matches( propertyData, ShaderGlobalsOverallPattern );
+ string value = ( matchCollection.Count > 0 ) ? matchCollection[ 0 ].Groups[ 0 ].Value : propertyData;
+ foreach( Match lineMatch in Regex.Matches( value, ShaderGlobalsMultilinePattern, RegexOptions.Multiline ) )
+ {
+ if( lineMatch.Groups.Count > 1 )
+ {
+ if( !duplicatesHelper.ContainsKey( lineMatch.Groups[ nameIdx ].Value ) && CgToWirePortType.ContainsKey( lineMatch.Groups[ typeIdx ].Value ) )
+ {
+ TemplateShaderPropertyData newData = new TemplateShaderPropertyData( -1,
+ string.Empty,
+ string.Empty,
+ string.Empty,
+ lineMatch.Groups[ nameIdx ].Value,
+ CgToWirePortType[ lineMatch.Groups[ typeIdx ].Value ],
+ PropertyType.Global );
+ duplicatesHelper.Add( newData.PropertyName, newData );
+ propertiesList.Add( newData );
+ }
+ }
+ }
+ }
+
+ public static void CreateStencilOps( string stencilData, ref TemplateStencilData stencilDataObj )
+ {
+ stencilDataObj.DataCheck = TemplateDataCheck.Invalid;
+ MatchCollection overallGlobalMatch = Regex.Matches( stencilData, StencilOpGlobalPattern );
+ if( overallGlobalMatch.Count == 1 && overallGlobalMatch[ 0 ].Groups.Count == 2 )
+ {
+ string property = string.Empty;
+ string value = overallGlobalMatch[ 0 ].Groups[ 1 ].Value;
+ foreach( Match match in Regex.Matches( value, StencilOpLinePattern ) )
+ {
+ stencilDataObj.DataCheck = TemplateDataCheck.Valid;
+ if( match.Groups.Count == 3 )
+ {
+ switch( match.Groups[ 1 ].Value )
+ {
+ default:
+ {
+ stencilDataObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ case "Ref":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ReferenceInline = property;
+ }
+ else
+ {
+ try
+ {
+ stencilDataObj.Reference = Convert.ToInt32( match.Groups[ 2 ].Value );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ stencilDataObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ }
+ }
+ break;
+ case "ReadMask":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ReadMaskInline = property;
+ }
+ else
+ {
+ try
+ {
+ stencilDataObj.ReadMask = Convert.ToInt32( match.Groups[ 2 ].Value );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ stencilDataObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ }
+ }
+ break;
+ case "WriteMask":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.WriteMaskInline = property;
+ }
+ else
+ {
+ try
+ {
+ stencilDataObj.WriteMask = Convert.ToInt32( match.Groups[ 2 ].Value );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ stencilDataObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ }
+ }
+ break;
+ case "CompFront":
+ case "Comp":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ComparisonFrontInline = property;
+ }
+ else
+ {
+ stencilDataObj.ComparisonFront = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "PassFront":
+ case "Pass":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.PassFrontInline = property;
+ }
+ else
+ {
+ stencilDataObj.PassFront = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "FailFront":
+ case "Fail":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.FailFrontInline = property;
+ }
+ else
+ {
+ stencilDataObj.FailFront = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "ZFail":
+ case "ZFailFront":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ZFailFrontInline = property;
+ }
+ else
+ {
+ stencilDataObj.ZFailFront = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "CompBack":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ComparisonBackInline = property;
+ }
+ else
+ {
+ stencilDataObj.ComparisonBack = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "PassBack":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.PassBackInline = property;
+ }
+ else
+ {
+ stencilDataObj.PassBack = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "FailBack":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.FailBackInline = property;
+ }
+ else
+ {
+ stencilDataObj.FailBack = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ case "ZFailBack":
+ {
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ stencilDataObj.ZFailBackInline = property;
+ }
+ else
+ {
+ stencilDataObj.ZFailBack = match.Groups[ 2 ].Value;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public static void CreateColorMask( string colorMaskData, ref TemplateColorMaskData colorMaskObj )
+ {
+ colorMaskObj.DataCheck = TemplateDataCheck.Invalid;
+ Match match = Regex.Match( colorMaskData, ColorMaskPattern );
+ if( match.Groups.Count == 3 && !match.Groups[ 2 ].Success ) // second group is the colormask MRT which isn't implemented yet
+ {
+ string property = string.Empty;
+ if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ colorMaskObj.InlineData = property;
+ colorMaskObj.DataCheck = TemplateDataCheck.Valid;
+ }
+ else
+ {
+ for( int i = 0; i < 4; i++ )
+ {
+ colorMaskObj.ColorMaskData[ i ] = false;
+ }
+
+ colorMaskObj.DataCheck = TemplateDataCheck.Valid;
+ try
+ {
+ for( int i = 0; i < match.Groups[ 1 ].Value.Length; i++ )
+ {
+ switch( Char.ToLower( match.Groups[ 1 ].Value[ i ] ) )
+ {
+ case 'r': colorMaskObj.ColorMaskData[ 0 ] = true; break;
+ case 'g': colorMaskObj.ColorMaskData[ 1 ] = true; break;
+ case 'b': colorMaskObj.ColorMaskData[ 2 ] = true; break;
+ case 'a': colorMaskObj.ColorMaskData[ 3 ] = true; break;
+ case '0':
+ {
+ for( int j = 0; j < 4; j++ )
+ {
+ colorMaskObj.ColorMaskData[ j ] = false;
+ }
+ return;
+ }
+ default:
+ {
+ colorMaskObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ colorMaskObj.DataCheck = TemplateDataCheck.Invalid;
+ return;
+ }
+ }
+ }
+ }
+
+ public static void CreateCullMode( string cullModeData, ref TemplateCullModeData cullDataObj )
+ {
+ cullDataObj.DataCheck = TemplateDataCheck.Invalid;
+ Match match = Regex.Match( cullModeData, CullModePattern );
+ if( match.Groups.Count == 2 )
+ {
+ string property = string.Empty;
+ if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ cullDataObj.InlineData = property;
+ cullDataObj.DataCheck = TemplateDataCheck.Valid;
+ }
+ else
+ {
+ try
+ {
+ cullDataObj.CullModeData = (CullMode)Enum.Parse( typeof( CullMode ), match.Groups[ 1 ].Value );
+ cullDataObj.DataCheck = TemplateDataCheck.Valid;
+ }
+ catch( Exception e )
+ {
+ cullDataObj.DataCheck = TemplateDataCheck.Invalid;
+ Debug.LogException( e );
+ return;
+ }
+ }
+ }
+ }
+
+ public static void CreateBlendMode( string blendModeData, ref TemplateBlendData blendDataObj )
+ {
+ blendDataObj.ValidBlendMode = true;
+ string property = string.Empty;
+ bool noMatches = true;
+ // TODO: OPTIMIZE REGEX EXPRESSIONS TO NOT CATCH EMPTY GROUPS
+ foreach( Match match in Regex.Matches( blendModeData, BlendModePattern ) )
+ {
+
+ if( match.Groups.Count == 3 )
+ {
+ if( match.Groups[ 0 ].Success &&
+ match.Groups[ 1 ].Success )
+ {
+
+ try
+ {
+ if( IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ blendDataObj.SourceFactorRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor sourceAll = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 1 ].Value );
+ blendDataObj.SourceFactorRGB = sourceAll;
+ }
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ blendDataObj.DestFactorRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor destAll = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 2 ].Value );
+ blendDataObj.DestFactorRGB = destAll;
+ }
+
+ blendDataObj.SeparateBlendFactors = false;
+ blendDataObj.BlendModeOff = false;
+ noMatches = false;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ blendDataObj.DataCheck = TemplateDataCheck.Invalid;
+ blendDataObj.ValidBlendMode = false;
+ return;
+ }
+ break;
+ }
+ }
+ else if( match.Groups.Count == 5 )
+ {
+ if( match.Groups[ 0 ].Success &&
+ match.Groups[ 1 ].Success )
+ {
+ try
+ {
+ if( IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ blendDataObj.SourceFactorRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor sourceRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 1 ].Value );
+ blendDataObj.SourceFactorRGB = sourceRGB;
+ }
+
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ blendDataObj.DestFactorRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor destRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 2 ].Value );
+ blendDataObj.DestFactorRGB = destRGB;
+ }
+
+ if( match.Groups[ 3 ].Success && match.Groups[ 4 ].Success )
+ {
+ if( IsInlineProperty( match.Groups[ 3 ].Value, ref property ) )
+ {
+ blendDataObj.SourceFactorAlphaInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor sourceA = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 3 ].Value );
+ blendDataObj.SourceFactorAlpha = sourceA;
+ }
+
+ if( IsInlineProperty( match.Groups[ 4 ].Value, ref property ) )
+ {
+ blendDataObj.DestFactorAlphaInline = property;
+ }
+ else
+ {
+ AvailableBlendFactor destA = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), match.Groups[ 4 ].Value );
+ blendDataObj.DestFactorAlpha = destA;
+ }
+
+ blendDataObj.SeparateBlendFactors = true;
+ }
+ else
+ {
+ blendDataObj.SeparateBlendFactors = false;
+ }
+ blendDataObj.BlendModeOff = false;
+ noMatches = false;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ blendDataObj.DataCheck = TemplateDataCheck.Invalid;
+ blendDataObj.ValidBlendMode = false;
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ if( noMatches )
+ blendDataObj.ValidBlendMode = false;
+ }
+
+ public static void CreateBlendOp( string blendOpData, ref TemplateBlendData blendDataObj )
+ {
+ bool noMatches = true;
+ blendDataObj.ValidBlendOp = true;
+ string property = string.Empty;
+ // TODO: OPTIMIZE REGEX EXPRESSIONS TO NOT CATCH EMPTY GROUPS
+ foreach( Match match in Regex.Matches( blendOpData, BlendOpPattern, RegexOptions.None ) )
+ {
+ if( match.Groups.Count == 2 )
+ {
+ if( match.Groups[ 0 ].Success &&
+ match.Groups[ 1 ].Success )
+ {
+
+ try
+ {
+ if( IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ blendDataObj.BlendOpRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendOps blendOpsAll = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 1 ].Value );
+ blendDataObj.BlendOpRGB = blendOpsAll;
+ }
+ blendDataObj.SeparateBlendOps = false;
+ noMatches = false;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ blendDataObj.DataCheck = TemplateDataCheck.Invalid;
+ blendDataObj.ValidBlendOp = false;
+ return;
+ }
+ break;
+ }
+ }
+ else if( match.Groups.Count == 3 )
+ {
+ if( match.Groups[ 0 ].Success &&
+ match.Groups[ 1 ].Success )
+ {
+ try
+ {
+ if( IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ blendDataObj.BlendOpRGBInline = property;
+ }
+ else
+ {
+ AvailableBlendOps blendOpsRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 1 ].Value );
+ blendDataObj.BlendOpRGB = blendOpsRGB;
+ }
+
+ if( match.Groups[ 2 ].Success )
+ {
+ if( IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ blendDataObj.BlendOpAlphaInline = property;
+ }
+ else
+ {
+ AvailableBlendOps blendOpsA = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), match.Groups[ 2 ].Value );
+ blendDataObj.BlendOpAlpha = blendOpsA;
+ }
+ blendDataObj.SeparateBlendOps = true;
+ }
+ else
+ {
+ blendDataObj.SeparateBlendOps = false;
+ }
+ noMatches = false;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ blendDataObj.DataCheck = TemplateDataCheck.Invalid;
+ blendDataObj.ValidBlendOp = false;
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ if( noMatches )
+ blendDataObj.ValidBlendOp = false;
+ }
+
+ public static void FetchLocalVars( string body, ref List<TemplateLocalVarData> localVarList, TemplateFunctionData vertexFunction, TemplateFunctionData fragFunction )
+ {
+ foreach( Match match in Regex.Matches( body, LocalVarPattern ) )
+ {
+ if( match.Groups.Count == 4 )
+ {
+ if( CgToWirePortType.ContainsKey( match.Groups[ 2 ].Value ) )
+ {
+ MasterNodePortCategory category;
+ if( fragFunction.MainBodyLocalIdx > vertexFunction.MainBodyLocalIdx )
+ {
+ if( match.Index < fragFunction.MainBodyLocalIdx )
+ {
+ category = MasterNodePortCategory.Vertex;
+ }
+ else
+ {
+ category = MasterNodePortCategory.Fragment;
+ }
+ }
+ else
+ {
+ if( match.Index < vertexFunction.MainBodyLocalIdx )
+ {
+ category = MasterNodePortCategory.Fragment;
+ }
+ else
+ {
+ category = MasterNodePortCategory.Vertex;
+ }
+ }
+
+ if( !string.IsNullOrEmpty( match.Groups[ 1 ].Value ) && ShortcutToInfo.ContainsKey( match.Groups[ 1 ].Value ) )
+ {
+ string id = match.Groups[ 0 ].Value.Substring( 0, match.Groups[ 0 ].Value.IndexOf( "*/" ) + 2 );
+ TemplateLocalVarData data = new TemplateLocalVarData( ShortcutToInfo[ match.Groups[ 1 ].Value ], id, CgToWirePortType[ match.Groups[ 2 ].Value ], category, match.Groups[ 3 ].Value, match.Index );
+ localVarList.Add( data );
+ }
+ else
+ {
+ TemplateLocalVarData data = new TemplateLocalVarData( CgToWirePortType[ match.Groups[ 2 ].Value ], category, match.Groups[ 3 ].Value, match.Index );
+ localVarList.Add( data );
+ }
+
+ }
+ }
+ }
+ }
+
+ public static void FetchInlineVars( string body, ref TemplateIdManager idManager )
+ {
+ foreach( Match match in Regex.Matches( body, InlinePattern ) )
+ {
+ if( match.Success && match.Groups.Count == 2 )
+ {
+ string id = match.Groups[ 0 ].Value;
+ string prop = match.Groups[ 1 ].Value;
+ idManager.RegisterTag( id, prop );
+ }
+ }
+ }
+
+ public static TemplateSRPType CreateTags( ref TemplateTagsModuleData tagsObj, bool isSubShader )
+ {
+ TemplateSRPType srpType = TemplateSRPType.BuiltIn;
+ MatchCollection matchColl = Regex.Matches( tagsObj.TagsId, TagsPattern, RegexOptions.IgnorePatternWhitespace );
+ int count = matchColl.Count;
+ if( count > 0 )
+ {
+ for( int i = 0; i < count; i++ )
+ {
+ if( matchColl[ i ].Groups.Count == 3 )
+ {
+ if( isSubShader && matchColl[ i ].Groups[ 1 ].Value.Equals( "RenderPipeline" ) )
+ {
+ if( TagToRenderPipeline.ContainsKey( matchColl[ i ].Groups[ 2 ].Value ) )
+ srpType = TagToRenderPipeline[ matchColl[ i ].Groups[ 2 ].Value ];
+ }
+ tagsObj.Tags.Add( new TemplatesTagData( matchColl[ i ].Groups[ 1 ].Value, matchColl[ i ].Groups[ 2 ].Value ) );
+ }
+ }
+ }
+ return srpType;
+ }
+
+ public static void CreateZWriteMode( string zWriteData, ref TemplateDepthData depthDataObj )
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ Match match = Regex.Match( zWriteData, ZWritePattern );
+ if( match.Groups.Count == 2 )
+ {
+ string property = string.Empty;
+ if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ depthDataObj.ZWriteInlineValue = property;
+ depthDataObj.DataCheck = TemplateDataCheck.Valid;
+ depthDataObj.ValidZWrite = true;
+ }
+ else
+ {
+ try
+ {
+ depthDataObj.ZWriteModeValue = (ZWriteMode)Enum.Parse( typeof( ZWriteMode ), match.Groups[ 1 ].Value );
+ depthDataObj.DataCheck = TemplateDataCheck.Valid;
+ depthDataObj.ValidZWrite = true;
+ }
+ catch
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+ }
+
+ public static void CreateZTestMode( string zTestData, ref TemplateDepthData depthDataObj )
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ Match match = Regex.Match( zTestData, ZTestPattern );
+ if( match.Groups.Count == 2 )
+ {
+ string property = string.Empty;
+ if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ depthDataObj.ZTestInlineValue = property;
+ depthDataObj.DataCheck = TemplateDataCheck.Valid;
+ depthDataObj.ValidZTest = true;
+ }
+ else
+ {
+ try
+ {
+ depthDataObj.ZTestModeValue = (ZTestMode)Enum.Parse( typeof( ZTestMode ), match.Groups[ 1 ].Value );
+ depthDataObj.DataCheck = TemplateDataCheck.Valid;
+ depthDataObj.ValidZTest = true;
+ }
+ catch
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+ }
+
+ public static void CreateZOffsetMode( string zOffsetData, ref TemplateDepthData depthDataObj )
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ Match match = Regex.Match( zOffsetData, ZOffsetPattern );
+ if( match.Groups.Count == 3 )
+ {
+ try
+ {
+ string property = string.Empty;
+
+ if( match.Groups[ 1 ].Success && IsInlineProperty( match.Groups[ 1 ].Value, ref property ) )
+ {
+ depthDataObj.OffsetFactorInlineValue = property;
+ }
+ else
+ {
+ depthDataObj.OffsetFactor = Convert.ToSingle( match.Groups[ 1 ].Value );
+ }
+
+ if( match.Groups[ 2 ].Success && IsInlineProperty( match.Groups[ 2 ].Value, ref property ) )
+ {
+ depthDataObj.OffsetUnitsInlineValue = property;
+ }
+ else
+ {
+ depthDataObj.OffsetUnits = Convert.ToSingle( match.Groups[ 2 ].Value );
+ }
+
+ depthDataObj.ValidOffset = true;
+ depthDataObj.DataCheck = TemplateDataCheck.Valid;
+ }
+ catch
+ {
+ depthDataObj.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+
+ public static List<TemplateVertexData> CreateVertexDataList( string vertexData, string parametersBody )
+ {
+ List<TemplateVertexData> vertexDataList = null;
+ Dictionary<TemplateSemantics, TemplateVertexData> vertexDataDict = null;
+
+ foreach( Match match in Regex.Matches( vertexData, VertexDataPattern ) )
+ {
+ if( match.Groups.Count > 1 )
+ {
+ if( vertexDataList == null )
+ {
+ vertexDataList = new List<TemplateVertexData>();
+ vertexDataDict = new Dictionary<TemplateSemantics, TemplateVertexData>();
+ }
+
+ WirePortDataType dataType = CgToWirePortType[ match.Groups[ 1 ].Value ];
+ string varName = match.Groups[ 2 ].Value;
+ TemplateSemantics semantics = (TemplateSemantics)Enum.Parse( typeof( TemplateSemantics ), match.Groups[ 3 ].Value );
+ TemplateVertexData templateVertexData = new TemplateVertexData( semantics, dataType, varName );
+ vertexDataList.Add( templateVertexData );
+ vertexDataDict.Add( semantics, templateVertexData );
+ }
+ }
+
+ if( vertexData.Contains( Constants.InstanceIdMacro ) )
+ {
+ TemplateVertexData templateVertexData = new TemplateVertexData( TemplateSemantics.SV_InstanceID, WirePortDataType.UINT, Constants.InstanceIdVariable );
+ templateVertexData.DataInfo = TemplateInfoOnSematics.INSTANCE_ID;
+ templateVertexData.Available = true;
+ templateVertexData.ExcludeStructPrefix = true;
+
+ vertexDataList.Add( templateVertexData );
+ vertexDataDict.Add( TemplateSemantics.SV_InstanceID, templateVertexData );
+ }
+
+ if( !string.IsNullOrEmpty( parametersBody ) )
+ {
+ string[] paramsArray = parametersBody.Split( IOUtils.FIELD_SEPARATOR );
+ if( paramsArray.Length > 0 )
+ {
+ for( int i = 0; i < paramsArray.Length; i++ )
+ {
+ string[] paramDataArr = paramsArray[ i ].Split( IOUtils.VALUE_SEPARATOR );
+ if( paramDataArr.Length == 2 )
+ {
+ string[] swizzleInfoArr = paramDataArr[ 1 ].Split( IOUtils.FLOAT_SEPARATOR );
+ TemplateSemantics semantic = ShortcutToSemantic[ swizzleInfoArr[ 0 ] ];
+ if( vertexDataDict.ContainsKey( semantic ) )
+ {
+ TemplateVertexData templateVertexData = vertexDataDict[ semantic ];
+ if( templateVertexData != null )
+ {
+ if( swizzleInfoArr.Length > 1 )
+ {
+ templateVertexData.DataSwizzle = "." + swizzleInfoArr[ 1 ];
+ }
+ templateVertexData.DataInfo = ShortcutToInfo[ paramDataArr[ 0 ] ];
+ templateVertexData.Available = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if( vertexDataDict != null )
+ {
+ vertexDataDict.Clear();
+ vertexDataDict = null;
+ }
+
+ return vertexDataList;
+ }
+
+ public static TemplateInterpData CreateInterpDataList( string interpData, string fullLine, int maxInterpolators )
+ {
+ TemplateInterpData interpDataObj = null;
+ List<TemplateVertexData> interpDataList = null;
+ Dictionary<TemplateSemantics, TemplateVertexData> interpDataDict = null;
+ Match rangeMatch = Regex.Match( fullLine, InterpRangePattern );
+ if( rangeMatch.Groups.Count > 0 )
+ {
+ interpDataObj = new TemplateInterpData();
+ // Get range of available interpolators
+ int minVal = 0;
+ int maxVal = 0;
+ try
+ {
+ string[] minValArgs = rangeMatch.Groups[ 1 ].Value.Split( IOUtils.FLOAT_SEPARATOR );
+ minVal = Convert.ToInt32( minValArgs[ 0 ] );
+ if( string.IsNullOrEmpty( rangeMatch.Groups[ 2 ].Value ) )
+ {
+ maxVal = maxInterpolators - 1;
+ interpDataObj.DynamicMax = true;
+ }
+ else
+ {
+ maxVal = Convert.ToInt32( rangeMatch.Groups[ 2 ].Value );
+ }
+ if( minVal > maxVal )
+ {
+ //int aux = minVal;
+ //minVal = maxVal;
+ //maxVal = aux;
+ maxVal = minVal;
+ }
+
+ for( int i = minVal; i <= maxVal; i++ )
+ {
+ interpDataObj.AvailableInterpolators.Add( new TemplateInterpElement( IntToSemantic[ i ] ) );
+ }
+ if( minValArgs.Length > 1 )
+ {
+ interpDataObj.AvailableInterpolators[ 0 ].SetAvailableChannelsFromString( minValArgs[ 1 ] );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ interpDataList = new List<TemplateVertexData>();
+ interpDataDict = new Dictionary<TemplateSemantics, TemplateVertexData>();
+
+ //Get Current interpolators
+ int parametersBeginIdx = fullLine.IndexOf( ":" ) + 1;
+ int parametersEnd = fullLine.IndexOf( TemplatesManager.TemplateEndOfLine );
+ string parametersBody = fullLine.Substring( parametersBeginIdx, parametersEnd - parametersBeginIdx );
+
+ foreach( Match match in Regex.Matches( interpData, VertexDataPattern ) )
+ {
+ if( match.Groups.Count > 1 )
+ {
+ WirePortDataType dataType = CgToWirePortType[ match.Groups[ 1 ].Value ];
+ string varName = match.Groups[ 2 ].Value;
+ TemplateSemantics semantics = (TemplateSemantics)Enum.Parse( typeof( TemplateSemantics ), match.Groups[ 3 ].Value );
+ TemplateVertexData templateVertexData = new TemplateVertexData( semantics, dataType, varName );
+ //interpDataList.Add( templateVertexData );
+ interpDataDict.Add( semantics, templateVertexData );
+ interpDataObj.RawInterpolators.Add( templateVertexData );
+ //Check if they are also on the free channels list and update their names
+ interpDataObj.ReplaceNameOnInterpolator( semantics, varName );
+ }
+ }
+
+ if( interpData.Contains( Constants.InstanceIdMacro ) )
+ {
+ TemplateVertexData templateInterpData = new TemplateVertexData( TemplateSemantics.SV_InstanceID, WirePortDataType.UINT, Constants.InstanceIdVariable );
+ templateInterpData.DataInfo = TemplateInfoOnSematics.INSTANCE_ID;
+ templateInterpData.Available = true;
+ templateInterpData.ExcludeStructPrefix = true;
+ interpDataList.Add( templateInterpData );
+ interpDataDict.Add( TemplateSemantics.SV_InstanceID, templateInterpData );
+ }
+
+ Dictionary<string, TemplateVertexData> auxDict = new Dictionary<string, TemplateVertexData>();
+ // Get info for available interpolators
+ string[] paramsArray = parametersBody.Split( IOUtils.FIELD_SEPARATOR );
+ if( paramsArray.Length > 0 )
+ {
+ for( int i = 0; i < paramsArray.Length; i++ )
+ {
+ string[] paramDataArr = paramsArray[ i ].Split( IOUtils.VALUE_SEPARATOR );
+ if( paramDataArr.Length == 2 )
+ {
+ string[] swizzleInfoArr = paramDataArr[ 1 ].Split( IOUtils.FLOAT_SEPARATOR );
+ TemplateSemantics semantic = ShortcutToSemantic[ swizzleInfoArr[ 0 ] ];
+ if( interpDataDict.ContainsKey( semantic ) )
+ {
+ if( interpDataDict[ semantic ] != null )
+ {
+ string[] multiComponent = paramDataArr[ 0 ].Split( IOUtils.FLOAT_SEPARATOR );
+
+ if( multiComponent.Length > 1 )
+ {
+ TemplateVertexData templateInterpData = null;
+ if( auxDict.ContainsKey( multiComponent[ 0 ] ) )
+ {
+ templateInterpData = auxDict[ multiComponent[ 0 ] ];
+ }
+ else
+ {
+ templateInterpData = new TemplateVertexData( interpDataDict[ semantic ] );
+ //if( swizzleInfoArr.Length > 1 )
+ //{
+ // templateInterpData.DataSwizzle = "." + swizzleInfoArr[ 1 ];
+ //}
+ templateInterpData.DataInfo = ShortcutToInfo[ multiComponent[ 0 ] ];
+ templateInterpData.Available = true;
+ interpDataList.Add( templateInterpData );
+ auxDict.Add( multiComponent[ 0 ], templateInterpData );
+ }
+
+ if( swizzleInfoArr[ 1 ].Length == multiComponent[ 1 ].Length )
+ {
+ for( int channelIdx = 0; channelIdx < swizzleInfoArr[ 1 ].Length; channelIdx++ )
+ {
+ templateInterpData.RegisterComponent( multiComponent[ 1 ][ channelIdx ], interpDataDict[ semantic ].VarName + "." + swizzleInfoArr[ 1 ][ channelIdx ] );
+ }
+ }
+ }
+ else
+ {
+ TemplateVertexData templateInterpData = new TemplateVertexData( interpDataDict[ semantic ] );
+ if( swizzleInfoArr.Length > 1 )
+ {
+ templateInterpData.DataSwizzle = "." + swizzleInfoArr[ 1 ];
+ }
+ templateInterpData.DataInfo = ShortcutToInfo[ paramDataArr[ 0 ] ];
+ templateInterpData.Available = true;
+ interpDataList.Add( templateInterpData );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*TODO:
+ 1) Remove interpDataList.Add( templateVertexData ); from initial foreach
+ 2) When looping though each foreach array element, create a new TemplateVertexData
+ from the one containted on the interpDataDict and add it to interpDataList
+ */
+ for( int i = 0; i < interpDataList.Count; i++ )
+ {
+ interpDataList[ i ].BuildVar();
+ }
+
+ auxDict.Clear();
+ auxDict = null;
+
+ interpDataObj.Interpolators = interpDataList;
+ interpDataDict.Clear();
+ interpDataDict = null;
+ }
+ return interpDataObj;
+ }
+
+ public static void FetchDependencies( TemplateInfoContainer dependencies, ref string body )
+ {
+ int index = body.IndexOf( TemplatesManager.TemplateDependenciesListTag );
+ if( index > 0 )
+ {
+ dependencies.Index = index;
+ dependencies.Id = TemplatesManager.TemplateDependenciesListTag;
+ dependencies.Data = TemplatesManager.TemplateDependenciesListTag;
+ }
+ else
+ {
+ int lastIndex = body.LastIndexOf( '}' );
+ if( lastIndex > 0 )
+ {
+ body = body.Insert( lastIndex, "\t" + TemplatesManager.TemplateDependenciesListTag + "\n" );
+ FetchDependencies( dependencies, ref body );
+ }
+ }
+ }
+
+ public static void FetchCustomInspector( TemplateInfoContainer inspectorContainer, ref string body )
+ {
+ Match match = Regex.Match( body, CustomInspectorPattern, RegexOptions.Multiline );
+ if( match != null && match.Groups.Count > 1 )
+ {
+ inspectorContainer.Index = match.Index;
+ inspectorContainer.Id = match.Groups[ 0 ].Value;
+ inspectorContainer.Data = match.Groups[ 1 ].Value;
+
+#if UNITY_2019_3_OR_NEWER
+ if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 )
+ {
+ if( inspectorContainer.Data.Equals( "UnityEditor.Experimental.Rendering.HDPipeline.HDLitGUI" ) )
+ inspectorContainer.Data = "UnityEditor.Rendering.HighDefinition.HDLitGUI";
+ }
+#endif
+ }
+ else
+ {
+ int index = body.LastIndexOf( '}' );
+ if( index > 0 )
+ {
+ body = body.Insert( index, string.Format( "\tCustomEditor \"{0}\"\n", Constants.DefaultCustomInspector ) );
+ FetchCustomInspector( inspectorContainer, ref body );
+ }
+ }
+ }
+
+ public static void FetchFallback( TemplateInfoContainer fallbackContainer, ref string body )
+ {
+ Match match = Regex.Match( body, FallbackPattern, RegexOptions.Multiline | RegexOptions.IgnoreCase );
+ if( match != null && match.Groups.Count > 1 )
+ {
+ fallbackContainer.Index = match.Index;
+ fallbackContainer.Id = match.Groups[ 0 ].Value;
+ fallbackContainer.Data = match.Groups[ 1 ].Value;
+ }
+ else
+ {
+ int index = body.LastIndexOf( '}' );
+ if( index > 0 )
+ {
+ body = body.Insert( index, "\tFallback \"\"\n" );
+ FetchFallback( fallbackContainer, ref body );
+ }
+ }
+ }
+
+ public static string AutoSwizzleData( string dataVar, WirePortDataType from, WirePortDataType to, bool isPosition )
+ {
+ switch( from )
+ {
+ case WirePortDataType.COLOR:
+ case WirePortDataType.FLOAT4:
+ {
+ switch( to )
+ {
+ case WirePortDataType.FLOAT3: dataVar += ".xyz"; break;
+ case WirePortDataType.FLOAT2: dataVar += ".xy"; break;
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT: dataVar += ".x"; break;
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT3:
+ {
+ switch( to )
+ {
+ case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},{1})", dataVar,(isPosition?1:0) ); break;
+ case WirePortDataType.FLOAT2: dataVar += ".xy"; break;
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT: dataVar += ".x"; break;
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT2:
+ {
+ switch( to )
+ {
+ case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},0,{1})", dataVar , (isPosition ? 1 : 0) ); break;
+ case WirePortDataType.FLOAT3: dataVar = string.Format( "float3({0},0)", dataVar ); break;
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT: dataVar += ".x"; break;
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT:
+ {
+ switch( to )
+ {
+ case WirePortDataType.FLOAT4: dataVar = string.Format( "float4({0},0,0,{1})", dataVar, ( isPosition ? 1 : 0 ) ); break;
+ case WirePortDataType.FLOAT3: dataVar = string.Format( "float3({0},0,0)", dataVar ); break;
+ case WirePortDataType.FLOAT2: dataVar = string.Format( "float2({0},0)", dataVar ); break;
+ }
+ }
+ break;
+ }
+ return dataVar;
+ }
+
+ public static bool CheckIfTemplate( string assetPath )
+ {
+ Type type = AssetDatabase.GetMainAssetTypeAtPath( assetPath );
+ if( type == typeof( Shader ) )
+ {
+ Shader shader = AssetDatabase.LoadAssetAtPath<Shader>( assetPath );
+ if( shader != null )
+ {
+ string body = IOUtils.LoadTextFileFromDisk( assetPath );
+ return ( body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) > -1 );
+ }
+ }
+ return false;
+ }
+
+ public static bool CheckIfCompatibles( WirePortDataType first, WirePortDataType second )
+ {
+ switch( first )
+ {
+ case WirePortDataType.OBJECT:
+ return true;
+ case WirePortDataType.FLOAT:
+ case WirePortDataType.FLOAT2:
+ case WirePortDataType.FLOAT3:
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR:
+ case WirePortDataType.INT:
+ {
+ switch( second )
+ {
+ case WirePortDataType.FLOAT3x3:
+ case WirePortDataType.FLOAT4x4:
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ return false;
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT3x3:
+ case WirePortDataType.FLOAT4x4:
+ {
+ switch( second )
+ {
+ case WirePortDataType.FLOAT:
+ case WirePortDataType.FLOAT2:
+ case WirePortDataType.FLOAT3:
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR:
+ case WirePortDataType.INT:
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ return false;
+ }
+ }
+ break;
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ {
+ switch( second )
+ {
+ case WirePortDataType.FLOAT:
+ case WirePortDataType.FLOAT2:
+ case WirePortDataType.FLOAT3:
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.FLOAT3x3:
+ case WirePortDataType.FLOAT4x4:
+ case WirePortDataType.COLOR:
+ case WirePortDataType.INT:
+ return false;
+ }
+ }
+ break;
+ }
+ return true;
+ }
+ // Lightweight <-> Default functions
+ public static string WorldSpaceViewDir( MasterNodeDataCollector dataCollector, string worldPosVec3, bool normalize )
+ {
+ string value = string.Empty;
+ if( dataCollector.IsTemplate && dataCollector.IsSRP )
+ {
+ value = string.Format( "_WorldSpaceCameraPos.xyz - {0}", worldPosVec3 );
+ }
+ else
+ {
+ value = string.Format( "UnityWorldSpaceViewDir( {0} )", worldPosVec3 );
+ }
+
+ if( normalize )
+ {
+ value = SafeNormalize( dataCollector, value );
+ }
+
+ return value;
+ }
+
+ public static string SafeNormalize( MasterNodeDataCollector dataCollector, string value )
+ {
+ if( dataCollector.IsTemplate && dataCollector.IsSRP )
+ {
+ value = string.Format( "SafeNormalize( {0} )", value );
+ }
+ else
+ {
+ dataCollector.AddToIncludes( -1, Constants.UnityBRDFLib );
+ value = string.Format( "Unity_SafeNormalize( {0} )", value );
+ }
+ return value;
+ }
+
+
+ public static string CreateUnpackNormalStr( MasterNodeDataCollector dataCollector, bool applyScale, string scale )
+ {
+ string funcName;
+ if( dataCollector.IsTemplate && dataCollector.IsSRP )
+ {
+ if( dataCollector.TemplateDataCollectorInstance.IsHDRP )
+ {
+ funcName = "UnpackNormalmapRGorAG( {0}, " + scale + " )";
+ }
+ else
+ {
+ funcName = "UnpackNormalScale( {0}, " + scale + " )";
+ }
+ }
+ else
+ {
+ funcName = applyScale ? "UnpackScaleNormal( {0}, " + scale + " )" : "UnpackNormal( {0} )";
+ }
+ return funcName;
+ }
+
+ public static bool IsInlineProperty( string data, ref string property )
+ {
+ if( data.Length > 0 && data[ 0 ] == '[' && data[ data.Length - 1 ] == ']' )
+ {
+ property = data.Substring( 1, data.Length - 2 );
+ return true;
+ }
+ return false;
+ }
+
+ // public static readonly string FetchDefaultDepthFormat = "UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD( {0} )))";
+ public static readonly string FetchDefaultDepthFormat = "SAMPLE_DEPTH_TEXTURE( _CameraDepthTexture, {0}.xy )";
+ public static readonly string FetchDefaultDepthFormatVertex = "SAMPLE_DEPTH_TEXTURE_LOD( _CameraDepthTexture, float4( {0}.xy, 0, 0 ) )";
+
+ public static readonly string FetchLWDepthFormat = "SHADERGRAPH_SAMPLE_SCENE_DEPTH( {0}.xy )";
+ public static readonly string FetchLWDepthFormatVertex = "SHADERGRAPH_SAMPLE_SCENE_DEPTH_LOD( {0}.xy )";
+#if UNITY_2018_3_OR_NEWER
+ public static readonly string FetchHDDepthFormat = "SampleCameraDepth( {0}.xy )";
+#else
+ public static readonly string FetchHDDepthFormat = "SAMPLE_TEXTURE2D( _CameraDepthTexture, s_point_clamp_sampler, {0}.xy ).r";
+#endif
+ public static string CreateDepthFetch( MasterNodeDataCollector dataCollector, string screenPos )
+ {
+ string screenDepthInstruction = string.Empty;
+ if( dataCollector.IsTemplate && dataCollector.IsSRP )
+ {
+ if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.Lightweight )
+ {
+ if( dataCollector.PortCategory == MasterNodePortCategory.Vertex )
+ {
+ string m_functionBody = string.Empty;
+ GenerateLW( ref m_functionBody );
+ dataCollector.AddFunctions( FetchLWDepthFormatVertex, m_functionBody, "0" );
+ screenDepthInstruction = string.Format( FetchLWDepthFormatVertex, screenPos );
+ }
+ else
+ screenDepthInstruction = string.Format( FetchLWDepthFormat, screenPos );
+ }
+ else if( dataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD )
+ screenDepthInstruction = string.Format( FetchHDDepthFormat, screenPos );
+ }
+ else
+ {
+ if( dataCollector.PortCategory == MasterNodePortCategory.Vertex )
+ screenDepthInstruction = string.Format( FetchDefaultDepthFormatVertex, screenPos );
+ else
+ screenDepthInstruction = string.Format( FetchDefaultDepthFormat, screenPos );
+ }
+ return screenDepthInstruction;
+ }
+
+ public static void GenerateLW( ref string body )
+ {
+ body = string.Empty;
+ IOUtils.AddFunctionHeader( ref body, "float SHADERGRAPH_SAMPLE_SCENE_DEPTH_LOD(float2 uv)" );
+ IOUtils.AddFunctionLine( ref body, "#if defined(REQUIRE_DEPTH_TEXTURE)" );
+ IOUtils.AddFunctionLine( ref body, "#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)" );
+ IOUtils.AddFunctionLine( ref body, " \tfloat rawDepth = SAMPLE_TEXTURE2D_ARRAY_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, uv, unity_StereoEyeIndex, 0).r;" );
+ IOUtils.AddFunctionLine( ref body, "#else" );
+ IOUtils.AddFunctionLine( ref body, " \tfloat rawDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, uv, 0);" );
+ IOUtils.AddFunctionLine( ref body, "#endif" );
+ IOUtils.AddFunctionLine( ref body, "return rawDepth;" );
+ IOUtils.AddFunctionLine( ref body, "#endif // REQUIRE_DEPTH_TEXTURE" );
+ IOUtils.AddFunctionLine( ref body, "return 0;" );
+ IOUtils.CloseFunctionBody( ref body );
+ }
+
+ public static bool GetShaderModelForInterpolatorAmount( int interpAmount, ref string shaderModel )
+ {
+ for( int i = 0; i < AvailableShaderModels.Length; i++ )
+ {
+ if( AvailableInterpolators[ AvailableShaderModels[ i ] ] >= interpAmount )
+ {
+ shaderModel = AvailableShaderModels[ i ];
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static string GetSubShaderFrom( string shaderBody )
+ {
+ Match match = Regex.Match( shaderBody, FetchSubShaderBody, RegexOptions.Singleline );
+ if( match.Success && match.Groups.Count > 1 )
+ {
+ return match.Groups[ 1 ].Value;
+ }
+
+ return string.Empty;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta
new file mode 100644
index 00000000..8cbfe8cd
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateHelperFunctions.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 517aad6764d713946bc566f0a83cd44d
+timeCreated: 1495548641
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs
new file mode 100644
index 00000000..a9d242d0
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs
@@ -0,0 +1,236 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplatePassId
+ {
+ public string PassId;
+ public bool RemoveFromShader;
+ }
+
+
+ [Serializable]
+ public class TemplateTag
+ {
+ public string Tag = string.Empty;
+ public string Replacement = string.Empty;
+ public string Output = string.Empty;
+ public TemplateTag( string tag, string replacement = null )
+ {
+ Tag = tag;
+ if( replacement != null )
+ {
+ Replacement = replacement;
+ Output = replacement;
+ }
+ }
+ }
+
+ [Serializable]
+ public class TemplateId
+ {
+ public int StartIdx = -1;
+ public string UniqueID;
+ public string Tag;
+ public string ReplacementText;
+ public bool IsReplaced = false;
+ public bool EmptyReplacer = false;
+ public TemplateId( int bodyIdx, string uniqueID, string tag, bool emptyReplacer = false )
+ {
+ StartIdx = bodyIdx;
+ UniqueID = uniqueID;
+ Tag = tag;
+ EmptyReplacer = emptyReplacer;
+ ReplacementText = emptyReplacer ? string.Empty : tag;
+ }
+
+ public void SetReplacementText( string replacementText )
+ {
+ ReplacementText = replacementText;
+ IsReplaced = true;
+ }
+
+ public void Reset()
+ {
+ ReplacementText = EmptyReplacer?string.Empty:Tag;
+ IsReplaced = false;
+ }
+ }
+
+ [Serializable]
+ public class TemplateIdManager
+ {
+ [SerializeField]
+ private bool m_isSorted = false;
+ [SerializeField]
+ private string m_shaderBody;
+ [SerializeField]
+ private List<TemplateId> m_registeredIds = new List<TemplateId>();
+
+ [SerializeField]
+ private List<TemplateTag> m_registeredTags = new List<TemplateTag>();
+
+ [SerializeField]
+ private List<TemplatePassId> m_registeredPassIds = new List<TemplatePassId>();
+
+ private Dictionary<string, TemplateId> m_registeredIdsDict = new Dictionary<string, TemplateId>();
+
+ public TemplateIdManager( string shaderBody )
+ {
+ m_shaderBody = shaderBody;
+ }
+
+ public void Destroy()
+ {
+ m_registeredPassIds.Clear();
+ m_registeredPassIds = null;
+
+ m_registeredTags.Clear();
+ m_registeredTags = null;
+
+ m_registeredIds.Clear();
+ m_registeredIds = null;
+ if( m_registeredIdsDict != null )
+ {
+ m_registeredIdsDict.Clear();
+ m_registeredIdsDict = null;
+ }
+ }
+
+ void RefreshIds()
+ {
+ if( m_registeredIdsDict == null )
+ {
+ m_registeredIdsDict = new Dictionary<string, TemplateId>();
+ }
+
+ if( m_registeredIdsDict.Count != m_registeredIds.Count )
+ {
+ m_registeredIdsDict.Clear();
+ int count = m_registeredIds.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_registeredIdsDict.Add( m_registeredIds[ i ].UniqueID, m_registeredIds[ i ] );
+ }
+ }
+ }
+
+ public void RegisterId( int bodyIdx, string uniqueID, string tag, bool emptyReplacer = false )
+ {
+ if( bodyIdx < 0 )
+ return;
+
+ RefreshIds();
+
+ TemplateId templateId = new TemplateId( bodyIdx, uniqueID, tag, emptyReplacer );
+ m_registeredIds.Add( templateId );
+ m_registeredIdsDict.Add( uniqueID, templateId );
+ }
+
+ public void RegisterTag( string tag, string replacement = null )
+ {
+ m_registeredTags.Add( new TemplateTag( tag, replacement ) );
+ }
+
+ public void RegisterPassId( string passId )
+ {
+ m_registeredPassIds.Add( new TemplatePassId() { PassId = passId, RemoveFromShader = false } );
+ }
+
+ public void SetPassIdUsage( int idx , bool removeFromShader )
+ {
+ m_registeredPassIds[ idx ].RemoveFromShader = removeFromShader;
+ }
+
+ public void SetReplacementText( string uniqueId, string replacementText )
+ {
+ RefreshIds();
+
+ if( m_registeredIdsDict.ContainsKey( uniqueId ) && m_registeredIdsDict[ uniqueId ].StartIdx >= 0 )
+ m_registeredIdsDict[ uniqueId ].SetReplacementText( replacementText );
+ }
+
+
+ public string BuildShader()
+ {
+ if( !m_isSorted )
+ {
+ m_registeredIds.Sort( ( x, y ) => { return x.StartIdx.CompareTo( y.StartIdx ); } );
+ }
+
+ int idCount = m_registeredIds.Count;
+ int offset = 0;
+ string finalShaderBody = m_shaderBody;
+ for( int i = 0; i < idCount; i++ )
+ {
+ if( m_registeredIds[ i ].StartIdx >= 0 && m_registeredIds[ i ].IsReplaced )
+ {
+ finalShaderBody = finalShaderBody.ReplaceAt( m_registeredIds[ i ].Tag, m_registeredIds[ i ].ReplacementText, offset + m_registeredIds[ i ].StartIdx );
+ offset += ( m_registeredIds[ i ].ReplacementText.Length - m_registeredIds[ i ].Tag.Length );
+ }
+ }
+
+ int count = m_registeredPassIds.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_registeredPassIds[ i ].RemoveFromShader )
+ finalShaderBody = finalShaderBody.Replace( m_registeredPassIds[ i ].PassId, string.Empty );
+ }
+
+ for( int i = 0; i < idCount; i++ )
+ {
+ if( !m_registeredIds[ i ].IsReplaced && !m_registeredIds[ i ].Tag.Equals( m_registeredIds[ i ].ReplacementText ) )
+ {
+ finalShaderBody = finalShaderBody.Replace( m_registeredIds[ i ].Tag, m_registeredIds[ i ].ReplacementText );
+ }
+ }
+
+ count = m_registeredTags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ finalShaderBody = finalShaderBody.Replace( m_registeredTags[ i ].Tag, m_registeredTags[ i ].Replacement );
+ m_registeredTags[ i ].Replacement = m_registeredTags[ i ].Output;
+ }
+
+ //finalShaderBody = finalShaderBody.Replace( TemplatesManager.TemplateExcludeFromGraphTag, string.Empty );
+ //finalShaderBody = finalShaderBody.Replace( TemplatesManager.TemplateMainPassTag, string.Empty );
+
+ return finalShaderBody;
+ }
+
+ public void ResetRegistersState()
+ {
+ int count = m_registeredIds.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_registeredIds[ i ].Reset();
+ }
+ }
+
+ public void Reset()
+ {
+ m_registeredIds.Clear();
+ if( m_registeredIdsDict == null )
+ {
+ m_registeredIdsDict = new Dictionary<string, TemplateId>();
+ }
+ else
+ {
+ m_registeredIdsDict.Clear();
+ }
+ }
+
+ public string ShaderBody
+ {
+ get { return m_shaderBody; }
+ set { m_shaderBody = value; }
+ }
+
+ public List<TemplateTag> RegisteredTags { get { return m_registeredTags; } set { m_registeredTags = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta
new file mode 100644
index 00000000..887ff5a8
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateIdManager.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b0d2e93061ffcbd45b085a61e5000daa
+timeCreated: 1517315635
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs
new file mode 100644
index 00000000..6e5da580
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs
@@ -0,0 +1,234 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateInterpElement
+ {
+ public TemplateSemantics Semantic;
+ public bool[] AvailableChannels = { true, true, true, true };
+ public bool IsFull = false;
+ public int Usage = 0;
+ public string Name;
+
+ public TemplateInterpElement( TemplateInterpElement other )
+ {
+ Semantic = other.Semantic;
+ for ( int i = 0; i < AvailableChannels.Length; i++ )
+ {
+ AvailableChannels[ i ] = other.AvailableChannels[ i ];
+ }
+ IsFull = other.IsFull;
+ Usage = other.Usage;
+ Name = other.Name;
+ }
+
+ public TemplateInterpElement( TemplateSemantics semantic )
+ {
+ Semantic = semantic;
+ int semanticId = TemplateHelperFunctions.SemanticToInt[ Semantic ];
+ Name = ( semanticId == 0 ) ? TemplateHelperFunctions.BaseInterpolatorName : TemplateHelperFunctions.BaseInterpolatorName + semanticId.ToString();
+ }
+
+ public void SetAvailableChannelsFromString( string channels )
+ {
+ for ( int i = 0; i < AvailableChannels.Length; i++ )
+ {
+ AvailableChannels[ i ] = false;
+ }
+ Usage = AvailableChannels.Length;
+
+ for ( int i = 0; i < channels.Length; i++ )
+ {
+ switch ( channels[ i ] )
+ {
+ case 'x': if ( !AvailableChannels[ 0 ] ) { AvailableChannels[ 0 ] = true; Usage--; } break;
+ case 'y': if ( !AvailableChannels[ 1 ] ) { AvailableChannels[ 1 ] = true; Usage--; } break;
+ case 'z': if ( !AvailableChannels[ 2 ] ) { AvailableChannels[ 2 ] = true; Usage--; } break;
+ case 'w': if ( !AvailableChannels[ 3 ] ) { AvailableChannels[ 3 ] = true; Usage--; } break;
+ }
+ }
+ }
+
+ public TemplateVertexData RequestChannels( WirePortDataType type, bool isColor, string customName = null )
+ {
+ if ( IsFull )
+ return null;
+
+ int channelsRequired = TemplateHelperFunctions.DataTypeChannelUsage[ type ];
+ if ( channelsRequired == 0 )
+ return null;
+
+ int firstChannel = -1;
+ for ( int i = 0; i < AvailableChannels.Length; i++ )
+ {
+ if ( AvailableChannels[ i ] )
+ {
+ if ( firstChannel < 0 )
+ {
+ firstChannel = i;
+ }
+ channelsRequired -= 1;
+ if ( channelsRequired == 0 )
+ break;
+ }
+ }
+
+ //did not found enough channels to fill request
+ if ( channelsRequired > 0 )
+ return null;
+
+ if( Usage == 0 && customName != null )
+ {
+ Name = customName;
+ }
+
+ Usage += 1;
+ TemplateVertexData data = null;
+
+ if ( type == WirePortDataType.COLOR || type == WirePortDataType.FLOAT4 )
+ {
+ // Automatically lock all channels
+ for ( int i = firstChannel; i < ( firstChannel + channelsRequired ); i++ )
+ {
+ AvailableChannels[ i ] = false;
+ }
+ IsFull = true;
+ data = new TemplateVertexData( Semantic, type, Name );
+ }
+ else
+ {
+ string[] swizzleArray = ( isColor ) ? TemplateHelperFunctions.ColorSwizzle : TemplateHelperFunctions.VectorSwizzle;
+ string channels = ".";
+ int count = firstChannel + TemplateHelperFunctions.DataTypeChannelUsage[ type ];
+ for ( int i = firstChannel; i < count; i++ )
+ {
+ AvailableChannels[ i ] = false;
+ channels += swizzleArray[ i ];
+ if ( i == ( AvailableChannels.Length - 1 ) )
+ {
+ IsFull = true;
+ }
+ }
+
+ data = new TemplateVertexData( Semantic, type, Name, channels );
+ }
+ return data;
+ }
+ }
+
+ [Serializable]
+ public class TemplateInterpData
+ {
+ [SerializeField]
+ private string m_interpDataId = string.Empty;
+
+ [SerializeField]
+ private int m_interpDataStartIdx = -1;
+
+ [SerializeField]
+ private bool m_dynamicMax = false;
+
+ public List<TemplateInterpElement> AvailableInterpolators = new List<TemplateInterpElement>();
+ public List<TemplateVertexData> Interpolators = new List<TemplateVertexData>();
+ public List<TemplateVertexData> RawInterpolators = new List<TemplateVertexData>();
+
+ public TemplateInterpData() { }
+
+ public bool HasRawInterpolatorOfName( string name )
+ {
+ return RawInterpolators.Exists( ( x ) => x.VarName.Equals( name ));
+ }
+
+ public TemplateInterpData( TemplateInterpData other )
+ {
+ m_dynamicMax = other.DynamicMax;
+
+ foreach ( TemplateInterpElement data in other.AvailableInterpolators )
+ {
+ AvailableInterpolators.Add( new TemplateInterpElement( data ) );
+ }
+
+ for ( int i = 0; i < other.Interpolators.Count; i++ )
+ {
+ Interpolators.Add( new TemplateVertexData( other.Interpolators[ i ] ) );
+ }
+
+ for( int i = 0; i < other.RawInterpolators.Count; i++ )
+ {
+ RawInterpolators.Add( new TemplateVertexData( other.RawInterpolators[ i ] ) );
+ }
+ }
+
+
+ public void RecalculateAvailableInterpolators( int newMax )
+ {
+ if( m_dynamicMax )
+ {
+ if( !TemplateHelperFunctions.IntToSemantic.ContainsKey( ( newMax - 1 ) ) )
+ {
+ Debug.LogWarning( "Attempting to add inexisting available interpolators" );
+ return;
+ }
+
+ if( AvailableInterpolators.Count > 0 )
+ {
+ int currMax = 1 + TemplateHelperFunctions.SemanticToInt[ AvailableInterpolators[ AvailableInterpolators.Count - 1 ].Semantic ];
+ if( newMax > currMax )
+ {
+ int count = newMax - currMax;
+ for( int i = 0; i < count; i++ )
+ {
+ AvailableInterpolators.Add( new TemplateInterpElement( TemplateHelperFunctions.IntToSemantic[ currMax + i ] ));
+ }
+ }
+ else if( newMax < currMax )
+ {
+ int min = TemplateHelperFunctions.SemanticToInt[ AvailableInterpolators[ 0 ].Semantic ];
+ if( newMax > min )
+ {
+ int count = currMax - newMax;
+ for( int i = 0; i < count; i++ )
+ {
+ AvailableInterpolators.RemoveAt( AvailableInterpolators.Count - 1 );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void ReplaceNameOnInterpolator( TemplateSemantics semantic, string newName )
+ {
+ for ( int i = 0; i < AvailableInterpolators.Count; i++ )
+ {
+ if ( AvailableInterpolators[ i ].Semantic == semantic )
+ {
+ AvailableInterpolators[ i ].Name = newName;
+ break;
+ }
+ }
+ }
+
+ public void Destroy()
+ {
+ AvailableInterpolators.Clear();
+ AvailableInterpolators = null;
+
+ Interpolators.Clear();
+ Interpolators = null;
+
+ RawInterpolators.Clear();
+ RawInterpolators = null;
+ }
+
+ public string InterpDataId { get { return m_interpDataId; } set { m_interpDataId = value; } }
+ public int InterpDataStartIdx { get { return m_interpDataStartIdx; } set { m_interpDataStartIdx = value; } }
+ public bool DynamicMax { get { return m_dynamicMax; } set { m_dynamicMax = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta
new file mode 100644
index 00000000..cf31bc9b
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateInterpData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8f700ba5366bcda45beea5c0e2db9f3e
+timeCreated: 1496053368
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs
new file mode 100644
index 00000000..3cde2f03
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs
@@ -0,0 +1,59 @@
+using System;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateLocalVarData
+ {
+ [SerializeField]
+ private WirePortDataType m_dataType = WirePortDataType.OBJECT;
+
+ [SerializeField]
+ private string m_localVarName = string.Empty;
+
+ [SerializeField]
+ private int m_position = -1;
+
+ [SerializeField]
+ private bool m_isSpecialVar = false;
+
+ [SerializeField]
+ private TemplateInfoOnSematics m_specialVarType;
+
+ [SerializeField]
+ private MasterNodePortCategory m_category;
+
+ [SerializeField]
+ private string m_id;
+
+ public TemplateLocalVarData( WirePortDataType dataType, MasterNodePortCategory category, string localVarName, int position )
+ {
+ m_dataType = dataType;
+ m_localVarName = localVarName;
+ m_position = position;
+ m_category = category;
+ //Debug.Log( m_localVarName + " " + m_inputData.PortCategory + " " + m_inputData.PortName );
+ }
+
+ public TemplateLocalVarData( TemplateInfoOnSematics specialVarType,string id, WirePortDataType dataType, MasterNodePortCategory category, string localVarName, int position )
+ {
+ m_id = id;
+ m_dataType = dataType;
+ m_localVarName = localVarName;
+ m_position = position;
+ m_specialVarType = specialVarType;
+ m_isSpecialVar = true;
+ m_category = category;
+ //Debug.Log( m_localVarName + " " + m_inputData.PortCategory + " " + m_inputData.PortName );
+ }
+
+ public WirePortDataType DataType { get { return m_dataType; } }
+ public string LocalVarName { get { return m_localVarName; } }
+ public int Position { get { return m_position; } }
+ public bool IsSpecialVar { get { return m_isSpecialVar; } }
+ public TemplateInfoOnSematics SpecialVarType{ get { return m_specialVarType; } }
+ public MasterNodePortCategory Category { get { return m_category; } }
+ public string Id { get { return m_id; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta
new file mode 100644
index 00000000..267c3527
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4c6ad22d8633c7142ae0237479df76ed
+timeCreated: 1518017743
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs
new file mode 100644
index 00000000..85898210
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs
@@ -0,0 +1,258 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ [NodeAttributes( "Template Local Var Data", "Surface Data", "Select and use available local variable data from the template" )]
+ public sealed class TemplateLocalVarsNode : TemplateNodeParent
+ {
+ private List<TemplateLocalVarData> m_localVarsData = null;
+
+ [SerializeField]
+ private int m_currentDataIdx = -1;
+
+ [SerializeField]
+ private string m_dataName = string.Empty;
+
+ private string[] m_dataLabels = null;
+
+ private bool m_fetchDataId = false;
+ private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper();
+
+ void FetchDataId()
+ {
+ if( m_localVarsData != null && m_localVarsData.Count > 0 )
+ {
+ m_currentDataIdx = 0;
+ int count = m_localVarsData.Count;
+ m_dataLabels = new string[ count ];
+ for( int i = 0; i < count; i++ )
+ {
+ m_dataLabels[ i ] = m_localVarsData[ i ].LocalVarName;
+ if( m_localVarsData[ i ].LocalVarName.Equals( m_dataName ) )
+ {
+ m_currentDataIdx = i;
+ }
+ }
+ UpdateFromId();
+ }
+ else
+ {
+ m_currentDataIdx = -1;
+ }
+ }
+
+ void UpdateFromId()
+ {
+ if( m_localVarsData != null )
+ {
+ if( m_localVarsData.Count == 0 )
+ {
+ for( int i = 0; i < 4; i++ )
+ m_containerGraph.DeleteConnection( false, UniqueId, i, false, true );
+
+ m_headerColor = UIUtils.GetColorFromCategory( "Default" );
+ m_content.text = "None";
+ m_additionalContent.text = string.Empty;
+ m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false );
+ ConfigurePorts();
+ return;
+ }
+
+ bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_localVarsData[ m_currentDataIdx ].DataType );
+ string category = m_localVarsData[ m_currentDataIdx ].Category == MasterNodePortCategory.Fragment ? "Surface Data" : "Vertex Data";
+ m_headerColor = UIUtils.GetColorFromCategory( category );
+ switch( m_localVarsData[ m_currentDataIdx ].DataType )
+ {
+ default:
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_localVarsData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT2:
+ m_outputPorts[ 0 ].ChangeProperties( "XY", m_localVarsData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT3:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_localVarsData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT4:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_localVarsData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.COLOR:
+ m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_localVarsData[ m_currentDataIdx ].DataType, false );
+ break;
+ }
+
+ ConfigurePorts();
+
+ if( !areCompatible )
+ {
+ m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true );
+ }
+
+ m_dataName = m_localVarsData[ m_currentDataIdx ].LocalVarName;
+ m_content.text = m_dataName;
+ m_sizeIsDirty = true;
+ CheckWarningState();
+ }
+ }
+
+ public override void DrawProperties()
+ {
+ base.DrawProperties();
+ if( m_multiPassMode )
+ {
+ DrawMultipassProperties();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+ protected override void OnSubShaderChange()
+ {
+ FetchLocalVarData();
+ FetchDataId();
+ }
+
+ protected override void OnPassChange()
+ {
+ base.OnPassChange();
+ FetchLocalVarData();
+ FetchDataId();
+ }
+
+ void DrawMultipassProperties()
+ {
+ DrawSubShaderUI();
+ DrawPassUI();
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ base.Draw( drawInfo );
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ return;
+
+ if( m_localVarsData == null || m_localVarsData.Count == 0 )
+ {
+ MasterNode masterNode = m_containerGraph.CurrentMasterNode;
+ if( masterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ FetchLocalVarData( masterNode );
+ }
+ }
+
+ if( m_fetchDataId )
+ {
+ m_fetchDataId = false;
+ FetchDataId();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( m_localVarsData[ m_currentDataIdx ].Category != dataCollector.PortCategory )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "Local Var {0} can only work on ports of type {1}", m_localVarsData[ m_currentDataIdx ].LocalVarName, m_localVarsData[ m_currentDataIdx ].Category ) );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( m_multiPassMode )
+ {
+ if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx ||
+ dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx
+ )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+ }
+
+ return GetOutputVectorItem( 0, outputId, m_dataName );
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ m_dataName = GetCurrentParam( ref nodeParams );
+ m_fetchDataId = true;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName );
+ }
+
+ public override void OnMasterNodeReplaced( MasterNode newMasterNode )
+ {
+ base.OnMasterNodeReplaced( newMasterNode );
+ if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ FetchLocalVarData( newMasterNode );
+ }
+ else
+ {
+ m_localVarsData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+
+ void FetchLocalVarData( MasterNode masterNode = null )
+ {
+ FetchMultiPassTemplate( masterNode );
+ if( m_multiPassMode )
+ {
+ if( m_templateMPData != null )
+ {
+ m_localVarsData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].LocalVarsList;
+ m_fetchDataId = true;
+ }
+ }
+ else
+ {
+ TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate;
+ if( currentTemplate != null )
+ {
+ m_localVarsData = currentTemplate.LocalVarsList;
+ m_fetchDataId = true;
+ }
+ else
+ {
+ m_localVarsData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_dataLabels = null;
+ m_localVarsData = null;
+ m_upperLeftWidgetHelper = null;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta
new file mode 100644
index 00000000..f7453d99
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateLocalVarsNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f708a5bf672ab004a9363a4a71f48f28
+timeCreated: 1518104790
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs
new file mode 100644
index 00000000..6d6c1de9
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs
@@ -0,0 +1,750 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+// THIS FILE IS DEPRECATED AND SHOULD NOT BE USED
+
+#define SHOW_TEMPLATE_HELP_BOX
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ [NodeAttributes( "Template Master Node", "Master", "Shader Generated according to template rules", null, KeyCode.None, false, true, "Template MultiPass Master Node", typeof( TemplateMultiPassMasterNode ) )]
+ public sealed class TemplateMasterNode : MasterNode
+ {
+ private const string WarningMessage = "Templates is a feature that is still heavily under development and users may experience some problems.\nPlease email support@amplify.pt if any issue occurs.";
+ private const string CurrentTemplateLabel = "Current Template";
+ private const string OpenTemplateStr = "Edit Template";
+
+ //protected const string SnippetsFoldoutStr = " Snippets";
+ //[SerializeField]
+ //private bool m_snippetsFoldout = true;
+
+ [NonSerialized]
+ private TemplateData m_currentTemplate = null;
+
+ private bool m_fireTemplateChange = false;
+ private bool m_fetchMasterNodeCategory = false;
+ private bool m_reRegisterTemplateData = false;
+
+ [SerializeField]
+ private string m_templateGUID = string.Empty;
+
+ [SerializeField]
+ private string m_templateName = string.Empty;
+
+ [SerializeField]
+ private TemplatesBlendModule m_blendOpHelper = new TemplatesBlendModule();
+
+ [SerializeField]
+ private TemplateCullModeModule m_cullModeHelper = new TemplateCullModeModule();
+
+ [SerializeField]
+ private TemplateColorMaskModule m_colorMaskHelper = new TemplateColorMaskModule();
+
+ [SerializeField]
+ private TemplatesStencilBufferModule m_stencilBufferHelper = new TemplatesStencilBufferModule();
+
+ [SerializeField]
+ private TemplateDepthModule m_depthOphelper = new TemplateDepthModule();
+
+ [SerializeField]
+ private TemplateTagsModule m_tagsHelper = new TemplateTagsModule();
+
+ protected override void CommonInit( int uniqueId )
+ {
+ base.CommonInit( uniqueId );
+ m_masterNodeCategory = 1;// First Template
+ m_marginPreviewLeft = 20;
+ m_insideSize.y = 60;
+ m_customPrecision = true;
+ }
+
+ public override void ReleaseResources()
+ {
+ if( m_currentTemplate != null && m_currentTemplate.AvailableShaderProperties != null )
+ {
+ // Unregister old template properties
+ int oldPropertyCount = m_currentTemplate.AvailableShaderProperties.Count;
+ for( int i = 0; i < oldPropertyCount; i++ )
+ {
+ UIUtils.ReleaseUniformName( UniqueId, m_currentTemplate.AvailableShaderProperties[ i ].PropertyName );
+ }
+ }
+ }
+
+ public override void OnEnable()
+ {
+ base.OnEnable();
+ m_reRegisterTemplateData = true;
+ }
+
+ void FetchInfoFromTemplate()
+ {
+ if( m_currentTemplate.BlendData.DataCheck == TemplateDataCheck.Valid )
+ m_blendOpHelper.ConfigureFromTemplateData( m_currentTemplate.BlendData );
+
+ if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ m_cullModeHelper.ConfigureFromTemplateData( m_currentTemplate.CullModeData );
+
+ if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ m_colorMaskHelper.ConfigureFromTemplateData( m_currentTemplate.ColorMaskData );
+
+ if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid )
+ m_stencilBufferHelper.ConfigureFromTemplateData( m_currentTemplate.StencilData );
+
+ if( m_currentTemplate.DepthData.DataCheck == TemplateDataCheck.Valid )
+ m_depthOphelper.ConfigureFromTemplateData( m_currentTemplate.DepthData );
+
+ if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid )
+ m_tagsHelper.ConfigureFromTemplateData( m_currentTemplate.TagData );
+ }
+
+ void FetchCurrentTemplate()
+ {
+ m_currentTemplate = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateData;
+ if( m_currentTemplate == null )
+ {
+ m_currentTemplate = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateName ) as TemplateData;
+ }
+
+ if( m_currentTemplate != null )
+ {
+ if( m_inputPorts.Count != m_currentTemplate.InputDataList.Count )
+ {
+ DeleteAllInputConnections( true );
+
+ List<TemplateInputData> inputDataList = m_currentTemplate.InputDataList;
+ int count = inputDataList.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId );
+ }
+ FetchInfoFromTemplate();
+ }
+ else
+ {
+ List<TemplateInputData> inputDataList = m_currentTemplate.InputDataList;
+ int count = inputDataList.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_inputPorts[ i ].ChangeProperties( inputDataList[ i ].PortName, inputDataList[ i ].DataType, false );
+ }
+ }
+ }
+ }
+
+ public override void RefreshAvailableCategories()
+ {
+ FetchCurrentTemplate();
+
+ int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount;
+ m_availableCategories = new MasterNodeCategoriesData[ templateCount + 1 ];
+ m_availableCategoryLabels = new GUIContent[ templateCount + 1 ];
+
+ m_availableCategories[ 0 ] = new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, string.Empty );
+ m_availableCategoryLabels[ 0 ] = new GUIContent( "Surface" );
+ if( m_currentTemplate == null )
+ {
+ m_masterNodeCategory = -1;
+ }
+
+ for( int i = 0; i < templateCount; i++ )
+ {
+ int idx = i + 1;
+ TemplateData templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateData;
+
+ if( m_currentTemplate != null && m_currentTemplate.GUID.Equals( templateData.GUID ) )
+ m_masterNodeCategory = idx;
+
+ m_availableCategories[ idx ] = new MasterNodeCategoriesData( AvailableShaderTypes.Template, templateData.GUID );
+ m_availableCategoryLabels[ idx ] = new GUIContent( templateData.Name );
+ }
+ }
+
+ void SetCategoryIdxFromTemplate()
+ {
+ int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount;
+ for( int i = 0; i < templateCount; i++ )
+ {
+ int idx = i + 1;
+ TemplateData templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateData;
+ if( templateData != null && m_currentTemplate != null && m_currentTemplate.GUID.Equals( templateData.GUID ) )
+ m_masterNodeCategory = idx;
+ }
+ }
+
+ public void SetTemplate( TemplateData newTemplate, bool writeDefaultData, bool fetchMasterNodeCategory )
+ {
+ ReleaseResources();
+
+ if( newTemplate == null || newTemplate.InputDataList == null )
+ return;
+
+ m_fetchMasterNodeCategory = fetchMasterNodeCategory;
+
+ DeleteAllInputConnections( true );
+ m_currentTemplate = newTemplate;
+ m_currentShaderData = newTemplate.Name;
+
+ List<TemplateInputData> inputDataList = newTemplate.InputDataList;
+ int count = inputDataList.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId );
+ }
+
+ if( writeDefaultData )
+ {
+ ShaderName = newTemplate.DefaultShaderName;
+ }
+
+ RegisterProperties();
+ m_fireTemplateChange = true;
+ m_templateGUID = newTemplate.GUID;
+ m_templateName = newTemplate.DefaultShaderName;
+ FetchInfoFromTemplate();
+ }
+
+ void RegisterProperties()
+ {
+ if( m_currentTemplate != null )
+ {
+ m_reRegisterTemplateData = false;
+ // Register old template properties
+ int newPropertyCount = m_currentTemplate.AvailableShaderProperties.Count;
+ for( int i = 0; i < newPropertyCount; i++ )
+ {
+ int nodeId = UIUtils.CheckUniformNameOwner( m_currentTemplate.AvailableShaderProperties[ i ].PropertyName );
+ if( nodeId > -1 )
+ {
+ ParentNode node = m_containerGraph.GetNode( nodeId );
+ if( node != null )
+ {
+ UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being used by {1}. Please rename it and reload template.", m_currentTemplate.AvailableShaderProperties[ i ].PropertyName, node.Attributes.Name ) );
+ }
+ else
+ {
+ UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being on your graph. Please rename it and reload template.", m_currentTemplate.AvailableShaderProperties[ i ].PropertyName ) );
+ }
+ }
+ else
+ {
+ UIUtils.RegisterUniformName( UniqueId, m_currentTemplate.AvailableShaderProperties[ i ].PropertyName );
+ }
+ }
+ }
+ }
+
+ public override void DrawProperties()
+ {
+ if( m_currentTemplate == null )
+ return;
+
+ base.DrawProperties();
+
+ bool generalIsVisible = ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions;
+ NodeUtils.DrawPropertyGroup( ref generalIsVisible, GeneralFoldoutStr, DrawGeneralOptions );
+ ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedGeneralShaderOptions = generalIsVisible;
+ if( m_currentTemplate.BlendData.DataCheck == TemplateDataCheck.Valid )
+ m_blendOpHelper.Draw( this );
+
+
+ if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ CullMode cullMode = ( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) ? m_cullModeHelper.CurrentCullMode : CullMode.Back;
+ m_stencilBufferHelper.Draw( this, cullMode );
+ }
+
+ if( m_currentTemplate.DepthData.DataCheck == TemplateDataCheck.Valid )
+ m_depthOphelper.Draw( this );
+
+ if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid )
+ m_tagsHelper.Draw( this );
+
+ DrawMaterialInputs( UIUtils.MenuItemToolbarStyle );
+
+ // NodeUtils.DrawPropertyGroup( ref m_snippetsFoldout, SnippetsFoldoutStr, DrawSnippetOptions );
+ if( GUILayout.Button( OpenTemplateStr ) && m_currentTemplate != null )
+ {
+ try
+ {
+ string pathname = AssetDatabase.GUIDToAssetPath( m_currentTemplate.GUID );
+ if( !string.IsNullOrEmpty( pathname ) )
+ {
+ Shader selectedTemplate = AssetDatabase.LoadAssetAtPath<Shader>( pathname );
+ if( selectedTemplate != null )
+ {
+ AssetDatabase.OpenAsset( selectedTemplate, 1 );
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+#if SHOW_TEMPLATE_HELP_BOX
+ EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning );
+#endif
+
+ }
+
+ public void DrawGeneralOptions()
+ {
+ DrawShaderName();
+ DrawCurrentShaderType();
+ EditorGUI.BeginChangeCheck();
+ DrawPrecisionProperty( false );
+ if( EditorGUI.EndChangeCheck() )
+ ContainerGraph.CurrentPrecision = m_currentPrecisionType;
+
+ if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ m_cullModeHelper.Draw( this );
+
+ if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ m_colorMaskHelper.Draw( this );
+ }
+
+ //public void DrawSnippetOptions()
+ //{
+ // m_currentTemplate.DrawSnippetProperties( this );
+ //}
+
+ bool CreateInstructionsForList( ref List<InputPort> ports, ref string shaderBody, ref List<string> vertexInstructions, ref List<string> fragmentInstructions )
+ {
+ if( ports.Count == 0 )
+ return true;
+
+ bool isValid = true;
+ UIUtils.CurrentWindow.CurrentGraph.ResetNodesLocalVariables();
+ for( int i = 0; i < ports.Count; i++ )
+ {
+ TemplateInputData inputData = m_currentTemplate.InputDataFromId( ports[ i ].PortId );
+ if( ports[ i ].IsConnected )
+ {
+ m_currentDataCollector.ResetInstructions();
+ m_currentDataCollector.ResetVertexInstructions();
+
+ m_currentDataCollector.PortCategory = ports[ i ].Category;
+ string newPortInstruction = ports[ i ].GeneratePortInstructions( ref m_currentDataCollector );
+
+
+ if( m_currentDataCollector.DirtySpecialLocalVariables )
+ {
+ string cleanVariables = m_currentDataCollector.SpecialLocalVariables.Replace( "\t", string.Empty );
+ m_currentDataCollector.AddInstructions( cleanVariables, false );
+ m_currentDataCollector.ClearSpecialLocalVariables();
+ }
+
+ if( m_currentDataCollector.DirtyVertexVariables )
+ {
+ string cleanVariables = m_currentDataCollector.VertexLocalVariables.Replace( "\t", string.Empty );
+ m_currentDataCollector.AddVertexInstruction( cleanVariables, UniqueId, false );
+ m_currentDataCollector.ClearVertexLocalVariables();
+ }
+
+ // fill functions
+ for( int j = 0; j < m_currentDataCollector.InstructionsList.Count; j++ )
+ {
+ fragmentInstructions.Add( m_currentDataCollector.InstructionsList[ j ].PropertyName );
+ }
+
+ for( int j = 0; j < m_currentDataCollector.VertexDataList.Count; j++ )
+ {
+ vertexInstructions.Add( m_currentDataCollector.VertexDataList[ j ].PropertyName );
+ }
+
+ isValid = m_currentTemplate.FillTemplateBody( inputData.TagId, ref shaderBody, newPortInstruction ) && isValid;
+ }
+ else
+ {
+ isValid = m_currentTemplate.FillTemplateBody( inputData.TagId, ref shaderBody, inputData.DefaultValue ) && isValid;
+ }
+ }
+ return isValid;
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ base.Draw( drawInfo );
+
+ if( m_currentTemplate == null )
+ {
+ FetchCurrentTemplate();
+ }
+
+ if( m_reRegisterTemplateData )
+ {
+ RegisterProperties();
+ }
+
+ if( m_containerGraph.IsInstancedShader )
+ {
+ DrawInstancedIcon( drawInfo );
+ }
+
+ if( m_fetchMasterNodeCategory )
+ {
+ if( m_availableCategories != null )
+ {
+ m_fetchMasterNodeCategory = false;
+ SetCategoryIdxFromTemplate();
+ }
+ }
+
+ if( m_fireTemplateChange )
+ {
+ m_fireTemplateChange = false;
+ m_containerGraph.FireMasterNodeReplacedEvent();
+ }
+ }
+
+ public override void UpdateFromShader( Shader newShader )
+ {
+ if( m_currentMaterial != null )
+ {
+ m_currentMaterial.shader = newShader;
+ }
+ CurrentShader = newShader;
+ }
+
+ public override void UpdateMasterNodeMaterial( Material material )
+ {
+ m_currentMaterial = material;
+ FireMaterialChangedEvt();
+ }
+
+ public override Shader Execute( string pathname, bool isFullPath )
+ {
+ if( m_currentTemplate == null )
+ return m_currentShader;
+
+ //Create data collector
+ ForceReordering();
+ base.Execute( pathname, isFullPath );
+
+ SetupNodeCategories();
+
+ m_currentDataCollector.TemplateDataCollectorInstance.BuildFromTemplateData( m_currentDataCollector, m_currentTemplate );
+ int shaderPropertiesAmount = m_currentTemplate.AvailableShaderProperties.Count;
+ for( int i = 0; i < shaderPropertiesAmount; i++ )
+ {
+ m_currentDataCollector.SoftRegisterUniform( m_currentTemplate.AvailableShaderProperties[ i ] );
+ }
+ m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector );
+
+ //Sort ports by both
+ List<InputPort> fragmentPorts = new List<InputPort>();
+ List<InputPort> vertexPorts = new List<InputPort>();
+ SortInputPorts( ref vertexPorts, ref fragmentPorts );
+
+ string shaderBody = m_currentTemplate.TemplateBody;
+
+ List<string> vertexInstructions = new List<string>();
+ List<string> fragmentInstructions = new List<string>();
+
+ bool validBody = true;
+
+ validBody = CreateInstructionsForList( ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+ ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex );
+ validBody = CreateInstructionsForList( ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+
+ m_currentTemplate.ResetTemplateUsageData();
+
+ // Fill vertex interpolators assignment
+ for( int i = 0; i < m_currentDataCollector.VertexInterpDeclList.Count; i++ )
+ {
+ vertexInstructions.Add( m_currentDataCollector.VertexInterpDeclList[ i ] );
+ }
+
+ vertexInstructions.AddRange( m_currentDataCollector.TemplateDataCollectorInstance.GetInterpUnusedChannels() );
+ //Fill common local variables and operations
+
+ validBody = m_currentTemplate.FillVertexInstructions( ref shaderBody, vertexInstructions.ToArray() ) && validBody;
+ validBody = m_currentTemplate.FillFragmentInstructions( ref shaderBody, fragmentInstructions.ToArray() ) && validBody;
+
+ // Add Instanced Properties
+ if( m_containerGraph.IsInstancedShader )
+ {
+ m_currentDataCollector.TabifyInstancedVars();
+ m_currentDataCollector.InstancedPropertiesList.Insert( 0, new PropertyDataCollector( -1, string.Format( IOUtils.InstancedPropertiesBegin, UIUtils.RemoveInvalidCharacters( m_shaderName ) ) ) );
+ m_currentDataCollector.InstancedPropertiesList.Add( new PropertyDataCollector( -1, IOUtils.InstancedPropertiesEnd ) );
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.InstancedPropertiesList );
+ }
+
+ //Add Functions
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.FunctionsList );
+
+ // Fill common tags
+ m_currentDataCollector.IncludesList.AddRange( m_currentDataCollector.PragmasList );
+
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.ShaderNameId, ref shaderBody, string.Format( TemplatesManager.NameFormatter, m_shaderName ) ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePassTag, ref shaderBody, m_currentDataCollector.GrabPassList ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePragmaTag, ref shaderBody, m_currentDataCollector.IncludesList ) && validBody;
+ //validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateTagsTag, ref shaderBody, m_currentDataCollector.TagsList ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplatePropertyTag, ref shaderBody, m_currentDataCollector.BuildUnformatedPropertiesStringArr() ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateGlobalsTag, ref shaderBody, m_currentDataCollector.UniformsList ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.VertexDataId, ref shaderBody, m_currentDataCollector.VertexInputList.ToArray() ) && validBody;
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.InterpDataId, ref shaderBody, m_currentDataCollector.InterpolatorList.ToArray() ) && validBody;
+
+ if( m_currentTemplate.BlendData.ValidBlendMode )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.BlendData.BlendModeId, ref shaderBody, m_blendOpHelper.CurrentBlendFactor ) && validBody;
+ }
+
+ if( m_currentTemplate.BlendData.ValidBlendOp )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.BlendData.BlendOpId, ref shaderBody, m_blendOpHelper.CurrentBlendOp ) && validBody;
+ }
+
+ if( m_currentTemplate.BlendData.ValidAlphaToMask )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.BlendData.AlphaToMaskId, ref shaderBody, m_blendOpHelper.CurrentAlphaToMask ) && validBody;
+ }
+
+ if( m_currentTemplate.DepthData.ValidZWrite )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.ZWriteModeId, ref shaderBody, m_depthOphelper.CurrentZWriteMode ) && validBody;
+ }
+
+ if( m_currentTemplate.DepthData.ValidZTest )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.ZTestModeId, ref shaderBody, m_depthOphelper.CurrentZTestMode ) && validBody;
+ }
+
+ if( m_currentTemplate.DepthData.ValidOffset )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.DepthData.OffsetId, ref shaderBody, m_depthOphelper.CurrentOffset ) && validBody;
+ }
+
+ if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.CullModeData.CullModeId, ref shaderBody, m_cullModeHelper.GenerateShaderData(false) ) && validBody;
+ }
+
+ if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.ColorMaskData.ColorMaskId, ref shaderBody, m_colorMaskHelper.GenerateShaderData( false ) ) && validBody;
+ }
+
+ if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ CullMode cullMode = ( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid ) ? m_cullModeHelper.CurrentCullMode : CullMode.Back;
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.StencilData.StencilBufferId, ref shaderBody, m_stencilBufferHelper.CreateStencilOp( cullMode ) ) && validBody;
+ }
+
+ if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( m_currentTemplate.TagData.TagsId, ref shaderBody, m_tagsHelper.GenerateTags() ) && validBody;
+ }
+
+ if( m_currentDataCollector.TemplateDataCollectorInstance.HasVertexInputParams )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateInputsVertParamsTag, ref shaderBody, m_currentDataCollector.TemplateDataCollectorInstance.VertexInputParamsStr ) && validBody;
+ }
+
+ if( m_currentDataCollector.TemplateDataCollectorInstance.HasFragmentInputParams )
+ {
+ validBody = m_currentTemplate.FillTemplateBody( TemplatesManager.TemplateInputsFragParamsTag, ref shaderBody, m_currentDataCollector.TemplateDataCollectorInstance.FragInputParamsStr ) && validBody;
+ }
+
+ m_currentTemplate.FillEmptyTags( ref shaderBody );
+
+ //m_currentTemplate.InsertSnippets( ref shaderBody );
+
+ vertexInstructions.Clear();
+ vertexInstructions = null;
+
+ fragmentInstructions.Clear();
+ fragmentInstructions = null;
+ if( validBody )
+ {
+ UpdateShaderAsset( ref pathname, ref shaderBody, isFullPath );
+ }
+
+ return m_currentShader;
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ try
+ {
+ ShaderName = GetCurrentParam( ref nodeParams );
+ if( m_shaderName.Length > 0 )
+ ShaderName = UIUtils.RemoveShaderInvalidCharacters( ShaderName );
+
+ string templateGUID = GetCurrentParam( ref nodeParams );
+ string templateShaderName = string.Empty;
+ if( UIUtils.CurrentShaderVersion() > 13601 )
+ {
+ templateShaderName = GetCurrentParam( ref nodeParams );
+ }
+
+ TemplateData template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ) as TemplateData;
+ if( template != null )
+ {
+ SetTemplate( template, false, true );
+ }
+ else
+ {
+ template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplateByName( templateShaderName ) as TemplateData;
+ if( template != null )
+ {
+ SetTemplate( template, false, true );
+ }
+ else
+ {
+ m_masterNodeCategory = -1;
+ }
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 13902 )
+ {
+ //BLEND MODULE
+ if( m_currentTemplate.BlendData.ValidBlendMode )
+ {
+ m_blendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_currentTemplate.BlendData.ValidBlendOp )
+ {
+ m_blendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ //CULL MODE
+ if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_cullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ //COLOR MASK
+ if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_colorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ //STENCIL BUFFER
+ if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_stencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 14202 )
+ {
+ //DEPTH OPTIONS
+ if( m_currentTemplate.DepthData.ValidZWrite )
+ {
+ m_depthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_currentTemplate.DepthData.ValidZTest )
+ {
+ m_depthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_currentTemplate.DepthData.ValidOffset )
+ {
+ m_depthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ }
+
+ //TAGS
+ if( UIUtils.CurrentShaderVersion() > 14301 )
+ {
+ if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid )
+ m_tagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e, this );
+ }
+ m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader;
+ m_containerGraph.CurrentPrecision = m_currentPrecisionType;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderName );
+ IOUtils.AddFieldValueToString( ref nodeInfo, ( m_currentTemplate != null ) ? m_currentTemplate.GUID : string.Empty );
+ IOUtils.AddFieldValueToString( ref nodeInfo, ( m_currentTemplate != null ) ? m_currentTemplate.DefaultShaderName : string.Empty );
+
+ //BLEND MODULE
+ if( m_currentTemplate.BlendData.ValidBlendMode )
+ {
+ m_blendOpHelper.WriteBlendModeToString( ref nodeInfo );
+ }
+
+ if( m_currentTemplate.BlendData.ValidBlendOp )
+ {
+ m_blendOpHelper.WriteBlendOpToString( ref nodeInfo );
+ }
+
+ //CULL MODULE
+ if( m_currentTemplate.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_cullModeHelper.WriteToString( ref nodeInfo );
+ }
+
+ //COLOR MASK MODULE
+ if( m_currentTemplate.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_colorMaskHelper.WriteToString( ref nodeInfo );
+ }
+
+ //STENCIL BUFFER MODULE
+ if( m_currentTemplate.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_stencilBufferHelper.WriteToString( ref nodeInfo );
+ }
+
+ //DEPTH MODULE
+ if( m_currentTemplate.DepthData.ValidZWrite )
+ {
+ m_depthOphelper.WriteZWriteToString( ref nodeInfo );
+ }
+
+ if( m_currentTemplate.DepthData.ValidZTest )
+ {
+ m_depthOphelper.WriteZTestToString( ref nodeInfo );
+ }
+
+ if( m_currentTemplate.DepthData.ValidOffset )
+ {
+ m_depthOphelper.WriteOffsetToString( ref nodeInfo );
+ }
+
+ //TAGS
+ if( m_currentTemplate.TagData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_tagsHelper.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_currentTemplate = null;
+ m_blendOpHelper = null;
+ m_cullModeHelper = null;
+ m_colorMaskHelper.Destroy();
+ m_colorMaskHelper = null;
+ m_stencilBufferHelper.Destroy();
+ m_stencilBufferHelper = null;
+ m_tagsHelper.Destroy();
+ m_tagsHelper = null;
+
+ }
+
+ public TemplateData CurrentTemplate { get { return m_currentTemplate; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta
new file mode 100644
index 00000000..b17058f3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMasterNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8bbd856408a816448a2686501df37397
+timeCreated: 1493905112
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs
new file mode 100644
index 00000000..920dc274
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs
@@ -0,0 +1,50 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ public class TemplateMenuItems
+ {
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Unlit", false, 85 )]
+ public static void ApplyTemplateLegacyUnlit()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0770190933193b94aaa3065e307002fa" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Post Process", false, 85 )]
+ public static void ApplyTemplateLegacyPostProcess()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "c71b220b631b6344493ea3cf87110c93" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Deprecated/Legacy/Default Unlit", false, 85 )]
+ public static void ApplyTemplateDeprecatedLegacyDefaultUnlit()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "6e114a916ca3e4b4bb51972669d463bf" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Default UI", false, 85 )]
+ public static void ApplyTemplateLegacyDefaultUI()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "5056123faa0c79b47ab6ad7e8bf059a4" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Unlit Lightmap", false, 85 )]
+ public static void ApplyTemplateLegacyUnlitLightmap()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "899e609c083c74c4ca567477c39edef0" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Default Sprites", false, 85 )]
+ public static void ApplyTemplateLegacyDefaultSprites()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0f8ba0101102bb14ebf021ddadce9b49" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Particles Alpha Blended", false, 85 )]
+ public static void ApplyTemplateLegacyParticlesAlphaBlended()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "0b6a9f8b4f707c74ca64c0be8e590de0" );
+ }
+ [MenuItem( "Assets/Create/Amplify Shader/Legacy/Multi Pass Unlit", false, 85 )]
+ public static void ApplyTemplateLegacyMultiPassUnlit()
+ {
+ AmplifyShaderEditorWindow.CreateConfirmationTemplateShader( "e1de45c0d41f68c41b2cc20c8b9c05ef" );
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta
new file mode 100644
index 00000000..69a390bc
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMenuItems.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: da0b931bd234a1e43b65f684d4b59bfb
+timeCreated: 1496736284
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs
new file mode 100644
index 00000000..147fee0b
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs
@@ -0,0 +1,497 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+
+ [Serializable]
+ public class TemplateModulesHelper
+ {
+ [SerializeField]
+ internal bool Foldout = false;
+
+ private bool m_isDirty = false;
+
+ [SerializeField]
+ private TemplatesBlendModule m_blendOpHelper = new TemplatesBlendModule();
+
+ [SerializeField]
+ private TemplateCullModeModule m_cullModeHelper = new TemplateCullModeModule();
+
+ [SerializeField]
+ private TemplateColorMaskModule m_colorMaskHelper = new TemplateColorMaskModule();
+
+ [SerializeField]
+ private TemplatesStencilBufferModule m_stencilBufferHelper = new TemplatesStencilBufferModule();
+
+ [SerializeField]
+ private TemplateDepthModule m_depthOphelper = new TemplateDepthModule();
+
+ [SerializeField]
+ private TemplateTagsModule m_tagsHelper = new TemplateTagsModule();
+
+ [SerializeField]
+ private TemplateShaderModelModule m_shaderModelHelper = new TemplateShaderModelModule();
+
+ [SerializeField]
+ private TemplateAdditionalIncludesHelper m_additionalIncludes = new TemplateAdditionalIncludesHelper();
+
+ [SerializeField]
+ private TemplateAdditionalDefinesHelper m_additionalDefines = new TemplateAdditionalDefinesHelper();
+
+ [SerializeField]
+ private TemplateAdditionalPragmasHelper m_additionalPragmas = new TemplateAdditionalPragmasHelper();
+
+ [SerializeField]
+ private TemplateAdditionalDirectivesHelper m_additionalDirectives = new TemplateAdditionalDirectivesHelper(" Additional Directives");
+
+ [SerializeField]
+ private bool m_hasValidData = false;
+
+ [SerializeField]
+ private bool m_allModulesMode = false;
+
+ public void CopyFrom( TemplateModulesHelper other )
+ {
+ m_allModulesMode = other.AllModulesMode;
+
+ if( other.BlendOpHelper.IsDirty )
+ {
+ m_blendOpHelper.CopyFrom( other.BlendOpHelper, true );
+ }
+
+ if( other.CullModeHelper.IsDirty )
+ {
+ m_cullModeHelper.CopyFrom( other.CullModeHelper , true );
+ }
+
+ if( other.ColorMaskHelper.IsDirty )
+ {
+ m_colorMaskHelper.CopyFrom( other.ColorMaskHelper , true);
+ }
+
+ if( other.StencilBufferHelper.IsDirty )
+ {
+ m_stencilBufferHelper.CopyFrom( other.StencilBufferHelper,true );
+ }
+
+ if( other.DepthOphelper.IsDirty )
+ {
+ m_depthOphelper.CopyFrom( other.DepthOphelper,true );
+ }
+
+ if( other.TagsHelper.IsDirty )
+ {
+ m_tagsHelper.CopyFrom( other.TagsHelper );
+ }
+
+ if( other.ShaderModelHelper.IsDirty )
+ {
+ m_shaderModelHelper.CopyFrom( other.ShaderModelHelper, true );
+ }
+ }
+
+ public void SyncWith( TemplateModulesHelper other )
+ {
+
+ if( m_blendOpHelper.ValidData && other.BlendOpHelper.ValidData )
+ {
+ m_blendOpHelper.CopyFrom( other.BlendOpHelper, false );
+ }
+
+ if( m_cullModeHelper.ValidData && other.CullModeHelper.ValidData )
+ {
+ m_cullModeHelper.CopyFrom( other.CullModeHelper, false );
+ }
+
+ if( m_colorMaskHelper.ValidData && other.ColorMaskHelper.ValidData )
+ {
+ m_colorMaskHelper.CopyFrom( other.ColorMaskHelper , false );
+ }
+
+ if( m_stencilBufferHelper.ValidData && other.StencilBufferHelper.ValidData )
+ {
+ m_stencilBufferHelper.CopyFrom( other.StencilBufferHelper, false );
+ }
+
+ if( m_depthOphelper.ValidData && other.DepthOphelper.ValidData )
+ {
+ m_depthOphelper.CopyFrom( other.DepthOphelper, false );
+ }
+
+ if( m_shaderModelHelper.ValidData && other.ShaderModelHelper.ValidData )
+ {
+ m_shaderModelHelper.CopyFrom( other.ShaderModelHelper , false);
+ }
+ }
+
+ public void FetchDataFromTemplate( TemplateModulesData module )
+ {
+ m_allModulesMode = module.AllModulesMode;
+
+ if( module.PragmaTag.IsValid )
+ {
+ m_hasValidData = true;
+ //m_additionalPragmas.IsValid = true;
+ //m_additionalPragmas.FillNativeItems( module.IncludePragmaContainer.PragmasList );
+
+ //m_additionalIncludes.IsValid = true;
+ //m_additionalIncludes.FillNativeItems( module.IncludePragmaContainer.IncludesList );
+
+ //m_additionalDefines.IsValid = true;
+ //m_additionalDefines.FillNativeItems( module.IncludePragmaContainer.DefinesList );
+
+ m_additionalDirectives.FillNativeItems( module.IncludePragmaContainer.NativeDirectivesList );
+ m_additionalDirectives.IsValid = true;
+ }
+ else
+ {
+ //m_additionalPragmas.IsValid = false;
+ //m_additionalIncludes.IsValid = false;
+ //m_additionalDefines.IsValid = false;
+ m_additionalDirectives.IsValid = false;
+ }
+
+ m_blendOpHelper.ConfigureFromTemplateData( module.BlendData );
+ if( module.BlendData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_cullModeHelper.ConfigureFromTemplateData( module.CullModeData );
+ if( module.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_colorMaskHelper.ConfigureFromTemplateData( module.ColorMaskData );
+ if( module.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_stencilBufferHelper.ConfigureFromTemplateData( module.StencilData );
+ if( module.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_depthOphelper.ConfigureFromTemplateData( module.DepthData );
+ if( module.DepthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_tagsHelper.ConfigureFromTemplateData( module.TagData );
+ if( module.TagData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+
+ m_shaderModelHelper.ConfigureFromTemplateData( module.ShaderModel );
+ if( module.ShaderModel.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_hasValidData = true;
+ }
+ }
+
+ public void OnLogicUpdate( TemplateModulesData currentModule )
+ {
+ if( currentModule.TagData.DataCheck == TemplateDataCheck.Valid )
+ m_tagsHelper.OnLogicUpdate();
+ }
+
+ public void Draw( ParentNode owner, TemplateModulesData currentModule , TemplateModulesHelper parent = null )
+ {
+ if( currentModule.ShaderModel.DataCheck == TemplateDataCheck.Valid )
+ m_shaderModelHelper.Draw( owner );
+
+ m_isDirty = m_shaderModelHelper.IsDirty;
+
+ if( currentModule.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ m_cullModeHelper.Draw( owner );
+
+ m_isDirty = m_isDirty || m_cullModeHelper.IsDirty;
+
+ if( currentModule.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ m_colorMaskHelper.Draw( owner );
+
+ m_isDirty = m_isDirty || m_colorMaskHelper.IsDirty;
+
+ if( currentModule.DepthData.DataCheck == TemplateDataCheck.Valid )
+ m_depthOphelper.Draw( owner, false );
+
+ m_isDirty = m_isDirty || m_depthOphelper.IsDirty;
+
+ if( currentModule.BlendData.DataCheck == TemplateDataCheck.Valid )
+ m_blendOpHelper.Draw( owner, false );
+
+ m_isDirty = m_isDirty || m_blendOpHelper.IsDirty;
+
+
+ if( currentModule.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ CullMode cullMode = CullMode.Back;
+ if( currentModule.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ cullMode = m_cullModeHelper.CurrentCullMode;
+ }
+ else if( parent != null && parent.CullModeHelper.ValidData )
+ {
+ cullMode = parent.CullModeHelper.CurrentCullMode;
+ }
+ m_stencilBufferHelper.Draw( owner, cullMode, false );
+ }
+
+ m_isDirty = m_isDirty || m_stencilBufferHelper.IsDirty;
+
+ if( currentModule.TagData.DataCheck == TemplateDataCheck.Valid )
+ m_tagsHelper.Draw( owner, false );
+
+ m_isDirty = m_isDirty || m_tagsHelper.IsDirty;
+
+ if( currentModule.PragmaTag.IsValid )
+ {
+ //m_additionalDefines.Draw( owner );
+ //m_additionalIncludes.Draw( owner );
+ //m_additionalPragmas.Draw( owner );
+ m_additionalDirectives.Draw( owner , false);
+ }
+
+ m_isDirty = m_isDirty ||
+ //m_additionalDefines.IsDirty ||
+ //m_additionalIncludes.IsDirty ||
+ //m_additionalPragmas.IsDirty ||
+ m_additionalDirectives.IsDirty;
+ }
+
+ public void Destroy()
+ {
+ m_shaderModelHelper = null;
+ m_blendOpHelper = null;
+ m_cullModeHelper = null;
+ m_colorMaskHelper.Destroy();
+ m_colorMaskHelper = null;
+ m_stencilBufferHelper.Destroy();
+ m_stencilBufferHelper = null;
+ m_tagsHelper.Destroy();
+ m_tagsHelper = null;
+ m_additionalDefines.Destroy();
+ m_additionalDefines = null;
+ m_additionalIncludes.Destroy();
+ m_additionalIncludes = null;
+ m_additionalPragmas.Destroy();
+ m_additionalPragmas = null;
+ m_additionalDirectives.Destroy();
+ m_additionalDirectives = null;
+ }
+
+ public string GenerateAllModulesString( bool isSubShader )
+ {
+ string moduleBody = string.Empty;
+ if( !ShaderModelHelper.IndependentModule )
+ {
+ moduleBody += ShaderModelHelper.GenerateShaderData( isSubShader ) + "\n";
+ }
+
+ if( !BlendOpHelper.IndependentModule )
+ {
+ if( BlendOpHelper.BlendModeEnabled )
+ moduleBody += BlendOpHelper.CurrentBlendFactor + "\n";
+
+ if( BlendOpHelper.BlendOpActive )
+ moduleBody += BlendOpHelper.CurrentBlendOp + "\n";
+
+ }
+
+ if( !BlendOpHelper.AlphaToMaskIndependent )
+ {
+ if( BlendOpHelper.ValidAlphaToMask && BlendOpHelper.AlphaToMaskValue )
+ moduleBody += BlendOpHelper.CurrentAlphaToMask + "\n";
+ }
+
+ if( !CullModeHelper.IndependentModule )
+ moduleBody += CullModeHelper.GenerateShaderData( isSubShader ) + "\n";
+
+ if( !ColorMaskHelper.IndependentModule )
+ moduleBody += ColorMaskHelper.GenerateShaderData( isSubShader ) + "\n";
+
+ if( !DepthOphelper.IndependentModule )
+ {
+ moduleBody += DepthOphelper.CurrentZWriteMode;
+ moduleBody += DepthOphelper.CurrentZTestMode;
+ if( DepthOphelper.OffsetEnabled )
+ moduleBody += DepthOphelper.CurrentOffset;
+ }
+
+ if( !StencilBufferHelper.IndependentModule && StencilBufferHelper.Active )
+ {
+ CullMode cullMode = ( CullModeHelper.ValidData ) ? CullModeHelper.CurrentCullMode : CullMode.Back;
+ moduleBody += StencilBufferHelper.CreateStencilOp( cullMode );
+ }
+
+ return moduleBody;
+ }
+
+ public void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ try
+ {
+ m_blendOpHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_cullModeHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_colorMaskHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_stencilBufferHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_depthOphelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_tagsHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_shaderModelHelper.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+
+ if( UIUtils.CurrentShaderVersion() < 15312 )
+ {
+ try
+ {
+ m_additionalDefines.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_additionalPragmas.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ try
+ {
+ m_additionalIncludes.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ m_additionalDirectives.AddItems( AdditionalLineType.Include, m_additionalIncludes.ItemsList );
+ m_additionalDirectives.AddItems( AdditionalLineType.Define, m_additionalDefines.ItemsList );
+ m_additionalDirectives.AddItems( AdditionalLineType.Pragma, m_additionalPragmas.ItemsList );
+
+ }
+ else
+ {
+ try
+ {
+ m_additionalDirectives.ReadFromString( ref index, ref nodeParams );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ }
+
+ public void WriteToString( ref string nodeInfo )
+ {
+ m_blendOpHelper.WriteToString( ref nodeInfo );
+ m_cullModeHelper.WriteToString( ref nodeInfo );
+ m_colorMaskHelper.WriteToString( ref nodeInfo );
+ m_stencilBufferHelper.WriteToString( ref nodeInfo );
+ m_depthOphelper.WriteToString( ref nodeInfo );
+ m_tagsHelper.WriteToString( ref nodeInfo );
+ m_shaderModelHelper.WriteToString( ref nodeInfo );
+
+ //m_additionalDefines.WriteToString( ref nodeInfo );
+ //m_additionalPragmas.WriteToString( ref nodeInfo );
+ //m_additionalIncludes.WriteToString( ref nodeInfo );
+
+ m_additionalDirectives.WriteToString( ref nodeInfo );
+ }
+
+ public TemplatesBlendModule BlendOpHelper { get { return m_blendOpHelper; } }
+ public TemplateCullModeModule CullModeHelper { get { return m_cullModeHelper; } }
+ public TemplateColorMaskModule ColorMaskHelper { get { return m_colorMaskHelper; } }
+ public TemplatesStencilBufferModule StencilBufferHelper { get { return m_stencilBufferHelper; } }
+ public TemplateDepthModule DepthOphelper { get { return m_depthOphelper; } }
+ public TemplateTagsModule TagsHelper { get { return m_tagsHelper; } }
+ public TemplateShaderModelModule ShaderModelHelper { get { return m_shaderModelHelper; } }
+ //public TemplateAdditionalIncludesHelper AdditionalIncludes { get { return m_additionalIncludes; } }
+ //public TemplateAdditionalDefinesHelper AdditionalDefines { get { return m_additionalDefines; } }
+ //public TemplateAdditionalPragmasHelper AdditionalPragmas { get { return m_additionalPragmas; } }
+ public TemplateAdditionalDirectivesHelper AdditionalDirectives { get { return m_additionalDirectives; } }
+ public bool AllModulesMode { get { return m_allModulesMode; } }
+ public bool HasValidData { get { return m_hasValidData; } }
+ public bool IsDirty
+ {
+ get { return m_isDirty; }
+ set
+ {
+ m_isDirty = value;
+ if( !value )
+ {
+ m_blendOpHelper.IsDirty = false;
+ m_cullModeHelper.IsDirty = false;
+ m_colorMaskHelper.IsDirty = false;
+ m_stencilBufferHelper.IsDirty = false;
+ m_tagsHelper.IsDirty = false;
+ m_shaderModelHelper.IsDirty = false;
+ //m_additionalDefines.IsDirty = false;
+ //m_additionalPragmas.IsDirty = false;
+ //m_additionalIncludes.IsDirty = false;
+ m_additionalDirectives.IsDirty = false;
+ }
+ }
+ }
+ // public bool Foldout { get { return m_foldout; } set { m_foldout = value; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta
new file mode 100644
index 00000000..95ebce97
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 144af5a201bd97542bf3a483976759db
+timeCreated: 1518705839
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs
new file mode 100644
index 00000000..cb28c2f3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs
@@ -0,0 +1,62 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateModuleParent
+ {
+ private const string UnreadableDataMessagePrefix = "Unreadable data on Module ";
+ protected string m_unreadableMessage;
+
+ [SerializeField]
+ protected bool m_validData = false;
+
+ [SerializeField]
+ protected bool m_isDirty = false;
+
+ [SerializeField]
+ protected string m_moduleName = string.Empty;
+
+ //[SerializeField]
+ //protected bool m_foldoutValue = false;
+
+ [SerializeField]
+ protected bool m_independentModule = true;
+
+ public TemplateModuleParent( string moduleName ) { m_moduleName = moduleName; m_unreadableMessage = UnreadableDataMessagePrefix + moduleName; }
+ public virtual void Draw( UndoParentNode owner , bool style = true) { }
+ public virtual void ReadFromString( ref uint index, ref string[] nodeParams ) { }
+ public virtual void WriteToString( ref string nodeInfo ) { }
+ public virtual string GenerateShaderData( bool isSubShader ) { return string.Empty; }
+ public virtual void Destroy() { }
+ public bool ValidData { get { return m_validData; } }
+ public bool ValidAndIndependent { get { return m_validData && m_independentModule; } }
+
+ public virtual void ShowUnreadableDataMessage( ParentNode owner )
+ {
+ ShowUnreadableDataMessage();
+ }
+
+ public virtual void ShowUnreadableDataMessage()
+ {
+ EditorGUILayout.HelpBox( m_unreadableMessage, MessageType.Info );
+ }
+
+ public bool IsDirty
+ {
+ get { return m_isDirty; }
+ set { m_isDirty = value; }
+ }
+
+ public bool IndependentModule
+ {
+ get { return m_independentModule; }
+ set { m_independentModule = value; }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta
new file mode 100644
index 00000000..a0a1d88c
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModuleParent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3aaabf1f5cb06414a8be17a89487e10f
+timeCreated: 1511185965
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs
new file mode 100644
index 00000000..5cbc9a7b
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs
@@ -0,0 +1,541 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ public enum TemplateModuleDataType
+ {
+ ModuleShaderModel,
+ ModuleBlendMode,
+ ModuleBlendOp,
+ ModuleAlphaToMask,
+ ModuleCullMode,
+ ModuleColorMask,
+ ModuleStencil,
+ ModuleZwrite,
+ ModuleZTest,
+ ModuleZOffset,
+ ModuleTag,
+ ModuleGlobals,
+ ModuleSRPBatcher,
+ ModuleFunctions,
+ ModulePragma,
+ ModulePragmaBefore,
+ ModulePass,
+ ModuleInputVert,
+ ModuleInputFrag,
+ PassVertexFunction,
+ PassFragmentFunction,
+ PassVertexData,
+ PassInterpolatorData,
+ PassNameData,
+ AllModules,
+ VControl,
+ ControlData,
+ DomainData
+ //EndPass
+ }
+
+ public enum TemplateSRPType
+ {
+ BuiltIn,
+ HD,
+ Lightweight
+ }
+
+ [Serializable]
+ public class TemplateModulesData
+ {
+ [SerializeField]
+ private TemplateBlendData m_blendData = new TemplateBlendData();
+
+ [SerializeField]
+ private TemplateCullModeData m_cullModeData = new TemplateCullModeData();
+
+ [SerializeField]
+ private TemplateColorMaskData m_colorMaskData = new TemplateColorMaskData();
+
+ [SerializeField]
+ private TemplateStencilData m_stencilData = new TemplateStencilData();
+
+ [SerializeField]
+ private TemplateDepthData m_depthData = new TemplateDepthData();
+
+ [SerializeField]
+ private TemplateTagsModuleData m_tagData = new TemplateTagsModuleData();
+
+ [SerializeField]
+ private TemplateTagData m_globalsTag = new TemplateTagData( TemplatesManager.TemplateGlobalsTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_srpBatcherTag = new TemplateTagData( TemplatesManager.TemplateSRPBatcherTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_allModulesTag = new TemplateTagData( TemplatesManager.TemplateAllModulesTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_functionsTag = new TemplateTagData( TemplatesManager.TemplateFunctionsTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_pragmaTag = new TemplateTagData( TemplatesManager.TemplatePragmaTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_pragmaBeforeTag = new TemplateTagData( TemplatesManager.TemplatePragmaBeforeTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_passTag = new TemplateTagData( TemplatesManager.TemplatePassTag, true );
+
+ [SerializeField]
+ private TemplateTagData m_inputsVertTag = new TemplateTagData( TemplatesManager.TemplateInputsVertParamsTag, false );
+
+ [SerializeField]
+ private TemplateTagData m_inputsFragTag = new TemplateTagData( TemplatesManager.TemplateInputsFragParamsTag, false );
+
+ [SerializeField]
+ private TemplateShaderModelData m_shaderModel = new TemplateShaderModelData();
+
+ [SerializeField]
+ private TemplateSRPType m_srpType = TemplateSRPType.BuiltIn;
+
+ [SerializeField]
+ private bool m_srpIsPBR = false;
+
+ [SerializeField]
+ private string m_uniquePrefix;
+
+ [SerializeField]
+ private TemplateIncludePragmaContainter m_includePragmaContainer = new TemplateIncludePragmaContainter();
+
+ [SerializeField]
+ private bool m_allModulesMode = false;
+
+ [SerializeField]
+ private string m_passUniqueName = string.Empty;
+
+ public void Destroy()
+ {
+ m_blendData = null;
+ m_cullModeData = null;
+ m_colorMaskData = null;
+ m_stencilData = null;
+ m_depthData = null;
+ m_tagData.Destroy();
+ m_tagData = null;
+ m_globalsTag = null;
+ m_srpBatcherTag = null;
+ m_allModulesTag = null;
+ m_functionsTag = null;
+ m_pragmaTag = null;
+ m_pragmaBeforeTag = null;
+ m_passTag = null;
+ m_inputsVertTag = null;
+ m_inputsFragTag = null;
+ m_includePragmaContainer.Destroy();
+ m_includePragmaContainer = null;
+ }
+
+ public void ConfigureCommonTag( TemplateTagData tagData, TemplatePropertyContainer propertyContainer, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, string subBody )
+ {
+ int id = subBody.IndexOf( tagData.Id );
+ if ( id >= 0 )
+ {
+ tagData.StartIdx = offsetIdx + id;
+ idManager.RegisterId( tagData.StartIdx, uniquePrefix + tagData.Id, tagData.Id );
+ propertyContainer.AddId( subBody, tagData.Id, tagData.SearchIndentation );
+ }
+ }
+
+ public TemplateModulesData( TemplateOptionsContainer optionsContainer, TemplateIdManager idManager, TemplatePropertyContainer propertyContainer, string uniquePrefix, int offsetIdx, string subBody, bool isSubShader )
+ {
+ if ( string.IsNullOrEmpty( subBody ) )
+ return;
+
+ m_uniquePrefix = uniquePrefix;
+ //PRAGMAS AND INCLUDES
+ TemplateHelperFunctions.CreatePragmaIncludeList( subBody, m_includePragmaContainer );
+
+ //COMMON TAGS
+ ConfigureCommonTag( m_globalsTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ ConfigureCommonTag( m_srpBatcherTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ ConfigureCommonTag( m_functionsTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ ConfigureCommonTag( m_pragmaTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ ConfigureCommonTag( m_pragmaBeforeTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ if( !TemplateHelperFunctions.GetPassUniqueId( m_passTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody, ref m_passUniqueName ) )
+ {
+ ConfigureCommonTag( m_passTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ }
+ ConfigureCommonTag( m_inputsVertTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ ConfigureCommonTag( m_inputsFragTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+
+ // If Options are enabled then remove them so they won't influence Regex matches
+ if( optionsContainer.Enabled && optionsContainer.EndIndex > 0 )
+ {
+ offsetIdx += optionsContainer.EndIndex;
+ subBody = subBody.Substring( optionsContainer.EndIndex );
+ }
+ //BlEND MODE
+ {
+ Match blendModeMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendWholeWordPattern );
+ if( blendModeMatch.Success )
+ {
+ int blendModeIdx = blendModeMatch.Index;
+
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendModeIdx );
+ string blendParams = subBody.Substring( blendModeIdx, end - blendModeIdx );
+ m_blendData.BlendModeId = blendParams;
+ m_blendData.BlendModeStartIndex = offsetIdx + blendModeIdx;
+ idManager.RegisterId( m_blendData.BlendModeStartIndex, uniquePrefix + m_blendData.BlendModeId, m_blendData.BlendModeId );
+
+ TemplateHelperFunctions.CreateBlendMode( blendParams, ref m_blendData );
+ if( m_blendData.ValidBlendMode )
+ {
+ propertyContainer.AddId( subBody, blendParams, false );
+ }
+
+ }
+ }
+ //BLEND OP
+ {
+ Match blendOpMatch = Regex.Match( subBody, TemplateHelperFunctions.BlendOpWholeWordPattern );
+ if( blendOpMatch.Success )
+ {
+ int blendOpIdx = blendOpMatch.Index;
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, blendOpIdx );
+ string blendOpParams = subBody.Substring( blendOpIdx, end - blendOpIdx );
+ m_blendData.BlendOpId = blendOpParams;
+ BlendData.BlendOpStartIndex = offsetIdx + blendOpIdx;
+ idManager.RegisterId( m_blendData.BlendOpStartIndex, uniquePrefix + m_blendData.BlendOpId, m_blendData.BlendOpId );
+ TemplateHelperFunctions.CreateBlendOp( blendOpParams, ref m_blendData );
+ if( m_blendData.ValidBlendOp )
+ {
+ propertyContainer.AddId( subBody, blendOpParams, false );
+ }
+ }
+
+ }
+
+ //ALPHA TO MASK
+ {
+ Match alphaToMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.AlphaToMaskPattern );
+ if( alphaToMaskMatch.Success )
+ {
+ m_blendData.ValidAlphaToMask = true;
+ m_blendData.AlphaToMaskId = alphaToMaskMatch.Groups[ 0 ].Value;
+ if( alphaToMaskMatch.Groups.Count > 1 )
+ m_blendData.AlphaToMaskValue = alphaToMaskMatch.Groups[ 1 ].Value.Equals( "On" ) ? true : false;
+ m_blendData.IndependentAlphaToMask = true;
+ idManager.RegisterId( offsetIdx + alphaToMaskMatch.Index, uniquePrefix + m_blendData.AlphaToMaskId, m_blendData.AlphaToMaskId );
+ propertyContainer.AddId( subBody, m_blendData.AlphaToMaskId, false );
+ }
+
+ m_blendData.DataCheck = ( m_blendData.ValidBlendMode || m_blendData.ValidBlendOp || m_blendData.ValidAlphaToMask ) ? TemplateDataCheck.Valid : TemplateDataCheck.Invalid;
+ }
+
+ //CULL MODE
+ {
+ Match cullMatch = Regex.Match( subBody, TemplateHelperFunctions.CullWholeWordPattern );
+ if( cullMatch.Success )
+ {
+ int cullIdx = cullMatch.Index;
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, cullIdx );
+ string cullParams = subBody.Substring( cullIdx, end - cullIdx );
+ m_cullModeData.CullModeId = cullParams;
+ m_cullModeData.StartIdx = offsetIdx + cullIdx;
+ idManager.RegisterId( m_cullModeData.StartIdx, uniquePrefix + m_cullModeData.CullModeId, m_cullModeData.CullModeId );
+ TemplateHelperFunctions.CreateCullMode( cullParams, ref m_cullModeData );
+ if( m_cullModeData.DataCheck == TemplateDataCheck.Valid )
+ propertyContainer.AddId( subBody, cullParams, false, string.Empty );
+
+ }
+ }
+ //COLOR MASK
+ {
+ Match colorMaskMatch = Regex.Match( subBody, TemplateHelperFunctions.ColorMaskWholeWordPattern );
+ if( colorMaskMatch.Success )
+ {
+ int colorMaskIdx = colorMaskMatch.Index;
+ int end = subBody.IndexOf( TemplatesManager.TemplateNewLine, colorMaskIdx );
+ string colorMaskParams = subBody.Substring( colorMaskIdx, end - colorMaskIdx );
+ m_colorMaskData.ColorMaskId = colorMaskParams;
+ m_colorMaskData.StartIdx = offsetIdx + colorMaskIdx;
+ idManager.RegisterId( m_colorMaskData.StartIdx, uniquePrefix + m_colorMaskData.ColorMaskId, m_colorMaskData.ColorMaskId );
+ TemplateHelperFunctions.CreateColorMask( colorMaskParams, ref m_colorMaskData );
+ if( m_colorMaskData.DataCheck == TemplateDataCheck.Valid )
+ propertyContainer.AddId( subBody, colorMaskParams, false );
+
+ }
+ }
+ //STENCIL
+ {
+ Match stencilMatch = Regex.Match( subBody, TemplateHelperFunctions.StencilWholeWordPattern );
+ if( stencilMatch.Success )
+ {
+ int stencilIdx = stencilMatch.Index;
+ int stencilEndIdx = subBody.IndexOf( "}", stencilIdx );
+ if( stencilEndIdx > 0 )
+ {
+ string stencilParams = subBody.Substring( stencilIdx, stencilEndIdx + 1 - stencilIdx );
+ m_stencilData.StencilBufferId = stencilParams;
+ m_stencilData.StartIdx = offsetIdx + stencilIdx;
+ idManager.RegisterId( m_stencilData.StartIdx, uniquePrefix + m_stencilData.StencilBufferId, m_stencilData.StencilBufferId );
+ TemplateHelperFunctions.CreateStencilOps( stencilParams, ref m_stencilData );
+ if( m_stencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ propertyContainer.AddId( subBody, stencilParams, true );
+ }
+ }
+ }
+ else
+ {
+ int stencilTagIdx = subBody.IndexOf( TemplatesManager.TemplateStencilTag );
+ if( stencilTagIdx > -1 )
+ {
+ m_stencilData.SetIndependentDefault();
+ m_stencilData.StencilBufferId = TemplatesManager.TemplateStencilTag;
+ m_stencilData.StartIdx = offsetIdx + stencilTagIdx;
+ idManager.RegisterId( m_stencilData.StartIdx, uniquePrefix + m_stencilData.StencilBufferId, m_stencilData.StencilBufferId );
+ propertyContainer.AddId( subBody, m_stencilData.StencilBufferId, true );
+ }
+ }
+ }
+ //ZWRITE
+ {
+ Match zWriteMatch = Regex.Match( subBody, TemplateHelperFunctions.ZWriteWholeWordPattern );
+ if( zWriteMatch.Success )
+ {
+ int zWriteOpIdx = zWriteMatch.Index;
+ int zWriteEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zWriteOpIdx );
+ if( zWriteEndIdx > 0 )
+ {
+ m_depthData.ZWriteModeId = subBody.Substring( zWriteOpIdx, zWriteEndIdx + 1 - zWriteOpIdx );
+ m_depthData.ZWriteStartIndex = offsetIdx + zWriteOpIdx;
+ idManager.RegisterId( m_depthData.ZWriteStartIndex, uniquePrefix + m_depthData.ZWriteModeId, m_depthData.ZWriteModeId );
+ TemplateHelperFunctions.CreateZWriteMode( m_depthData.ZWriteModeId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ propertyContainer.AddId( subBody, m_depthData.ZWriteModeId, true );
+ }
+ }
+ }
+ }
+
+ //ZTEST
+ {
+ Match zTestMatch = Regex.Match( subBody, TemplateHelperFunctions.ZTestWholeWordPattern );
+ if( zTestMatch.Success )
+ {
+ int zTestOpIdx = zTestMatch.Index;
+ int zTestEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zTestOpIdx );
+ if( zTestEndIdx > 0 )
+ {
+ m_depthData.ZTestModeId = subBody.Substring( zTestOpIdx, zTestEndIdx + 1 - zTestOpIdx );
+ m_depthData.ZTestStartIndex = offsetIdx + zTestOpIdx;
+ idManager.RegisterId( m_depthData.ZTestStartIndex, uniquePrefix + m_depthData.ZTestModeId, m_depthData.ZTestModeId );
+ TemplateHelperFunctions.CreateZTestMode( m_depthData.ZTestModeId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ propertyContainer.AddId( subBody, m_depthData.ZTestModeId, true );
+ }
+ }
+ }
+ }
+
+ //ZOFFSET
+ {
+ Match zOffsetMatch = Regex.Match( subBody, TemplateHelperFunctions.ZOffsetWholeWordPattern );
+ if( zOffsetMatch.Success )
+ {
+ int zOffsetIdx = zOffsetMatch.Index;
+ int zOffsetEndIdx = subBody.IndexOf( TemplatesManager.TemplateNewLine, zOffsetIdx );
+ if( zOffsetEndIdx > 0 )
+ {
+ m_depthData.OffsetId = subBody.Substring( zOffsetIdx, zOffsetEndIdx + 1 - zOffsetIdx );
+ m_depthData.OffsetStartIndex = offsetIdx + zOffsetIdx;
+ idManager.RegisterId( m_depthData.OffsetStartIndex, uniquePrefix + m_depthData.OffsetId, m_depthData.OffsetId );
+ TemplateHelperFunctions.CreateZOffsetMode( m_depthData.OffsetId, ref m_depthData );
+ if( m_depthData.DataCheck == TemplateDataCheck.Valid )
+ {
+ propertyContainer.AddId( subBody, m_depthData.OffsetId, true );
+ }
+ }
+ }
+ m_depthData.SetDataCheck();
+ }
+ //TAGS
+ {
+ Match tagsMatch = Regex.Match( subBody, TemplateHelperFunctions.TagsWholeWordPattern );
+ if ( tagsMatch.Success )
+ {
+ int tagsIdx = tagsMatch.Index;
+ int tagsEndIdx = subBody.IndexOf( "}", tagsIdx );
+ if ( tagsEndIdx > -1 )
+ {
+ m_tagData.Reset();
+ m_tagData.TagsId = subBody.Substring( tagsIdx, tagsEndIdx + 1 - tagsIdx );
+ m_tagData.StartIdx = offsetIdx + tagsIdx;
+ idManager.RegisterId( m_tagData.StartIdx, uniquePrefix + m_tagData.TagsId, m_tagData.TagsId );
+ m_srpType = TemplateHelperFunctions.CreateTags( ref m_tagData, isSubShader );
+
+ propertyContainer.AddId( subBody, m_tagData.TagsId, false );
+ m_tagData.DataCheck = TemplateDataCheck.Valid;
+ }
+ else
+ {
+ m_tagData.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ else
+ {
+ m_tagData.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+
+ //SHADER MODEL
+ {
+ Match match = Regex.Match( subBody, TemplateHelperFunctions.ShaderModelPattern );
+ if ( match != null && match.Groups.Count > 1 )
+ {
+ if ( TemplateHelperFunctions.AvailableInterpolators.ContainsKey( match.Groups[ 1 ].Value ) )
+ {
+ m_shaderModel.Id = match.Groups[ 0 ].Value;
+ m_shaderModel.StartIdx = offsetIdx + match.Index;
+ m_shaderModel.Value = match.Groups[ 1 ].Value;
+ m_shaderModel.InterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ match.Groups[ 1 ].Value ];
+ m_shaderModel.DataCheck = TemplateDataCheck.Valid;
+ idManager.RegisterId( m_shaderModel.StartIdx, uniquePrefix + m_shaderModel.Id, m_shaderModel.Id );
+ }
+ else
+ {
+ m_shaderModel.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+
+ // ALL MODULES
+ int allModulesIndex = subBody.IndexOf( TemplatesManager.TemplateAllModulesTag );
+ if( allModulesIndex > 0 )
+ {
+ //ONLY REGISTER MISSING TAGS
+ ConfigureCommonTag( m_allModulesTag, propertyContainer, idManager, uniquePrefix, offsetIdx, subBody );
+ m_allModulesMode = true;
+
+ m_blendData.SetAllModulesDefault();
+
+ if( !m_cullModeData.IsValid )
+ m_cullModeData.SetAllModulesDefault();
+
+ if( !m_colorMaskData.IsValid )
+ m_colorMaskData.SetAllModulesDefault();
+
+ if( !m_stencilData.IsValid )
+ m_stencilData.SetAllModulesDefault();
+
+ if( !m_depthData.IsValid )
+ m_depthData.SetAllModulesDefault();
+
+ if( !m_shaderModel.IsValid )
+ m_shaderModel.SetAllModulesDefault();
+ }
+ }
+
+ public void TestPropertyInternalName( string name, ref List<TemplateShaderPropertyData> availableShaderProperties, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ if( !string.IsNullOrEmpty( name ) && !duplicatesHelper.ContainsKey( name ))
+ {
+ TemplateShaderPropertyData newData = new TemplateShaderPropertyData( -1, string.Empty, string.Empty, name, name, WirePortDataType.INT, PropertyType.Property );
+ availableShaderProperties.Add( newData );
+ duplicatesHelper.Add( newData.PropertyName , newData );
+ }
+ }
+
+ public void RegisterInternalUnityInlines( ref List<TemplateShaderPropertyData> availableShaderProperties, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ TestPropertyInternalName( m_depthData.ZWriteInlineValue, ref availableShaderProperties , ref duplicatesHelper);
+ TestPropertyInternalName( m_depthData.ZTestInlineValue, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_depthData.OffsetFactorInlineValue, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_depthData.OffsetUnitsInlineValue, ref availableShaderProperties, ref duplicatesHelper );
+
+ TestPropertyInternalName( m_blendData.SourceFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_blendData.DestFactorRGBInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_blendData.SourceFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_blendData.DestFactorAlphaInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_blendData.BlendOpRGBInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_blendData.BlendOpAlphaInline, ref availableShaderProperties, ref duplicatesHelper );
+
+ TestPropertyInternalName( m_stencilData.ReferenceInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.ReadMaskInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.WriteMaskInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.ComparisonFrontInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.PassFrontInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.FailFrontInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.ZFailFrontInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.ComparisonBackInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.PassBackInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.FailBackInline, ref availableShaderProperties, ref duplicatesHelper );
+ TestPropertyInternalName( m_stencilData.ZFailBackInline, ref availableShaderProperties, ref duplicatesHelper );
+
+ TestPropertyInternalName( m_cullModeData.InlineData, ref availableShaderProperties, ref duplicatesHelper );
+
+ TestPropertyInternalName( m_colorMaskData.InlineData, ref availableShaderProperties, ref duplicatesHelper );
+ }
+
+ public void SetPassUniqueNameIfUndefined( string value )
+ {
+ if( string.IsNullOrEmpty( m_passUniqueName ) )
+ m_passUniqueName = value;
+ }
+
+ public bool HasValidData
+ {
+ get
+ {
+ return m_blendData.DataCheck == TemplateDataCheck.Valid ||
+ m_cullModeData.DataCheck == TemplateDataCheck.Valid ||
+ m_colorMaskData.DataCheck == TemplateDataCheck.Valid ||
+ m_stencilData.DataCheck == TemplateDataCheck.Valid ||
+ m_depthData.DataCheck == TemplateDataCheck.Valid ||
+ m_tagData.DataCheck == TemplateDataCheck.Valid ||
+ m_shaderModel.DataCheck == TemplateDataCheck.Valid ||
+ m_globalsTag.IsValid ||
+ m_srpBatcherTag.IsValid ||
+ m_allModulesTag.IsValid ||
+ m_functionsTag.IsValid ||
+ m_pragmaTag.IsValid ||
+ m_pragmaBeforeTag.IsValid ||
+ m_passTag.IsValid ||
+ m_inputsVertTag.IsValid ||
+ m_inputsFragTag.IsValid;
+ }
+ }
+
+ public TemplateBlendData BlendData { get { return m_blendData; } }
+ public TemplateCullModeData CullModeData { get { return m_cullModeData; } }
+ public TemplateColorMaskData ColorMaskData { get { return m_colorMaskData; } }
+ public TemplateStencilData StencilData { get { return m_stencilData; } }
+ public TemplateDepthData DepthData { get { return m_depthData; } }
+ public TemplateTagsModuleData TagData { get { return m_tagData; } }
+ public TemplateTagData GlobalsTag { get { return m_globalsTag; } }
+ public TemplateTagData SRPBatcherTag { get { return m_srpBatcherTag; } }
+ public TemplateTagData AllModulesTag { get { return m_allModulesTag; } }
+ public TemplateTagData FunctionsTag { get { return m_functionsTag; } }
+ public TemplateTagData PragmaTag { get { return m_pragmaTag; } }
+ public TemplateTagData PragmaBeforeTag { get { return m_pragmaBeforeTag; } }
+ public TemplateTagData PassTag { get { return m_passTag; } }
+ public TemplateTagData InputsVertTag { get { return m_inputsVertTag; } }
+ public TemplateTagData InputsFragTag { get { return m_inputsFragTag; } }
+ public TemplateShaderModelData ShaderModel { get { return m_shaderModel; } }
+ public TemplateSRPType SRPType { get { return m_srpType; } set { m_srpType = value; } }
+ public bool SRPIsPBR { get { return m_srpIsPBR; } set { m_srpIsPBR = value; } }
+ public bool SRPIsPBRHD { get { return m_srpIsPBR && m_srpType == TemplateSRPType.HD; } }
+ public string UniquePrefix { get { return m_uniquePrefix; } }
+ public string PassUniqueName { get { return m_passUniqueName; } }
+ public bool HasPassUniqueName { get { return !string.IsNullOrEmpty( m_passUniqueName ); } }
+ public TemplateIncludePragmaContainter IncludePragmaContainer { get { return m_includePragmaContainer; } }
+ public bool AllModulesMode { get { return m_allModulesMode; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta
new file mode 100644
index 00000000..64714772
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateModulesData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 122447ac2bc376a448a42a0f5373e63b
+timeCreated: 1521718529
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs
new file mode 100644
index 00000000..5086b55f
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs
@@ -0,0 +1,1248 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using System;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateUniquePassData
+ {
+ public int SubShaderIdx;
+ public int PassIdx;
+ }
+
+ [Serializable]
+ public sealed class TemplateMultiPass : TemplateDataParent
+ {
+ [SerializeField]
+ private List<TemplateShaderPropertyData> m_availableShaderProperties = new List<TemplateShaderPropertyData>();
+
+ [SerializeField]
+ private List<TemplateSubShader> m_subShaders = new List<TemplateSubShader>();
+
+ [SerializeField]
+ private TemplateTagData m_propertyTag;
+
+ [SerializeField]
+ private TemplateIdManager m_templateIdManager;
+
+ [SerializeField]
+ private string m_shaderNameId = string.Empty;
+
+ [SerializeField]
+ private string m_shaderBody;
+
+ [SerializeField]
+ private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer();
+
+ [SerializeField]
+ private TemplateShaderInfo m_shaderData;
+
+ [SerializeField]
+ private bool m_isSinglePass = false;
+
+ [SerializeField]
+ private int m_masterNodesRequired = 0;
+
+ [SerializeField]
+ TemplateInfoContainer m_customInspectorContainer = new TemplateInfoContainer();
+
+ [SerializeField]
+ TemplateInfoContainer m_dependenciesContainer = new TemplateInfoContainer();
+
+ [SerializeField]
+ TemplateInfoContainer m_fallbackContainer = new TemplateInfoContainer();
+
+ [SerializeField]
+ TemplateInfoContainer m_beforePragmaContainer = new TemplateInfoContainer();
+
+ [SerializeField]
+ private CustomTemplatePropertyUIEnum m_customTemplatePropertyUI = CustomTemplatePropertyUIEnum.None;
+
+ [SerializeField]
+ private int m_lodInjectorId = -1;
+
+ [SerializeField]
+ TemplateShaderModelData m_globalShaderModel = new TemplateShaderModelData();
+
+ private Dictionary<string, TemplateUniquePassData> m_passUniqueIdData = new Dictionary<string, TemplateUniquePassData>();
+
+
+ public TemplateMultiPass()
+ {
+ m_templateType = TemplateDataType.MultiPass;
+ }
+
+ public TemplateMultiPass( string name, string guid, bool isCommunity )
+ {
+ m_templateType = TemplateDataType.MultiPass;
+ Init( name, guid, isCommunity );
+ }
+
+ public override void Init( string name, string guid, bool isCommunity )
+ {
+ base.Init( name, guid, isCommunity );
+ TemplatesManager.CurrTemplateGUIDLoaded = guid;
+ LoadTemplateBody( guid );
+ Name = string.IsNullOrEmpty( name ) ? m_defaultShaderName : name;
+ }
+
+ void LoadTemplateBody( string guid )
+ {
+ m_passUniqueIdData.Clear();
+ m_guid = guid;
+ string datapath = AssetDatabase.GUIDToAssetPath( guid );
+ string shaderBody = string.Empty;
+ shaderBody = IOUtils.LoadTextFileFromDisk( datapath );
+ shaderBody = shaderBody.Replace( "\r\n", "\n" );
+
+ // Insert Before Tag
+ MatchCollection col = Regex.Matches( shaderBody, TemplateHelperFunctions.BeforePragmaPattern, RegexOptions.Singleline );
+ for( int i = col.Count - 1; i >= 0; i-- )
+ {
+ if( col[ i ].Groups.Count == 3 )
+ {
+ shaderBody = shaderBody.Insert( col[ i ].Groups[ 2 ].Index, TemplatesManager.TemplatePragmaBeforeTag + "\n" + col[ i ].Groups[ 1 ].Value );
+ }
+ }
+ //Detect SRP Batcher
+ MatchCollection srpMatch = Regex.Matches( shaderBody, TemplateHelperFunctions.SRPBatcherFindTag );
+ for( int i = srpMatch.Count - 1; i >= 0; i-- )
+ {
+ if( srpMatch[ i ].Groups.Count == 2 )
+ {
+ shaderBody = shaderBody.Insert( srpMatch[ i ].Groups[ 0 ].Index + srpMatch[ i ].Groups[ 0 ].Length, TemplatesManager.TemplateSRPBatcherTag + srpMatch[ i ].Groups[ 1 ].Value );
+ }
+ }
+
+
+ // Detect if template has LOD tag, if not, insert one
+ // It will be read and processed over the TemplateSubShader constructor
+ {
+ Match match = Regex.Match( shaderBody, TemplateHelperFunctions.SubShaderLODPattern );
+ if( match == null || ( match != null && !match.Success ) )
+ {
+ MatchCollection subShaderMatch = Regex.Matches( shaderBody, TemplatesManager.TemplateMPSubShaderTag );
+
+ int subShaderAmount = subShaderMatch.Count;
+
+ for( int i = subShaderAmount - 1; i > -1; i-- )
+ {
+ if( subShaderMatch[ i ].Success )
+ {
+ shaderBody = shaderBody.Insert( subShaderMatch[ i ].Index + subShaderMatch[ i ].Length, "\n\t\t\tLOD 0\n" );
+ }
+ }
+ }
+ }
+ m_shaderData = TemplateShaderInfoUtil.CreateShaderData( shaderBody );
+ if( m_shaderData == null )
+ {
+ m_isValid = false;
+ return;
+ }
+
+ m_templateIdManager = new TemplateIdManager( shaderBody );
+
+ try
+ {
+ int nameBegin = shaderBody.IndexOf( TemplatesManager.TemplateShaderNameBeginTag );
+ if( nameBegin < 0 )
+ {
+ // Not a template
+ return;
+ }
+
+ int nameEnd = shaderBody.IndexOf( TemplatesManager.TemplateFullEndTag, nameBegin );
+ if( nameEnd < 0 )
+ return;
+
+
+ m_shaderBody = shaderBody;
+ int defaultBegin = nameBegin + TemplatesManager.TemplateShaderNameBeginTag.Length;
+ int defaultLength = nameEnd - defaultBegin;
+ m_defaultShaderName = shaderBody.Substring( defaultBegin, defaultLength );
+ int[] nameIdx = m_defaultShaderName.AllIndexesOf( "\"" );
+ nameIdx[ 0 ] += 1; // Ignore the " character from the string
+ m_defaultShaderName = m_defaultShaderName.Substring( nameIdx[ 0 ], nameIdx[ 1 ] - nameIdx[ 0 ] );
+ m_shaderNameId = shaderBody.Substring( nameBegin, nameEnd + TemplatesManager.TemplateFullEndTag.Length - nameBegin );
+ m_templateProperties.AddId( shaderBody, m_shaderNameId, false );
+ m_templateIdManager.RegisterId( nameBegin, m_shaderNameId, m_shaderNameId );
+ shaderBody = shaderBody.Substring( nameEnd + TemplatesManager.TemplateFullEndTag.Length );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ m_isValid = false;
+ }
+
+ m_customTemplatePropertyUI = TemplateHelperFunctions.FetchCustomUI( shaderBody );
+ TemplateHelperFunctions.FetchDependencies( m_dependenciesContainer, ref m_shaderBody );
+ if( m_dependenciesContainer.IsValid )
+ {
+ int index = m_dependenciesContainer.Id.IndexOf( TemplatesManager.TemplateDependenciesListTag );
+ m_templateProperties.AddId( new TemplateProperty( m_dependenciesContainer.Id, m_dependenciesContainer.Id.Substring( 0, index ), true ) );
+ m_templateIdManager.RegisterId( m_dependenciesContainer.Index, m_dependenciesContainer.Id, m_dependenciesContainer.Id );
+ }
+
+ TemplateHelperFunctions.FetchCustomInspector( m_customInspectorContainer, ref m_shaderBody );
+ if( m_customInspectorContainer.IsValid )
+ {
+ int index = m_customInspectorContainer.Id.IndexOf( "CustomEditor" );
+ m_templateProperties.AddId( new TemplateProperty( m_customInspectorContainer.Id, m_customInspectorContainer.Id.Substring( 0, index ), true ) );
+ m_templateIdManager.RegisterId( m_customInspectorContainer.Index, m_customInspectorContainer.Id, m_customInspectorContainer.Id );
+ }
+
+ TemplateHelperFunctions.FetchFallback( m_fallbackContainer, ref m_shaderBody );
+ if( m_fallbackContainer.IsValid )
+ {
+ int index = m_fallbackContainer.Id.IndexOf( "Fallback", StringComparison.InvariantCultureIgnoreCase );
+ m_templateProperties.AddId( new TemplateProperty( m_fallbackContainer.Id, m_fallbackContainer.Id.Substring( 0, index ), true ) );
+ m_templateIdManager.RegisterId( m_fallbackContainer.Index, m_fallbackContainer.Id, m_fallbackContainer.Id );
+ }
+
+ m_lodInjectorId = m_shaderBody.IndexOf( TemplatesManager.TemplateLODsTag );
+
+ // Shader body may have been changed to inject inexisting tags like fallback
+ m_templateIdManager.ShaderBody = m_shaderBody;
+
+ m_propertyTag = new TemplateTagData( m_shaderData.PropertyStartIdx, TemplatesManager.TemplatePropertyTag, true );
+ m_templateIdManager.RegisterId( m_shaderData.PropertyStartIdx, TemplatesManager.TemplatePropertyTag, TemplatesManager.TemplatePropertyTag );
+ m_templateProperties.AddId( shaderBody, TemplatesManager.TemplatePropertyTag, true );
+ Dictionary<string, TemplateShaderPropertyData> duplicatesHelper = new Dictionary<string, TemplateShaderPropertyData>();
+ TemplateHelperFunctions.CreateShaderPropertiesList( m_shaderData.Properties, ref m_availableShaderProperties, ref duplicatesHelper );
+ for( int i = 0; i < m_availableShaderProperties.Count; i++ )
+ {
+ m_templateIdManager.RegisterId( m_availableShaderProperties[ i ].Index, m_availableShaderProperties[ i ].FullValue, m_availableShaderProperties[ i ].FullValue );
+ }
+
+ int subShaderCount = m_shaderData.SubShaders.Count;
+
+ int mainSubShaderIdx = -1;
+ int mainPassIdx = -1;
+
+ int firstVisibleSubShaderId = -1;
+ int firstVisiblePassId = -1;
+ bool foundMainPass = false;
+ bool foundFirstVisible = false;
+
+ m_templateIdManager.RegisterTag( TemplatesManager.TemplatePassesEndTag );
+ m_templateIdManager.RegisterTag( TemplatesManager.TemplateMainPassTag );
+
+ //SHADER MODEL
+ {
+ Match shaderModelMatch = Regex.Match( m_shaderData.Properties, TemplateHelperFunctions.ShaderModelPattern );
+ if( shaderModelMatch != null && shaderModelMatch.Success )
+ {
+ if( TemplateHelperFunctions.AvailableInterpolators.ContainsKey( shaderModelMatch.Groups[ 1 ].Value ) )
+ {
+ m_globalShaderModel.Id = shaderModelMatch.Groups[ 0 ].Value;
+ m_globalShaderModel.StartIdx = shaderModelMatch.Index;
+ m_globalShaderModel.Value = shaderModelMatch.Groups[ 1 ].Value;
+ m_globalShaderModel.InterpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ shaderModelMatch.Groups[ 1 ].Value ];
+ m_globalShaderModel.DataCheck = TemplateDataCheck.Valid;
+ }
+ else
+ {
+ m_globalShaderModel.DataCheck = TemplateDataCheck.Invalid;
+ }
+ }
+ }
+ //
+
+
+ for( int i = 0; i < subShaderCount; i++ )
+ {
+ TemplateSubShader subShader = new TemplateSubShader(this, i, m_templateIdManager, "SubShader" + i, m_shaderData.SubShaders[ i ], ref duplicatesHelper );
+
+ if( subShader.FoundMainPass )
+ {
+ if( !foundMainPass )
+ {
+ foundMainPass = true;
+ mainSubShaderIdx = i;
+ mainPassIdx = subShader.MainPass;
+ }
+ }
+ else if( subShader.MainPass > -1 )
+ {
+ if( !foundFirstVisible )
+ {
+ foundFirstVisible = true;
+ firstVisibleSubShaderId = i;
+ firstVisiblePassId = subShader.MainPass;
+ }
+ }
+
+ m_subShaders.Add( subShader );
+ m_masterNodesRequired += subShader.Passes.Count;
+ }
+
+
+ if( !foundMainPass && foundFirstVisible )
+ {
+ mainSubShaderIdx = firstVisibleSubShaderId;
+ mainPassIdx = firstVisiblePassId;
+ }
+
+ for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ )
+ {
+ m_subShaders[ subShaderIdx ].Modules.RegisterInternalUnityInlines( ref m_availableShaderProperties , ref duplicatesHelper );
+ int passCount = m_subShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.RegisterInternalUnityInlines( ref m_availableShaderProperties, ref duplicatesHelper );
+ m_subShaders[ subShaderIdx ].Passes[ passIdx ].IsMainPass = ( mainSubShaderIdx == subShaderIdx && mainPassIdx == passIdx );
+ }
+ }
+
+ duplicatesHelper.Clear();
+ duplicatesHelper = null;
+ m_isSinglePass = ( m_subShaders.Count == 1 && m_subShaders[ 0 ].PassAmount == 1 );
+
+ }
+
+ public void ResetState()
+ {
+ m_templateIdManager.ResetRegistersState();
+ int subshaderCount = m_subShaders.Count;
+ for( int subShaderIdx = 0; subShaderIdx < subshaderCount; subShaderIdx++ )
+ {
+ m_subShaders[ subShaderIdx ].TemplateProperties.ResetTemplateUsageData();
+ int passCount = m_subShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ m_subShaders[ subShaderIdx ].Passes[ passIdx ].TemplateProperties.ResetTemplateUsageData();
+ }
+ }
+ }
+
+ public override void Destroy()
+ {
+ m_templateProperties.Destroy();
+ m_templateProperties = null;
+
+ m_availableShaderProperties.Clear();
+ m_availableShaderProperties = null;
+
+ int subShaderCount = m_subShaders.Count;
+ for( int i = 0; i < subShaderCount; i++ )
+ {
+ m_subShaders[ i ].Destroy();
+ }
+
+ m_subShaders.Clear();
+ m_subShaders = null;
+
+ m_templateIdManager.Destroy();
+ m_templateIdManager = null;
+ }
+
+ public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, string[] list )
+ {
+ string id = GetSubShaderDataId( type, subShaderId, false );
+ string body = string.Empty;
+ FillTemplateBody( subShaderId, -1, id, ref body, list );
+ SetSubShaderData( type, subShaderId, body );
+ }
+
+ public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, List<PropertyDataCollector> list )
+ {
+ string id = GetSubShaderDataId( type, subShaderId, false );
+ string body = string.Empty;
+ FillTemplateBody( subShaderId, -1, id, ref body, list );
+ SetSubShaderData( type, subShaderId, body );
+ }
+
+ public void SetSubShaderData( TemplateModuleDataType type, int subShaderId, string text )
+ {
+ if( subShaderId >= m_subShaders.Count )
+ return;
+
+ string prefix = m_subShaders[ subShaderId ].Modules.UniquePrefix;
+ switch( type )
+ {
+ case TemplateModuleDataType.AllModules:
+ {
+ m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateAllModulesTag, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleShaderModel:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ShaderModel.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleBlendMode:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleBlendOp:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendOpId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleAlphaToMask:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.BlendData.AlphaToMaskId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleCullMode:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.CullModeData.CullModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleColorMask:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData.ColorMaskId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleStencil:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.StencilData.StencilBufferId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZwrite:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZWriteModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZTest:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZTestModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZOffset:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.DepthData.OffsetId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleTag:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.TagData.TagsId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleGlobals:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.GlobalsTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleSRPBatcher:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.SRPBatcherTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleFunctions:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.FunctionsTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePragma:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PragmaTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePragmaBefore:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PragmaBeforeTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePass:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.PassTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleInputVert:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.InputsVertTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleInputFrag:
+ {
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Modules.InputsFragTag.Id, text );
+ }
+ break;
+ }
+ }
+
+ public void SetPropertyData( string[] properties )
+ {
+ string body = string.Empty;
+ FillTemplateBody( -1, -1, TemplatesManager.TemplatePropertyTag, ref body, properties );
+ SetPropertyData( body );
+ }
+
+
+ public void SetPropertyData( string text )
+ {
+ m_templateIdManager.SetReplacementText( m_propertyTag.Id, text );
+ }
+
+ public string GetSubShaderDataId( TemplateModuleDataType type, int subShaderId, bool addPrefix )
+ {
+ if( subShaderId >= m_subShaders.Count )
+ return string.Empty;
+
+ string prefix = string.Empty;
+ switch( type )
+ {
+ case TemplateModuleDataType.AllModules:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + TemplatesManager.TemplateAllModulesTag;
+ }
+ case TemplateModuleDataType.ModuleBlendMode:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendModeId;
+ }
+ case TemplateModuleDataType.ModuleBlendOp:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.BlendData.BlendOpId;
+ }
+ case TemplateModuleDataType.ModuleAlphaToMask:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.BlendData.AlphaToMaskId;
+ }
+ case TemplateModuleDataType.ModuleCullMode:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.CullModeData.CullModeId;
+ }
+ case TemplateModuleDataType.ModuleColorMask:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.ColorMaskData.ColorMaskId;
+ }
+ case TemplateModuleDataType.ModuleStencil:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.StencilData.StencilBufferId;
+ }
+ case TemplateModuleDataType.ModuleZwrite:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZWriteModeId;
+ }
+ case TemplateModuleDataType.ModuleZTest:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.DepthData.ZTestModeId;
+ }
+ case TemplateModuleDataType.ModuleZOffset:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.DepthData.OffsetId;
+ }
+ case TemplateModuleDataType.ModuleTag:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.TagData.TagsId;
+ }
+ case TemplateModuleDataType.ModuleGlobals:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.GlobalsTag.Id;
+ }
+ case TemplateModuleDataType.ModuleSRPBatcher:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.SRPBatcherTag.Id;
+ }
+ case TemplateModuleDataType.ModuleFunctions:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.FunctionsTag.Id;
+ }
+ case TemplateModuleDataType.ModulePragma:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.PragmaTag.Id;
+ }
+ case TemplateModuleDataType.ModulePragmaBefore:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.PragmaBeforeTag.Id;
+ }
+ case TemplateModuleDataType.ModulePass:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.PassTag.Id;
+ }
+ case TemplateModuleDataType.ModuleInputVert:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.InputsVertTag.Id;
+ }
+ case TemplateModuleDataType.ModuleInputFrag:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Modules.InputsFragTag.Id;
+ }
+ }
+ return string.Empty;
+
+ }
+ public string GetPassDataId( TemplateModuleDataType type, int subShaderId, int passId, bool addPrefix )
+ {
+ if( subShaderId >= m_subShaders.Count || passId >= m_subShaders[ subShaderId ].Passes.Count )
+ return string.Empty;
+
+ string prefix = string.Empty;
+ switch( type )
+ {
+ case TemplateModuleDataType.AllModules:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + TemplatesManager.TemplateAllModulesTag;
+ }
+ case TemplateModuleDataType.ModuleBlendMode:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendModeId;
+ }
+ case TemplateModuleDataType.ModuleBlendOp:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendOpId;
+ }
+ case TemplateModuleDataType.ModuleAlphaToMask:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.AlphaToMaskId;
+ }
+ case TemplateModuleDataType.ModuleCullMode:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData.CullModeId;
+ }
+ case TemplateModuleDataType.ModuleColorMask:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData.ColorMaskId;
+ }
+ case TemplateModuleDataType.ModuleStencil:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.StencilData.StencilBufferId;
+ }
+ case TemplateModuleDataType.ModuleZwrite:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZWriteModeId;
+ }
+ case TemplateModuleDataType.ModuleZTest:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZTestModeId;
+ }
+ case TemplateModuleDataType.ModuleZOffset:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.OffsetId;
+ }
+ case TemplateModuleDataType.ModuleTag:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.TagData.TagsId;
+ }
+ case TemplateModuleDataType.ModuleGlobals:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.GlobalsTag.Id;
+ }
+ case TemplateModuleDataType.ModuleSRPBatcher:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.SRPBatcherTag.Id;
+ }
+ case TemplateModuleDataType.ModuleFunctions:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.FunctionsTag.Id;
+ }
+ case TemplateModuleDataType.ModulePragma:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaTag.Id;
+ }
+ case TemplateModuleDataType.ModulePragmaBefore:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaBeforeTag.Id;
+ }
+ case TemplateModuleDataType.ModulePass:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PassTag.Id;
+ }
+ case TemplateModuleDataType.ModuleInputVert:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsVertTag.Id;
+ }
+ case TemplateModuleDataType.ModuleInputFrag:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsFragTag.Id;
+ }
+ case TemplateModuleDataType.PassVertexFunction:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexFunctionData.Id;
+ }
+ case TemplateModuleDataType.PassFragmentFunction:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData.Id;
+ }
+ case TemplateModuleDataType.PassVertexData:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexDataContainer.VertexDataId;
+ }
+ case TemplateModuleDataType.PassInterpolatorData:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer.InterpDataId;
+ }
+ case TemplateModuleDataType.VControl:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessVControlTag.Id;
+ }
+ case TemplateModuleDataType.ControlData:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessControlData.Id;
+ }
+ case TemplateModuleDataType.DomainData:
+ {
+ prefix = addPrefix ? m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix : string.Empty;
+ return prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessDomainData.Id;
+ }
+ }
+ return string.Empty;
+ }
+
+ public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, string[] list )
+ {
+ //if( list == null || list.Length == 0 )
+ // return;
+
+ string id = GetPassDataId( type, subShaderId, passId, false );
+ string body = string.Empty;
+ FillTemplateBody( subShaderId, passId, id, ref body, list );
+ SetPassData( type, subShaderId, passId, body );
+ }
+
+ public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, List<PropertyDataCollector> list )
+ {
+ //if( list == null || list.Count == 0 )
+ // return;
+
+ string id = GetPassDataId( type, subShaderId, passId, false );
+ string body = string.Empty;
+ FillTemplateBody( subShaderId, passId, id, ref body, list );
+ SetPassData( type, subShaderId, passId, body );
+ }
+
+ public void SetPassData( TemplateModuleDataType type, int subShaderId, int passId, string text )
+ {
+ if( subShaderId >= m_subShaders.Count || passId >= m_subShaders[ subShaderId ].Passes.Count )
+ return;
+
+ string prefix = string.Empty;
+ switch( type )
+ {
+ //case TemplateModuleDataType.EndPass:
+ //{
+ // prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ // m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateEndPassTag, text );
+ //}
+ //break;
+ case TemplateModuleDataType.AllModules:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + TemplatesManager.TemplateAllModulesTag, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleShaderModel:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ShaderModel.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleBlendMode:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleBlendOp:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.BlendOpId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleAlphaToMask:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.BlendData.AlphaToMaskId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleCullMode:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData.CullModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleColorMask:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData.ColorMaskId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleStencil:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.StencilData.StencilBufferId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZwrite:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZWriteModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZTest:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.ZTestModeId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleZOffset:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.DepthData.OffsetId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleTag:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.TagData.TagsId, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleGlobals:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.GlobalsTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleSRPBatcher:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.SRPBatcherTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleFunctions:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.FunctionsTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePragma:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePragmaBefore:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PragmaBeforeTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModulePass:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.PassTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleInputVert:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsVertTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ModuleInputFrag:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].Modules.UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].Modules.InputsFragTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.PassVertexFunction:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexFunctionData.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.PassFragmentFunction:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.PassVertexData:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].VertexDataContainer.VertexDataId, text );
+ }
+ break;
+ case TemplateModuleDataType.PassInterpolatorData:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer.InterpDataId, text );
+ }
+ break;
+ case TemplateModuleDataType.PassNameData:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].PassNameContainer.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.VControl:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessVControlTag.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.ControlData:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessControlData.Id, text );
+ }
+ break;
+ case TemplateModuleDataType.DomainData:
+ {
+ prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].TessDomainData.Id, text );
+ }
+ break;
+ }
+ }
+
+ public void SetPassInputData( int subShaderId, int passId, int inputId, string text )
+ {
+ if( subShaderId >= m_subShaders.Count ||
+ passId >= m_subShaders[ subShaderId ].Passes.Count )
+ return;
+
+ string prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ TemplateInputData inputData = m_subShaders[ subShaderId ].Passes[ passId ].InputDataFromId( inputId );
+ if( inputData != null )
+ {
+ m_templateIdManager.SetReplacementText( prefix + inputData.TagId, text );
+ }
+ else
+ {
+ Debug.LogErrorFormat( "Unable to find input data for port with id {0} on subshader {1} pass {2}", inputId, subShaderId, passId );
+ }
+ }
+
+ public void SetPassInputDataByArrayIdx( int subShaderId, int passId, int inputId, string text )
+ {
+ if( subShaderId >= m_subShaders.Count ||
+ passId >= m_subShaders[ subShaderId ].Passes.Count ||
+ inputId >= m_subShaders[ subShaderId ].Passes[ passId ].InputDataList.Count )
+ return;
+
+ string prefix = m_subShaders[ subShaderId ].Passes[ passId ].UniquePrefix;
+ m_templateIdManager.SetReplacementText( prefix + m_subShaders[ subShaderId ].Passes[ passId ].InputDataList[ inputId ].TagId, text );
+ }
+
+ public TemplateData CreateTemplateData( string name, string guid, int subShaderId, int passId )
+ {
+ if( subShaderId >= m_subShaders.Count ||
+ passId >= m_subShaders[ subShaderId ].Passes.Count )
+ return null;
+
+ if( string.IsNullOrEmpty( name ) )
+ name = m_defaultShaderName;
+
+ TemplateData templateData = ScriptableObject.CreateInstance<TemplateData>();
+ templateData.Name = name;
+ templateData.GUID = guid;
+ templateData.TemplateBody = m_shaderBody;
+ templateData.DefaultShaderName = m_defaultShaderName;
+ templateData.ShaderNameId = m_shaderNameId;
+ templateData.OrderId = m_orderId;
+
+ templateData.InputDataList = SubShaders[ subShaderId ].Passes[ passId ].InputDataList;
+ templateData.VertexDataContainer = SubShaders[ subShaderId ].Passes[ passId ].VertexDataContainer;
+ templateData.InterpolatorDataContainer = SubShaders[ subShaderId ].Passes[ passId ].InterpolatorDataContainer;
+ templateData.AvailableShaderProperties = m_availableShaderProperties;
+ templateData.VertexFunctionData = SubShaders[ subShaderId ].Passes[ passId ].VertexFunctionData;
+ templateData.FragmentFunctionData = SubShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData;
+ templateData.BlendData = SubShaders[ subShaderId ].Passes[ passId ].Modules.BlendData;
+ templateData.CullModeData = SubShaders[ subShaderId ].Passes[ passId ].Modules.CullModeData;
+ templateData.ColorMaskData = SubShaders[ subShaderId ].Passes[ passId ].Modules.ColorMaskData;
+ templateData.StencilData = SubShaders[ subShaderId ].Passes[ passId ].Modules.StencilData;
+ templateData.DepthData = SubShaders[ subShaderId ].Passes[ passId ].Modules.DepthData;
+ templateData.TagData = SubShaders[ subShaderId ].Passes[ passId ].Modules.TagData;
+
+ //templateData.PropertyList = m_pr;
+ //private Dictionary<string, TemplateProperty> m_propertyDict = new Dictionary<string, TemplateProperty>();
+
+ return templateData;
+ }
+
+ public bool FillTemplateBody( int subShaderId, int passId, string id, ref string body, List<PropertyDataCollector> values )
+ {
+ if( values.Count == 0 )
+ {
+ return true;
+ }
+
+ string[] array = new string[ values.Count ];
+ for( int i = 0; i < values.Count; i++ )
+ {
+ array[ i ] = values[ i ].PropertyName;
+ }
+ return FillTemplateBody( subShaderId, passId, id, ref body, array );
+ }
+
+ public bool FillTemplateBody( int subShaderId, int passId, string id, ref string body, params string[] values )
+ {
+ if( values.Length == 0 )
+ {
+ if( id[ id.Length - 1 ] == '\n' )
+ body = "\n";
+
+ return true;
+ }
+
+ TemplatePropertyContainer propertyContainer = null;
+ if( subShaderId >= 0 )
+ {
+ if( passId >= 0 )
+ {
+ propertyContainer = SubShaders[ subShaderId ].Passes[ passId ].TemplateProperties;
+ }
+ else
+ {
+ propertyContainer = SubShaders[ subShaderId ].TemplateProperties;
+ }
+ }
+ else
+ {
+ propertyContainer = m_templateProperties;
+ }
+
+ propertyContainer.BuildInfo();
+
+ if( propertyContainer.PropertyDict.ContainsKey( id ) )
+ {
+ string finalValue = propertyContainer.PropertyDict[ id ].UseIndentationAtStart ? propertyContainer.PropertyDict[ id ].Indentation : string.Empty;
+ for( int i = 0; i < values.Length; i++ )
+ {
+
+ if( propertyContainer.PropertyDict[ id ].AutoLineFeed )
+ {
+ string[] valuesArr = values[ i ].Split( '\n' );
+ for( int j = 0; j < valuesArr.Length; j++ )
+ {
+ //first value will be automatically indented by the string replace
+ finalValue += ( ( i == 0 && j == 0 ) ? string.Empty : propertyContainer.PropertyDict[ id ].Indentation ) + valuesArr[ j ];
+ finalValue += TemplatesManager.TemplateNewLine;
+ }
+ }
+ else
+ {
+ //first value will be automatically indented by the string replace
+ finalValue += ( i == 0 ? string.Empty : propertyContainer.PropertyDict[ id ].Indentation ) + values[ i ];
+ }
+ }
+
+ body = finalValue;
+ propertyContainer.PropertyDict[ id ].Used = true;
+ return true;
+ }
+
+ if( values.Length > 1 || !string.IsNullOrEmpty( values[ 0 ] ) )
+ {
+ UIUtils.ShowMessage( string.Format( "Attempting to write data into inexistant tag {0}. Please review the template {1} body and consider adding the missing tag.", id, m_defaultShaderName ), MessageSeverity.Error );
+ return false;
+ }
+ return true;
+ }
+
+ public bool FillVertexInstructions( int subShaderId, int passId, params string[] values )
+ {
+ TemplateFunctionData vertexFunctionData = SubShaders[ subShaderId ].Passes[ passId ].VertexFunctionData;
+ if( vertexFunctionData != null && !string.IsNullOrEmpty( vertexFunctionData.Id ) )
+ {
+ string body = string.Empty;
+ bool isValid = FillTemplateBody( subShaderId, passId, vertexFunctionData.Id, ref body, values );
+ SetPassData( TemplateModuleDataType.PassVertexFunction, subShaderId, passId, body );
+ return isValid;
+ }
+
+ if( values.Length > 0 )
+ {
+ UIUtils.ShowMessage( "Attemping to add vertex instructions on a template with no assigned vertex code area", MessageSeverity.Error );
+ return false;
+ }
+ return true;
+ }
+
+ public bool FillFragmentInstructions( int subShaderId, int passId, params string[] values )
+ {
+ TemplateFunctionData fragmentFunctionData = SubShaders[ subShaderId ].Passes[ passId ].FragmentFunctionData;
+ if( fragmentFunctionData != null && !string.IsNullOrEmpty( fragmentFunctionData.Id ) )
+ {
+ string body = string.Empty;
+ bool isValid = FillTemplateBody( subShaderId, passId, fragmentFunctionData.Id, ref body, values );
+ SetPassData( TemplateModuleDataType.PassFragmentFunction, subShaderId, passId, body );
+ return isValid;
+ }
+
+ if( values.Length > 0 )
+ {
+ UIUtils.ShowMessage( "Attemping to add fragment instructions on a template with no assigned vertex code area", MessageSeverity.Error );
+ return false;
+ }
+ return true;
+ }
+
+ public void SetShaderName( string name )
+ {
+ m_templateIdManager.SetReplacementText( m_shaderNameId, name );
+ }
+
+ public void SetCustomInspector( string customInspector )
+ {
+ if( m_customInspectorContainer.Index > -1 )
+ {
+ m_templateIdManager.SetReplacementText( m_customInspectorContainer.Id, m_templateProperties.PropertyDict[ m_customInspectorContainer.Id ].Indentation + customInspector );
+ }
+ }
+
+ public void SetFallback( string fallback )
+ {
+ if( m_fallbackContainer.Index > -1 )
+ {
+ m_templateIdManager.SetReplacementText( m_fallbackContainer.Id, m_templateProperties.PropertyDict[ m_fallbackContainer.Id ].Indentation + fallback );
+ }
+ }
+
+ public void SetDependencies( string dependencies )
+ {
+ if( m_dependenciesContainer.Index > -1 )
+ {
+ m_templateIdManager.SetReplacementText( m_dependenciesContainer.Id, dependencies );
+ }
+ }
+
+ private void OnEnable()
+ {
+ hideFlags = HideFlags.HideAndDontSave;
+ }
+
+ public override bool Reload()
+ {
+ m_propertyTag = null;
+ m_shaderNameId = string.Empty;
+ m_shaderBody = string.Empty;
+ m_isSinglePass = false;
+ m_masterNodesRequired = 0;
+ m_beforePragmaContainer.Reset();
+ m_customInspectorContainer.Reset();
+ m_fallbackContainer.Reset();
+ m_dependenciesContainer.Reset();
+ m_availableShaderProperties.Clear();
+ int count = m_subShaders.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_subShaders[ i ].Destroy();
+ }
+ m_subShaders.Clear();
+
+ m_templateIdManager.Reset();
+ if( m_shaderData != null )
+ m_shaderData.Destroy();
+
+ m_templateProperties.Reset();
+
+ string oldName = m_defaultShaderName;
+ LoadTemplateBody( m_guid );
+
+ if( m_communityTemplate )
+ Name = m_defaultShaderName;
+
+ return !oldName.Equals( m_defaultShaderName );
+ }
+
+ public bool GetSubShaderandPassFor( string passUniqueId, ref int subShaderId, ref int passId )
+ {
+ if( string.IsNullOrEmpty( passUniqueId ) )
+ return false;
+
+ if( m_passUniqueIdData.Count == 0 )
+ {
+ for( int subShaderIdx = 0; subShaderIdx < m_subShaders.Count; subShaderIdx++ )
+ {
+ for( int passIdx = 0; passIdx < m_subShaders[ subShaderIdx ].Passes.Count; passIdx++ )
+ {
+ if( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.HasPassUniqueName )
+ {
+ if( m_passUniqueIdData.ContainsKey( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName ) )
+ {
+ Debug.LogErrorFormat( "Found duplicate pass name '{0}' over template. Please fix template as it will result in multiple errors.", m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName );
+ return false;
+ }
+ m_passUniqueIdData.Add( m_subShaders[ subShaderIdx ].Passes[ passIdx ].Modules.PassUniqueName, new TemplateUniquePassData() { PassIdx = passIdx, SubShaderIdx = subShaderIdx } );
+ }
+ }
+ }
+ }
+
+ if( m_passUniqueIdData.ContainsKey( passUniqueId ) )
+ {
+ subShaderId = m_passUniqueIdData[ passUniqueId ].SubShaderIdx;
+ passId = m_passUniqueIdData[ passUniqueId ].PassIdx;
+ return true;
+ }
+ subShaderId = -1;
+ passId = -1;
+ return false;
+ }
+
+ public TemplateShaderPropertyData GetShaderPropertyData( string propertyName )
+ {
+ return m_availableShaderProperties.Find( ( x ) => ( x.PropertyName.Equals( propertyName ) ) );
+ }
+
+ public TemplateSRPType SRPtype { get { return m_subShaders[ 0 ].Modules.SRPType; } }
+ //public bool SRPIsPBRHD { get { return m_subShaders[0].Modules.SRPIsPBRHD ; } }
+ public List<TemplateSubShader> SubShaders { get { return m_subShaders; } }
+ public List<TemplateShaderPropertyData> AvailableShaderProperties { get { return m_availableShaderProperties; } }
+ public TemplateTagData PropertyTag { get { return m_propertyTag; } }
+ public TemplateIdManager IdManager { get { return m_templateIdManager; } }
+ public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } }
+ public TemplateInfoContainer CustomInspectorContainer { get { return m_customInspectorContainer; } }
+ public TemplateInfoContainer FallbackContainer { get { return m_fallbackContainer; } }
+ public TemplateInfoContainer BeforePragmaContainer { get { return m_beforePragmaContainer; } }
+ public bool IsSinglePass { get { return m_isSinglePass; } }
+ public int MasterNodesRequired { get { return m_masterNodesRequired; } }
+ public CustomTemplatePropertyUIEnum CustomTemplatePropertyUI { get { return m_customTemplatePropertyUI; } }
+ public bool CanAddLODs { get { return m_lodInjectorId > -1; } }
+ public TemplateShaderModelData GlobalShaderModel { get { return m_globalShaderModel; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta
new file mode 100644
index 00000000..00e2dee2
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPass.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4214390aa7f66364bbab454dc15a04ac
+timeCreated: 1516981847
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs
new file mode 100644
index 00000000..92ce5c77
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs
@@ -0,0 +1,3113 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+//#define SHOW_TEMPLATE_HELP_BOX
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ public enum HDSRPMaterialType
+ {
+ SubsurfaceScattering,
+ Standard,
+ Specular,
+ Anisotropy,
+ Iridescence,
+ Translucent
+ }
+
+ public enum InvisibilityStatus
+ {
+ LockedInvisible,
+ Invisible,
+ Visible
+ }
+
+ public enum SetTemplateSource
+ {
+ NewShader,
+ ShaderLoad,
+ HotCodeReload
+ };
+
+ [Serializable]
+ [NodeAttributes( "Template Master Node", "Master", "Shader Generated according to template rules", null, KeyCode.None, false )]
+ public sealed class TemplateMultiPassMasterNode : MasterNode
+ {
+ private const double MaxLODEditTimestamp = 1;
+
+ private static int PASS_SELECTOR_VERSION = 16200;
+ private static int PASS_UNIQUE_ID_VERSION = 16204;
+
+ private const string LodNameId = "LODName";
+ private const string LodValueId = "LODValue";
+
+ private const string LodSubtitle = "LOD( {0} )";
+ private const string AdditionalLODsStr = "LODs";
+
+ private const string SubTitleFormatterStr = "(SubShader {0} Pass {1})";
+ private const string NoSubShaderPropertyStr = "No Sub-Shader properties available";
+ private const string NoPassPropertyStr = "No Pass properties available";
+
+ private const string WarningMessage = "Templates is a feature that is still heavily under development and users may experience some problems.\nPlease email support@amplify.pt if any issue occurs.";
+ private const string OpenTemplateStr = "Edit Template";
+ private const string ReloadTemplateStr = "Reload Template";
+ private const string CommonPropertiesStr = "Common Properties ";
+ private const string SubShaderModuleStr = "SubShader ";
+ private const string PassModuleStr = "Pass ";
+
+ private const string PassNameStr = "Name";
+ private const string PassNameFormateStr = "Name \"{0}\"";
+ private const string SubShaderLODValueLabel = "LOD Value";
+ private const string SubShaderLODNameLabel = "LOD Name";
+
+
+
+ private bool m_reRegisterTemplateData = false;
+ private bool m_fireTemplateChange = false;
+ private bool m_fetchMasterNodeCategory = false;
+
+ [SerializeField]
+ private string m_templateGUID = "4e1801f860093ba4f9eb58a4b556825b";
+
+ [SerializeField]
+ private int m_passIdx = 0;
+
+ //[SerializeField]
+ //private string m_passIdxStr = string.Empty;
+
+ [SerializeField]
+ private bool m_passFoldout = false;
+
+ [SerializeField]
+ private int m_subShaderIdx = 0;
+
+ //[SerializeField]
+ //private string m_subShaderIdxStr = string.Empty;
+
+ [SerializeField]
+ private bool m_subStringFoldout = false;
+
+ [SerializeField]
+ private bool m_lodFoldout = false;
+
+
+ [SerializeField]
+ private string m_mainLODName = string.Empty;
+
+ //[SerializeField]
+ //private string m_subShaderLODStr;
+
+ //[SerializeField]
+ //private bool m_mainMPMasterNode = false;
+
+ [NonSerialized]
+ private TemplateMultiPass m_templateMultiPass = null;
+
+ [NonSerialized]
+ private TemplateMultiPassMasterNode m_mainMasterNodeRef = null;
+
+ [SerializeField]
+ private TemplateModulesHelper m_subShaderModule = new TemplateModulesHelper();
+
+ [SerializeField]
+ private TemplateModulesHelper m_passModule = new TemplateModulesHelper();
+
+ [SerializeField]
+ private UsePassHelper m_usePass;
+
+ [SerializeField]
+ private string m_passName = string.Empty;
+
+ [SerializeField]
+ private string m_passUniqueId = string.Empty;
+
+ [SerializeField]
+ private string m_originalPassName = string.Empty;
+
+ [SerializeField]
+ private bool m_hasLinkPorts = false;
+
+ [SerializeField]
+ private InvisibilityStatus m_isInvisible = InvisibilityStatus.Visible;
+
+ [SerializeField]
+ private int m_invisibleOptions = 0;
+
+ [SerializeField]
+ private bool m_invalidNode = false;
+
+ [SerializeField]
+ private FallbackPickerHelper m_fallbackHelper = null;
+
+ [SerializeField]
+ private DependenciesHelper m_dependenciesHelper = new DependenciesHelper();
+
+ [SerializeField]
+ private TemplateOptionsUIHelper m_subShaderOptions = new TemplateOptionsUIHelper( true );
+
+ [SerializeField]
+ private TemplateOptionsUIHelper m_passOptions = new TemplateOptionsUIHelper( false );
+
+ [SerializeField]
+ private TemplatePassSelectorHelper m_passSelector = new TemplatePassSelectorHelper();
+
+ [SerializeField]
+ private TemplateOptionsDefinesContainer m_optionsDefineContainer = new TemplateOptionsDefinesContainer();
+
+ [SerializeField]
+ private TerrainDrawInstancedHelper m_drawInstancedHelper = new TerrainDrawInstancedHelper();
+
+ // HATE THIS BELOW, MUST REMOVE HD SPECIFIC CODE FROM GENERIC MASTER NODE
+ private const string HDSRPMaterialTypeStr = "Material Type";
+ private const string SRPMaterialSubsurfaceScatteringKeyword = "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING 1";
+ private const string SRPMaterialTransmissionKeyword = "_MATERIAL_FEATURE_TRANSMISSION 1";
+ private const string SRPHDMaterialSpecularKeyword = "_MATERIAL_FEATURE_SPECULAR_COLOR 1";
+ //private const string SRPLWMaterialSpecularKeyword = "_SPECULAR_SETUP 1";
+ private const string SRPMaterialAnisotropyKeyword = "_MATERIAL_FEATURE_ANISOTROPY 1";
+ private const string SRPMaterialIridiscenceKeyword = "_MATERIAL_FEATURE_IRIDESCENCE 1";
+ //private const string SRPMaterialNormalMapKeyword = "_NORMALMAP 1";
+ //private const string SRPMaterialAlphaTestKeyword = "_ALPHATEST_ON 1";
+ //private const string SRPMaterialBlendModeAlphaClipThresholdKeyword = "_AlphaClip 1";
+ private const string SRPMaterialTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT 1";
+ private const string SRPMaterialBlendModeAddKeyword = "_BLENDMODE_ADD 1";
+ private const string SRPMaterialBlendModeAlphaKeyword = "_BLENDMODE_ALPHA 1";
+ private const string SRPMaterialClearCoatKeyword = "_MATERIAL_FEATURE_CLEAR_COAT";
+
+ [NonSerialized]
+ private bool m_fetchPorts = true;
+ [NonSerialized]
+ private InputPort m_specularPort;
+ [NonSerialized]
+ private InputPort m_metallicPort;
+ [NonSerialized]
+ private InputPort m_coatMaskPort;
+ [NonSerialized]
+ private InputPort m_diffusionProfilePort;
+ [NonSerialized]
+ private InputPort m_subsurfaceMaskPort;
+ [NonSerialized]
+ private InputPort m_thicknessPort;
+ [NonSerialized]
+ private InputPort m_anisotropyPort;
+ [NonSerialized]
+ private InputPort m_iridescenceThicknessPort;
+ [NonSerialized]
+ private InputPort m_iridescenceMaskPort;
+ [NonSerialized]
+ private InputPort m_indexOfRefractionPort;
+ [NonSerialized]
+ private InputPort m_transmittanceColorPort;
+ [NonSerialized]
+ private InputPort m_transmittanceAbsorptionDistancePort;
+ [NonSerialized]
+ private InputPort m_transmittanceMaskPort;
+
+ [SerializeField]
+ private HDSRPMaterialType m_hdSrpMaterialType = HDSRPMaterialType.Standard;
+
+ [NonSerialized]
+ private bool m_refreshLODValueMasterNodes = false;
+ [NonSerialized]
+ private bool m_refocusLODValueMasterNodes = false;
+ [NonSerialized]
+ private double m_refreshLODValueMasterNodesTimestamp;
+
+ //////////////////////////////////////////////////////////////////////////
+ protected override void CommonInit( int uniqueId )
+ {
+ base.CommonInit( uniqueId );
+ m_masterNodeCategory = 1;// First Template
+ m_marginPreviewLeft = 20;
+ m_shaderNameIsTitle = true;
+ m_customInspectorName = string.Empty;
+ m_customPrecision = true;
+ }
+
+ public override void ReleaseResources()
+ {
+ // Internal template resources ( for inline properties) are released by first node on the list
+ // As it's also registered that way
+ if( IsLODMainFirstPass )
+ m_containerGraph.ClearInternalTemplateNodes();
+
+ if( !IsLODMainMasterNode )
+ return;
+ TemplateMultiPass template = ( m_templateMultiPass == null ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : m_templateMultiPass;
+ //Maintained the logic of being the main master node to unregister since this method is being called
+ //over the main master node in multiple places
+ //but it will unregister with unique of the first master node (pass 0) since it was the one
+ //to register it
+ int passUniqueId = ( m_passIdx == 0 ) ? UniqueId : ContainerGraph.MultiPassMasterNodes.NodesList[ 0 ].UniqueId;
+
+ if( template != null && template.AvailableShaderProperties != null )
+ {
+ // Unregister old template properties
+ int oldPropertyCount = template.AvailableShaderProperties.Count;
+ for( int i = 0; i < oldPropertyCount; i++ )
+ {
+ UIUtils.ReleaseUniformName( passUniqueId, template.AvailableShaderProperties[ i ].PropertyName );
+ }
+ }
+ }
+
+ public void CopyOptionsFrom( TemplateMultiPassMasterNode origin )
+ {
+ //Copy options
+ SubShaderOptions.CopyOptionsValuesFrom( origin.SubShaderOptions );
+ PassOptions.CopyOptionsValuesFrom( origin.PassOptions );
+
+ //Copy selected passes
+ if( IsMainOutputNode )
+ m_passSelector.CopyFrom( origin.PassSelector );
+ }
+
+ void RegisterProperties()
+ {
+ //First pass must be the one to always register properties so all modules
+ //can extract a valid negative Id when reading inline properties
+ if( /*!IsLODMainMasterNode*/!IsLODMainFirstPass )
+ {
+ m_reRegisterTemplateData = false;
+ return;
+ }
+
+ if( m_templateMultiPass != null )
+ {
+ m_reRegisterTemplateData = false;
+ // Register old template properties
+ int newPropertyCount = m_templateMultiPass.AvailableShaderProperties.Count;
+ for( int i = 0; i < newPropertyCount; i++ )
+ {
+ m_containerGraph.AddInternalTemplateNode( m_templateMultiPass.AvailableShaderProperties[ i ] );
+ int nodeId = UIUtils.CheckUniformNameOwner( m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName );
+ if( nodeId > -1 )
+ {
+ if( UniqueId != nodeId )
+ {
+ ParentNode node = m_containerGraph.GetNode( nodeId );
+ if( node != null )
+ {
+ UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being used by {1}. Please rename it and reload template.", m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName, node.Attributes.Name ) );
+ }
+ else
+ {
+ UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being on your graph. Please rename it and reload template.", m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ) );
+ }
+ }
+ }
+ else
+ {
+ UIUtils.RegisterUniformName( UniqueId, m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName );
+ }
+ }
+ }
+ }
+
+ public override void OnEnable()
+ {
+ base.OnEnable();
+ m_reRegisterTemplateData = true;
+
+ if( m_usePass == null )
+ {
+ m_usePass = ScriptableObject.CreateInstance<UsePassHelper>();
+ m_usePass.Init( " Additional Use Passes" );
+ }
+
+ if( m_fallbackHelper == null )
+ {
+ m_fallbackHelper = ScriptableObject.CreateInstance<FallbackPickerHelper>();
+ m_fallbackHelper.Init();
+ }
+ }
+
+ protected override void OnUniqueIDAssigned()
+ {
+ base.OnUniqueIDAssigned();
+ if( UniqueId >= 0 )
+ {
+ if( m_lodIndex == -1 )
+ {
+ m_containerGraph.MultiPassMasterNodes.AddNode( this );
+ }
+ else
+ {
+ m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this );
+ }
+ }
+ }
+
+ public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
+ {
+ base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
+ m_passOptions.CheckImediateActionsForPort( this, portId );
+ }
+
+ public override void OnInputPortDisconnected( int portId )
+ {
+ base.OnInputPortDisconnected( portId );
+ m_passOptions.CheckImediateActionsForPort( this, portId );
+ }
+
+ public void ForceTemplateRefresh()
+ {
+ SetTemplate( null, false, true, m_subShaderIdx, m_passIdx, SetTemplateSource.HotCodeReload );
+ }
+
+ public void SetTemplate( TemplateMultiPass template, bool writeDefaultData, bool fetchMasterNodeCategory, int subShaderIdx, int passIdx , SetTemplateSource source )
+ {
+ if( subShaderIdx > -1 )
+ m_subShaderIdx = subShaderIdx;
+
+ if( passIdx > -1 )
+ m_passIdx = passIdx;
+
+ ReleaseResources();
+ bool hotCodeOrRead = ( template == null );
+ m_templateMultiPass = ( hotCodeOrRead ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : template;
+ if( m_templateMultiPass != null )
+ {
+
+ string passName = string.IsNullOrEmpty( m_passUniqueId ) ? ( m_isInvisible == InvisibilityStatus.LockedInvisible ? m_passName : m_originalPassName ) : m_passUniqueId;
+ int newPassIdx = m_passIdx;
+ int newSubShaderIdx = m_subShaderIdx;
+ m_templateMultiPass.GetSubShaderandPassFor( passName, ref newSubShaderIdx, ref newPassIdx );
+ if( newPassIdx == -1 || newSubShaderIdx == -1 )
+ {
+ //m_containerGraph.MarkToDelete( this );
+ ContainerGraph.ParentWindow.SetOutdatedShaderFromTemplate();
+ m_invalidNode = true;
+ UIUtils.ShowMessage( "Template changed drastically. Removing invalid passes." );
+ return;
+ }
+ else
+ {
+ if( m_passIdx != newPassIdx )
+ m_passIdx = newPassIdx;
+
+ if( m_subShaderIdx != newSubShaderIdx )
+ m_subShaderIdx = newSubShaderIdx;
+ }
+
+ m_containerGraph.CurrentSRPType = m_templateMultiPass.SRPtype;
+ if( m_templateMultiPass.IsSinglePass )
+ {
+ SetAdditonalTitleText( string.Empty );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx )
+ {
+ SetAdditonalTitleText( string.Format( SubTitleFormatterStr, m_subShaderIdx, m_passIdx ) );
+ }
+ m_invalidNode = false;
+ if( m_subShaderIdx >= m_templateMultiPass.SubShaders.Count ||
+ m_passIdx >= m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes.Count )
+ {
+ if( DebugConsoleWindow.DeveloperMode )
+ Debug.LogFormat( "Inexisting pass {0}. Cancelling template fetch", m_originalPassName );
+
+ return;
+ }
+
+ m_isMainOutputNode = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsMainPass;
+ if( m_isMainOutputNode )
+ {
+ // We cannot use UIUtils.MasterNodeOnTexture.height since this method can be
+ // called before UIUtils is initialized
+ m_insideSize.y = 55;
+ }
+ else
+ {
+ m_insideSize.y = 0;
+ }
+
+ //IsMainOutputNode = m_mainMPMasterNode;
+ if( source != SetTemplateSource.HotCodeReload )
+ {
+ //Only set this if no hotcode reload happens ( via new shader or load )
+ m_isInvisible = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible ? InvisibilityStatus.LockedInvisible : InvisibilityStatus.Visible;
+ }
+ else
+ {
+ // On hot code reload we only need to verify if template pass visibility data changes
+ // and change accordingly
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible )
+ {
+ if( m_isInvisible != InvisibilityStatus.LockedInvisible )
+ m_isInvisible = InvisibilityStatus.LockedInvisible;
+ }
+ else
+ {
+ if( m_isInvisible == InvisibilityStatus.LockedInvisible )
+ {
+ m_isInvisible = InvisibilityStatus.Visible;
+ }
+ }
+ }
+
+ m_invisibleOptions = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InvisibleOptions;
+
+ m_originalPassName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data;
+
+ if( !hotCodeOrRead )
+ {
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Index > -1 )
+ {
+ //m_subShaderLODStr = m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id;
+ ShaderLOD = Convert.ToInt32( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Data );
+ }
+ else
+ {
+ ShaderLOD = 0;
+ }
+ }
+
+ m_shaderNameIsTitle = IsMainOutputNode;
+ m_fetchMasterNodeCategory = fetchMasterNodeCategory;
+ m_templateGUID = m_templateMultiPass.GUID;
+ UpdatePortInfo();
+
+ RegisterProperties();
+
+ // template is null when hot code reloading or loading from file so inspector name shouldn't be changed
+ if( !hotCodeOrRead )
+ {
+ m_customInspectorName = m_templateMultiPass.CustomInspectorContainer.Data;
+ if( m_isMainOutputNode )
+ {
+ m_passSelector.Clear();
+ m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] );
+ }
+ }
+ else
+ {
+ //Hotcode reload or ReadFromString
+ // Setup is only made if internal pass array is null
+ if( m_isMainOutputNode )
+ {
+ m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] );
+ }
+ }
+
+ SetupCustomOptionsFromTemplate( template != null );
+
+ if( string.IsNullOrEmpty( m_fallbackHelper.RawFallbackShader ) )
+ m_fallbackHelper.RawFallbackShader = m_templateMultiPass.FallbackContainer.Data;
+
+ //bool updateInfofromTemplate = UpdatePortInfo();
+ //if( updateInfofromTemplate )
+ //{
+ m_subShaderModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules );
+ m_passModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules );
+ //}
+
+ //RegisterProperties();
+ if( writeDefaultData )
+ {
+ //ShaderName = m_templateMultiPass.DefaultShaderName;
+ ShaderName = m_shaderName;
+ m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data;
+ if( !m_templateMultiPass.IsSinglePass /*&& !m_shaderNameIsTitle*/ )
+ {
+ if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx )
+ SetClippedTitle( m_passName );
+ }
+ }
+
+ UpdateSubShaderPassStr();
+
+ if( m_isMainOutputNode )
+ m_fireTemplateChange = true;
+ }
+ else
+ {
+ m_invalidNode = true;
+ }
+ }
+
+ public override void OnRefreshLinkedPortsComplete()
+ {
+ if( m_invalidNode )
+ return;
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD )
+ ConfigHDPorts();
+
+ SetReadOptions();
+ }
+
+ public void SetReadOptions()
+ {
+ m_passOptions.SetReadOptions();
+ if( m_isMainOutputNode )
+ m_subShaderOptions.SetReadOptions();
+ }
+
+ bool UpdatePortInfo()
+ {
+ List<TemplateInputData> inputDataList = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InputDataList;
+ int count = inputDataList.Count;
+ if( count != m_inputPorts.Count )
+ {
+ DeleteAllInputConnections( true );
+
+ for( int i = 0; i < count; i++ )
+ {
+ InputPort port = AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId );
+ port.ExternalLinkId = inputDataList[ i ].LinkId;
+ m_hasLinkPorts = m_hasLinkPorts || !string.IsNullOrEmpty( inputDataList[ i ].LinkId );
+ }
+ return true;
+ }
+ else
+ {
+ for( int i = 0; i < count; i++ )
+ {
+ m_inputPorts[ i ].ChangeProperties( inputDataList[ i ].PortName, inputDataList[ i ].DataType, false );
+ m_inputPorts[ i ].ExternalLinkId = inputDataList[ i ].LinkId;
+ }
+ return false;
+ }
+ }
+
+ public void SetPropertyActionFromItem( TemplateModulesHelper module, TemplateActionItem item )
+ {
+ TemplateModulesHelper subShaderModule = m_isMainOutputNode ? m_subShaderModule : m_mainMasterNodeRef.SubShaderModule;
+ switch( item.PropertyAction )
+ {
+ case PropertyActionsEnum.CullMode:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.CullModeHelper.CurrentCullMode = subShaderModule.CullModeHelper.CurrentCullMode;
+ }
+ else
+ {
+ module.CullModeHelper.CurrentCullMode = item.ActionCullMode;
+ }
+
+ }
+ break;
+ case PropertyActionsEnum.ColorMask:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.ColorMaskHelper.ColorMask = subShaderModule.ColorMaskHelper.ColorMask;
+ }
+ else
+ {
+ module.ColorMaskHelper.ColorMask = item.ColorMask;
+ }
+ }
+ break;
+ case PropertyActionsEnum.ZWrite:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.DepthOphelper.ZWriteModeValue = subShaderModule.DepthOphelper.ZWriteModeValue;
+ }
+ else
+ {
+ module.DepthOphelper.ZWriteModeValue = item.ActionZWrite;
+ }
+ }
+ break;
+ case PropertyActionsEnum.ZTest:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.DepthOphelper.ZTestModeValue = subShaderModule.DepthOphelper.ZTestModeValue;
+ }
+ else
+ {
+ module.DepthOphelper.ZTestModeValue = item.ActionZTest;
+ }
+ }
+ break;
+ case PropertyActionsEnum.ZOffsetFactor:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.DepthOphelper.OffsetFactorValue = subShaderModule.DepthOphelper.OffsetFactorValue;
+ }
+ else
+ {
+ module.DepthOphelper.OffsetFactorValue = item.ActionZOffsetFactor;
+ }
+ }
+ break;
+ case PropertyActionsEnum.ZOffsetUnits:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.DepthOphelper.OffsetUnitsValue = subShaderModule.DepthOphelper.OffsetUnitsValue;
+ }
+ else
+ {
+ module.DepthOphelper.OffsetUnitsValue = item.ActionZOffsetUnits;
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendRGB:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.BlendOpHelper.SourceFactorRGB = subShaderModule.BlendOpHelper.SourceFactorRGB;
+ module.BlendOpHelper.DestFactorRGB = subShaderModule.BlendOpHelper.DestFactorRGB;
+ }
+ else
+ {
+ module.BlendOpHelper.SourceFactorRGB = item.ActionBlendRGBSource;
+ module.BlendOpHelper.DestFactorRGB = item.ActionBlendRGBDest;
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendAlpha:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.BlendOpHelper.SourceFactorAlpha = subShaderModule.BlendOpHelper.SourceFactorAlpha;
+ module.BlendOpHelper.DestFactorAlpha = subShaderModule.BlendOpHelper.DestFactorAlpha;
+ }
+ else
+ {
+ module.BlendOpHelper.CurrentAlphaIndex = 1;
+ module.BlendOpHelper.SourceFactorAlpha = item.ActionBlendAlphaSource;
+ module.BlendOpHelper.DestFactorAlpha = item.ActionBlendAlphaDest;
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendOpRGB:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.BlendOpHelper.BlendOpRGB = subShaderModule.BlendOpHelper.BlendOpRGB;
+ }
+ else
+ {
+ module.BlendOpHelper.BlendOpRGB = item.ActionBlendOpRGB;
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendOpAlpha:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.BlendOpHelper.BlendOpAlpha = subShaderModule.BlendOpHelper.BlendOpAlpha;
+ }
+ else
+ {
+ module.BlendOpHelper.BlendOpAlpha = item.ActionBlendOpAlpha;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilReference:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.ReferenceValue = subShaderModule.StencilBufferHelper.ReferenceValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.ReferenceValue = item.ActionStencilReference;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilReadMask:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.ReadMaskValue = subShaderModule.StencilBufferHelper.ReadMaskValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.ReadMaskValue = item.ActionStencilReadMask;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilWriteMask:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.WriteMaskValue = subShaderModule.StencilBufferHelper.WriteMaskValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.WriteMaskValue = item.ActionStencilWriteMask;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilComparison:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.ComparisonFunctionIdxValue = subShaderModule.StencilBufferHelper.ComparisonFunctionIdxValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.ComparisonFunctionIdxValue = item.ActionStencilComparison;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilPass:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.PassStencilOpIdxValue = subShaderModule.StencilBufferHelper.PassStencilOpIdxValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.PassStencilOpIdxValue = item.ActionStencilPass;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilFail:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.FailStencilOpIdxValue = subShaderModule.StencilBufferHelper.FailStencilOpIdxValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.FailStencilOpIdxValue = item.ActionStencilFail;
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilZFail:
+ {
+ if( item.CopyFromSubShader )
+ {
+ module.StencilBufferHelper.ZFailStencilOpIdxValue = subShaderModule.StencilBufferHelper.ZFailStencilOpIdxValue;
+ }
+ else
+ {
+ module.StencilBufferHelper.ZFailStencilOpIdxValue = item.ActionStencilZFail;
+ }
+ }
+ break;
+ case PropertyActionsEnum.RenderType:
+ {
+ module.TagsHelper.AddSpecialTag( TemplateSpecialTags.RenderType, item );
+ }
+ break;
+ case PropertyActionsEnum.RenderQueue:
+ {
+ module.TagsHelper.AddSpecialTag( TemplateSpecialTags.Queue, item );
+ }
+ break;
+ }
+ }
+
+ public void OnCustomPassOptionSelected( bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions )
+ {
+ m_passOptions.OnCustomOptionSelected( isRefreshing, invertAction, this, uiItem, validActions );
+ }
+
+ public void OnCustomSubShaderOptionSelected( bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions )
+ {
+ if( m_isMainOutputNode )
+ m_subShaderOptions.OnCustomOptionSelected( isRefreshing, invertAction, this, uiItem, validActions );
+ }
+
+ void SetupCustomOptionsFromTemplate( bool newTemplate )
+ {
+ m_passOptions.SetupCustomOptionsFromTemplate( this, newTemplate );
+ if( m_isMainOutputNode )
+ m_subShaderOptions.SetupCustomOptionsFromTemplate( this, newTemplate );
+ }
+
+ void SetPassCustomOptionsInfo( TemplateMultiPassMasterNode masterNode )
+ {
+ TemplateMultiPassMasterNode mainMasterNode = masterNode.IsMainOutputNode ? masterNode : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode );
+ mainMasterNode.SubShaderOptions.SetSubShaderCustomOptionsPortsInfo( masterNode, ref m_currentDataCollector );
+ masterNode.PassOptions.SetCustomOptionsInfo( masterNode, ref m_currentDataCollector );
+ }
+
+ void RefreshCustomOptionsDict()
+ {
+ m_passOptions.RefreshCustomOptionsDict();
+ if( m_isMainOutputNode )
+ m_subShaderOptions.RefreshCustomOptionsDict();
+ }
+
+ void SetCategoryIdxFromTemplate()
+ {
+ int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount;
+ for( int i = 0; i < templateCount; i++ )
+ {
+ int idx = i + 1;
+ TemplateMultiPass templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateMultiPass;
+ if( templateData != null && m_templateMultiPass != null && m_templateMultiPass.GUID.Equals( templateData.GUID ) )
+ m_masterNodeCategory = idx;
+ }
+ }
+
+ public void CheckTemplateChanges()
+ {
+ if( m_invalidNode )
+ return;
+
+ if( IsLODMainMasterNode )
+ {
+ if( m_containerGraph.MultiPassMasterNodes.Count != m_templateMultiPass.MasterNodesRequired )
+ {
+ if( m_availableCategories == null )
+ RefreshAvailableCategories();
+
+ if( DebugConsoleWindow.DeveloperMode )
+ Debug.Log( "Template Pass amount was changed. Rebuiling master nodes" );
+
+ m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ], true );
+ }
+ }
+ }
+
+ public override void OnNodeLogicUpdate( DrawInfo drawInfo )
+ {
+ if( m_invalidNode )
+ {
+ return;
+ }
+ base.OnNodeLogicUpdate( drawInfo );
+
+ if( m_templateMultiPass == null )
+ {
+ // Hotcode reload has happened
+ SetTemplate( null, false, true, m_subShaderIdx, m_passIdx , SetTemplateSource.HotCodeReload );
+ CheckTemplateChanges();
+ }
+
+ if( m_reRegisterTemplateData )
+ {
+ RegisterProperties();
+ }
+
+ if( m_fetchMasterNodeCategory )
+ {
+ if( m_availableCategories != null )
+ {
+ m_fetchMasterNodeCategory = false;
+ SetCategoryIdxFromTemplate();
+ }
+ }
+
+ if( m_fireTemplateChange )
+ {
+ m_fireTemplateChange = false;
+ m_containerGraph.FireMasterNodeReplacedEvent();
+ }
+
+ if( m_subShaderModule.HasValidData )
+ {
+ m_subShaderModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules );
+ }
+
+ if( m_passModule.HasValidData )
+ {
+ m_passModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules );
+ }
+
+ if( !m_isMainOutputNode && m_mainMasterNodeRef == null )
+ {
+ m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode;
+ }
+
+ if( m_refreshLODValueMasterNodes && ( EditorApplication.timeSinceStartup - m_refreshLODValueMasterNodesTimestamp ) > MaxLODEditTimestamp )
+ {
+ m_refreshLODValueMasterNodes = false;
+ m_refocusLODValueMasterNodes = true;
+ m_containerGraph.SortLODMasterNodes();
+ }
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ if( m_isInvisible == InvisibilityStatus.Visible )
+ {
+ base.Draw( drawInfo );
+ }
+ }
+
+ public override void OnNodeLayout( DrawInfo drawInfo )
+ {
+ if( m_invalidNode )
+ {
+ if( m_isMainOutputNode )
+ {
+ UIUtils.ShowMessage( "Invalid current template. Switching to Standard Surface", MessageSeverity.Error );
+ m_shaderModelIdx = 0;
+ m_masterNodeCategory = 0;
+ m_containerGraph.ParentWindow.ReplaceMasterNode( new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, m_shaderName ), false );
+ }
+ return;
+ }
+
+ if( m_isInvisible != InvisibilityStatus.Visible )
+ {
+ return;
+ }
+
+ if( !IsMainOutputNode )
+ {
+ if( !IsInvisible && Docking )
+ {
+ m_useSquareNodeTitle = true;
+ TemplateMultiPassMasterNode master = ContainerGraph.CurrentMasterNode as TemplateMultiPassMasterNode;
+ m_position = master.TruePosition;
+ m_position.height = 32;
+ int masterIndex = ContainerGraph.MultiPassMasterNodes.NodesList.IndexOf( master );
+ int index = ContainerGraph.MultiPassMasterNodes.GetNodeRegisterIdx( UniqueId );
+ if( index > masterIndex )
+ {
+ int backTracking = 0;
+ for( int i = index - 1; i > masterIndex; i-- )
+ {
+ if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking )
+ backTracking++;
+ }
+ m_position.y = master.TruePosition.yMax + 1 + 33 * ( backTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax;
+ base.OnNodeLayout( drawInfo );
+ }
+ else
+ {
+ int forwardTracking = 1;
+ for( int i = index + 1; i < masterIndex; i++ )
+ {
+ if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking )
+ forwardTracking++;
+ }
+ m_position.y = master.TruePosition.y - 33 * ( forwardTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax;
+ base.OnNodeLayout( drawInfo );
+ }
+ }
+ else
+ {
+ m_useSquareNodeTitle = false;
+ base.OnNodeLayout( drawInfo );
+ }
+ }
+ else
+ {
+ base.OnNodeLayout( drawInfo );
+ }
+ }
+
+ public override void OnNodeRepaint( DrawInfo drawInfo )
+ {
+ base.OnNodeRepaint( drawInfo );
+ if( m_invalidNode )
+ return;
+
+ if( m_isInvisible == InvisibilityStatus.Visible )
+ {
+ if( m_containerGraph.IsInstancedShader )
+ {
+ DrawInstancedIcon( drawInfo );
+ }
+ }
+ }
+
+ public override void UpdateFromShader( Shader newShader )
+ {
+ if( m_currentMaterial != null && m_currentMaterial.shader != newShader )
+ {
+ m_currentMaterial.shader = newShader;
+ }
+ CurrentShader = newShader;
+ }
+
+ public override void UpdateMasterNodeMaterial( Material material )
+ {
+ m_currentMaterial = material;
+ FireMaterialChangedEvt();
+ }
+
+ void DrawReloadButton()
+ {
+ if( GUILayout.Button( ReloadTemplateStr ) && m_templateMultiPass != null )
+ {
+ m_templateMultiPass.Reload();
+ }
+ }
+
+ void DrawOpenTemplateButton()
+ {
+ GUILayout.BeginHorizontal();
+ {
+ if( GUILayout.Button( OpenTemplateStr ) && m_templateMultiPass != null )
+ {
+ try
+ {
+ string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID );
+ if( !string.IsNullOrEmpty( pathname ) )
+ {
+ Shader selectedTemplate = AssetDatabase.LoadAssetAtPath<Shader>( pathname );
+ if( selectedTemplate != null )
+ {
+ AssetDatabase.OpenAsset( selectedTemplate, 1 );
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ if( GUILayout.Button( "\u25C4", GUILayout.Width( 18 ), GUILayout.Height( 18 ) ) && m_templateMultiPass != null )
+ {
+ try
+ {
+ string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID );
+ if( !string.IsNullOrEmpty( pathname ) )
+ {
+ Shader selectedTemplate = AssetDatabase.LoadAssetAtPath<Shader>( pathname );
+ if( selectedTemplate != null )
+ {
+ Event.current.Use();
+ Selection.activeObject = selectedTemplate;
+ EditorGUIUtility.PingObject( Selection.activeObject );
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ }
+ GUILayout.EndHorizontal();
+ }
+
+ public override void DrawProperties()
+ {
+ base.DrawProperties();
+ if( m_invalidNode )
+ return;
+
+ NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, CommonPropertiesStr, DrawCommonProperties );
+ NodeUtils.DrawPropertyGroup( ref m_subStringFoldout, SubShaderModuleStr, DrawSubShaderProperties );
+ NodeUtils.DrawPropertyGroup( ref m_passFoldout, PassModuleStr, DrawPassProperties );
+
+ DrawMaterialInputs( UIUtils.MenuItemToolbarStyle, false );
+
+ if( m_propertyOrderChanged )
+ {
+ List<TemplateMultiPassMasterNode> mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList;
+ int count = mpNodes.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( mpNodes[ i ].UniqueId != UniqueId )
+ {
+ mpNodes[ i ].CopyPropertyListFrom( this );
+ }
+ }
+ }
+
+#if SHOW_TEMPLATE_HELP_BOX
+ EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning );
+#endif
+ }
+
+ // this will be removed later when PBR options are created
+ void SetExtraDefine( string define )
+ {
+ List<TemplateMultiPassMasterNode> nodes = this.ContainerGraph.MultiPassMasterNodes.NodesList;
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( "#define " + define, false );
+ }
+ }
+
+ void AddHDKeywords()
+ {
+ if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None )
+ return;
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD ||
+ !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR )
+ return;
+
+ switch( m_hdSrpMaterialType )
+ {
+ case HDSRPMaterialType.SubsurfaceScattering:
+ {
+ SetExtraDefine( SRPMaterialSubsurfaceScatteringKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialSubsurfaceScatteringKeyword );
+ if( m_thicknessPort != null && m_thicknessPort.HasOwnOrLinkConnection )
+ {
+ SetExtraDefine( SRPMaterialTransmissionKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword );
+ }
+ }
+ break;
+ case HDSRPMaterialType.Standard:
+ break;
+ case HDSRPMaterialType.Specular:
+ {
+ SetExtraDefine( SRPHDMaterialSpecularKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPHDMaterialSpecularKeyword );
+ }
+ break;
+ case HDSRPMaterialType.Anisotropy:
+ {
+ SetExtraDefine( SRPMaterialAnisotropyKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAnisotropyKeyword );
+ }
+ break;
+ case HDSRPMaterialType.Iridescence:
+ {
+ SetExtraDefine( SRPMaterialIridiscenceKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialIridiscenceKeyword );
+ }
+ break;
+ case HDSRPMaterialType.Translucent:
+ {
+ SetExtraDefine( SRPMaterialTransmissionKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword );
+ }
+ break;
+ }
+
+ if( m_coatMaskPort != null && m_coatMaskPort.HasOwnOrLinkConnection )
+ {
+ SetExtraDefine( SRPMaterialClearCoatKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialClearCoatKeyword );
+ }
+ }
+
+ void FetchHDPorts()
+ {
+ if( m_fetchPorts )
+ {
+ m_fetchPorts = false;
+ if( m_inputPorts.Count > 4 )
+ {
+ m_specularPort = GetInputPortByUniqueId( 3 );
+ m_metallicPort = GetInputPortByUniqueId( 4 );
+ m_coatMaskPort = GetInputPortByUniqueId( 11 );
+ m_diffusionProfilePort = GetInputPortByUniqueId( 12 );
+ m_subsurfaceMaskPort = GetInputPortByUniqueId( 13 );
+ m_thicknessPort = GetInputPortByUniqueId( 14 );
+ m_anisotropyPort = GetInputPortByUniqueId( 15 );
+ m_iridescenceThicknessPort = GetInputPortByUniqueId( 16 );
+ m_iridescenceMaskPort = GetInputPortByUniqueId( 17 );
+ m_indexOfRefractionPort = GetInputPortByUniqueId( 18 );
+ m_transmittanceColorPort = GetInputPortByUniqueId( 19 );
+ m_transmittanceAbsorptionDistancePort = GetInputPortByUniqueId( 20 );
+ m_transmittanceMaskPort = GetInputPortByUniqueId( 21 );
+ }
+ }
+ }
+
+ void ConfigHDPorts()
+ {
+ if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None )
+ return;
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD ||
+ !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR )
+ return;
+
+ FetchHDPorts();
+ if( m_inputPorts.Count > 4 )
+ {
+ switch( m_hdSrpMaterialType )
+ {
+ case HDSRPMaterialType.SubsurfaceScattering:
+ {
+ m_specularPort.Visible = false;
+ m_metallicPort.Visible = false;
+ m_coatMaskPort.Visible = true;
+ m_diffusionProfilePort.Visible = true;
+ m_subsurfaceMaskPort.Visible = true;
+ m_thicknessPort.Visible = true;
+ m_anisotropyPort.Visible = false;
+ m_iridescenceThicknessPort.Visible = false;
+ m_iridescenceMaskPort.Visible = false;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ case HDSRPMaterialType.Standard:
+ {
+ m_specularPort.Visible = false;
+ m_metallicPort.Visible = true;
+ m_coatMaskPort.Visible = true;
+ m_diffusionProfilePort.Visible = false;
+ m_subsurfaceMaskPort.Visible = false;
+ m_thicknessPort.Visible = false;
+ m_anisotropyPort.Visible = false;
+ m_iridescenceThicknessPort.Visible = false;
+ m_iridescenceMaskPort.Visible = false;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ case HDSRPMaterialType.Specular:
+ {
+ m_specularPort.Visible = true;
+ m_metallicPort.Visible = false;
+ m_coatMaskPort.Visible = true;
+ m_diffusionProfilePort.Visible = false;
+ m_subsurfaceMaskPort.Visible = false;
+ m_thicknessPort.Visible = false;
+ m_anisotropyPort.Visible = false;
+ m_iridescenceThicknessPort.Visible = false;
+ m_iridescenceMaskPort.Visible = false;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ case HDSRPMaterialType.Anisotropy:
+ {
+ m_specularPort.Visible = false;
+ m_metallicPort.Visible = true;
+ m_coatMaskPort.Visible = true;
+ m_diffusionProfilePort.Visible = false;
+ m_subsurfaceMaskPort.Visible = false;
+ m_thicknessPort.Visible = false;
+ m_anisotropyPort.Visible = true;
+ m_iridescenceThicknessPort.Visible = false;
+ m_iridescenceMaskPort.Visible = false;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ case HDSRPMaterialType.Iridescence:
+ {
+ m_specularPort.Visible = false;
+ m_metallicPort.Visible = true;
+ m_coatMaskPort.Visible = true;
+ m_diffusionProfilePort.Visible = false;
+ m_subsurfaceMaskPort.Visible = false;
+ m_thicknessPort.Visible = false;
+ m_anisotropyPort.Visible = false;
+ m_iridescenceThicknessPort.Visible = true;
+ m_iridescenceMaskPort.Visible = true;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ case HDSRPMaterialType.Translucent:
+ {
+ m_specularPort.Visible = false;
+ m_metallicPort.Visible = false;
+ m_coatMaskPort.Visible = false;
+ m_diffusionProfilePort.Visible = true;
+ m_subsurfaceMaskPort.Visible = false;
+ m_thicknessPort.Visible = true;
+ m_anisotropyPort.Visible = false;
+ m_iridescenceThicknessPort.Visible = false;
+ m_iridescenceMaskPort.Visible = false;
+ m_indexOfRefractionPort.Visible = false;
+ m_transmittanceColorPort.Visible = false;
+ m_transmittanceAbsorptionDistancePort.Visible = false;
+ m_transmittanceMaskPort.Visible = false;
+ }
+ break;
+ }
+ }
+ m_sizeIsDirty = ( m_isInvisible == InvisibilityStatus.Visible );
+ }
+
+
+ public void SetShaderLODValueAndLabel( int value )
+ {
+ if( ShaderLOD != value )
+ ShaderLOD = value;
+
+ if( ContainerGraph.HasLODs )
+ {
+ SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) );
+ }
+ else
+ {
+ SetAdditonalTitleText( string.Empty );
+ }
+ }
+
+ void DrawLODAddRemoveButtons()
+ {
+ DrawLODAddRemoveButtons( -2 , true );
+ }
+
+ void DrawLODAddRemoveButtons( int index , bool showRemove )
+ {
+ if( GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( 15 ) ) )
+ {
+ Vector2 minPos = Vec2Position;
+ //bool newNodePositionMode = false;
+ //if( newNodePositionMode )
+ //{
+ // for( int lod = 0; lod < ContainerGraph.LodMultiPassMasternodes.Count; lod++ )
+ // {
+ // if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 )
+ // {
+ // Vector2 currPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position;
+ // if( currPos.y > minPos.y )
+ // {
+ // minPos = currPos;
+ // }
+ // }
+ // else
+ // {
+ // if( index < 0 )
+ // {
+ // index = lod;
+ // }
+ // break;
+ // }
+ // }
+ //}
+ //else
+ //{
+ for( int lod = ContainerGraph.LodMultiPassMasternodes.Count - 1 ; lod >= 0; lod-- )
+ {
+ if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 )
+ {
+ minPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position;
+ break;
+ }
+ }
+ //}
+
+ minPos.y += HeightEstimate + 10;
+ ContainerGraph.CreateLodMasterNodes( m_templateMultiPass, index, minPos );
+ }
+
+ if( showRemove && GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( 15 ) ) )
+ {
+ ContainerGraph.DestroyLodMasterNodes( index );
+ }
+ }
+
+ void SetupLODNodeName()
+ {
+ if( IsMainOutputNode )
+ {
+ if( string.IsNullOrEmpty( m_mainLODName ) )
+ {
+ m_shaderNameIsTitle = true;
+ m_content.text = GenerateClippedTitle( m_croppedShaderName );
+ }
+ else
+ {
+ m_shaderNameIsTitle = false;
+ m_content.text = GenerateClippedTitle( m_mainLODName );
+ }
+ }
+ else
+ {
+ m_shaderNameIsTitle = false;
+ m_content.text = GenerateClippedTitle( m_passName );
+ }
+ }
+
+ public void DrawLodRowItem(bool listMode)
+ {
+ float labelWidthBuffer = EditorGUIUtility.labelWidth;
+ EditorGUILayout.BeginHorizontal();
+ if( listMode )
+ {
+ if( GUILayout.Button( "\u25b6", GUILayout.Width( 18 ), GUILayout.Height( 18 ) ) )
+ {
+ m_containerGraph.ParentWindow.FocusOnNode( this, 1, false, true );
+ }
+ EditorGUI.BeginChangeCheck();
+ GUI.SetNextControlName( LodValueId + m_lodIndex );
+ m_shaderLOD = EditorGUILayoutIntField( string.Empty, m_shaderLOD, GUILayout.Width( 50 ) );
+ }
+ else
+ {
+ EditorGUI.BeginChangeCheck();
+ EditorGUIUtility.labelWidth = 45;
+ GUI.SetNextControlName( LodValueId + m_lodIndex );
+ m_shaderLOD = EditorGUILayoutIntField( "LOD", ShaderLOD, GUILayout.Width(100));
+ EditorGUIUtility.labelWidth = labelWidthBuffer;
+ }
+
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_refreshLODValueMasterNodes = true;
+ m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup;
+
+ if( ContainerGraph.HasLODs )
+ SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) );
+ }
+
+ EditorGUI.BeginChangeCheck();
+ GUI.SetNextControlName( LodNameId + ShaderLOD );
+ if( listMode )
+ {
+ m_mainLODName = EditorGUILayoutTextField( string.Empty, m_mainLODName, GUILayout.Width( 100 ) );
+ }
+ else
+ {
+ GUILayout.Space( -15 );
+ EditorGUIUtility.labelWidth = 45;
+ m_mainLODName = EditorGUILayoutTextField( string.Empty, m_mainLODName );
+ EditorGUIUtility.labelWidth = labelWidthBuffer;
+ }
+ if( EditorGUI.EndChangeCheck() )
+ {
+ // If reorder is scheduled make sure it doesn't happen when editing LOD name
+ if( m_refreshLODValueMasterNodes )
+ m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup;
+
+ SetupLODNodeName();
+ }
+
+ if( listMode )
+ DrawLODAddRemoveButtons( m_lodIndex, ( m_lodIndex >= 0) );
+
+ EditorGUILayout.EndHorizontal();
+
+ if( m_refocusLODValueMasterNodes )
+ {
+ m_refocusLODValueMasterNodes = false;
+ string focusedControl = GUI.GetNameOfFocusedControl();
+ if( focusedControl.Contains( LodValueId ) )
+ {
+ GUI.FocusControl( LodValueId + m_lodIndex );
+ TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl );
+ if( te != null )
+ {
+ te.SelectTextEnd();
+ }
+ }
+ else if( focusedControl.Contains( LodNameId ) )
+ {
+ GUI.FocusControl( LodNameId + m_lodIndex );
+ TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl );
+ if( te != null )
+ {
+ te.SelectTextEnd();
+ }
+ }
+ }
+ }
+
+ void DrawLOD()
+ {
+ if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 )
+ {
+ EditorGUILayout.Space();
+
+ DrawLodRowItem(true);
+ EditorGUILayout.Space();
+
+ for( int i = 0; i < ContainerGraph.LodMultiPassMasternodes.Count; i++ )
+ {
+ if( ContainerGraph.LodMultiPassMasternodes[ i ].NodesList.Count > 0 )
+ {
+ TemplateMultiPassMasterNode masterNode = m_containerGraph.LodMultiPassMasternodes[ i ].NodesList[ m_passIdx ];
+ masterNode.DrawLodRowItem( true );
+ EditorGUILayout.Space();
+ }
+ }
+ EditorGUILayout.Space();
+ }
+ }
+
+ void DrawCommonProperties()
+ {
+ if( m_isMainOutputNode )
+ {
+ //if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 )
+ //{
+ // if( GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( 15 ) ) )
+ // {
+ // ContainerGraph.CreateLodMasterNodes( m_templateMultiPass, Vec2Position );
+ // }
+
+
+ // if( GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( 15 ) ) )
+ // {
+ // ContainerGraph.DestroyLodMasterNodes();
+ // }
+
+ //}
+
+ //EditorGUILayout.LabelField( "LOD: " + m_lodIndex );
+ DrawShaderName();
+ DrawCurrentShaderType();
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD )
+ {
+ if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.HDPBR )
+ {
+ EditorGUI.BeginChangeCheck();
+ CurrentHDMaterialType = (HDSRPMaterialType)EditorGUILayoutEnumPopup( HDSRPMaterialTypeStr, m_hdSrpMaterialType );
+ if( EditorGUI.EndChangeCheck() )
+ ConfigHDPorts();
+ }
+ }
+
+ EditorGUI.BeginChangeCheck();
+ DrawPrecisionProperty( false );
+ if( EditorGUI.EndChangeCheck() )
+ ContainerGraph.CurrentPrecision = m_currentPrecisionType;
+ m_drawInstancedHelper.Draw( this );
+ m_fallbackHelper.Draw( this );
+ DrawCustomInspector( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn );
+ m_subShaderOptions.DrawCustomOptions( this );
+ m_dependenciesHelper.Draw( this, true );
+ }
+ //EditorGUILayout.LabelField( m_subShaderIdxStr );
+ //EditorGUILayout.LabelField( m_passIdxStr );
+
+ if( IsLODMainMasterNode && m_templateMultiPass.CanAddLODs )
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref m_lodFoldout, AdditionalLODsStr, DrawLOD, DrawLODAddRemoveButtons );
+ }
+
+ DrawOpenTemplateButton();
+ if( DebugConsoleWindow.DeveloperMode )
+ DrawReloadButton();
+
+ }
+
+ public void DrawSubShaderProperties()
+ {
+ if( !m_isMainOutputNode )
+ {
+ m_mainMasterNodeRef.DrawSubShaderProperties();
+ return;
+ }
+
+ bool noValidData = true;
+ if( ShaderLOD > 0 )
+ {
+ noValidData = false;
+ if( m_templateMultiPass.CanAddLODs && m_containerGraph.LodMultiPassMasternodes[0].Count > 0 )
+ {
+ DrawLodRowItem( false );
+ }
+ else
+ {
+ ShaderLOD = EditorGUILayoutIntField( SubShaderLODValueLabel, ShaderLOD );
+ }
+ }
+
+ if( m_subShaderModule.HasValidData )
+ {
+ noValidData = false;
+ m_subShaderModule.Draw( this, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules );
+ //if( m_subShaderModule.IsDirty )
+ //{
+ // List<TemplateMultiPassMasterNode> mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList;
+ // int count = mpNodes.Count;
+ // for( int i = 0; i < count; i++ )
+ // {
+ // if( mpNodes[ i ].SubShaderIdx == m_subShaderIdx && mpNodes[ i ].UniqueId != UniqueId )
+ // {
+ // mpNodes[ i ].SubShaderModule.CopyFrom( m_subShaderModule );
+ // }
+ // }
+ // m_subShaderModule.IsDirty = false;
+ //}
+ }
+
+ m_passSelector.Draw( this );
+
+ if( noValidData )
+ {
+ EditorGUILayout.HelpBox( NoSubShaderPropertyStr, MessageType.Info );
+ }
+ }
+
+ void DrawPassProperties()
+ {
+ EditorGUI.BeginChangeCheck();
+ m_passName = EditorGUILayoutTextField( PassNameStr, m_passName );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ if( m_passName.Length > 0 )
+ {
+ m_passName = UIUtils.RemoveShaderInvalidCharacters( m_passName );
+ }
+ else
+ {
+ m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data;
+ }
+ //if( !m_templateMultiPass.IsSinglePass )
+ // SetClippedTitle( m_passName );
+ }
+ EditorGUILayout.LabelField( Pass.Modules.PassUniqueName );
+ if( m_passModule.HasValidData )
+ {
+ m_passModule.Draw( this, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules, m_subShaderModule );
+ }
+
+ m_usePass.Draw( this, false );
+ m_passOptions.DrawCustomOptions( this );
+ }
+
+ bool CreateInstructionsForList( TemplateData templateData, ref List<InputPort> ports, ref string shaderBody, ref List<string> vertexInstructions, ref List<string> fragmentInstructions )
+ {
+ if( ports.Count == 0 )
+ return true;
+ AddHDKeywords();
+ bool isValid = true;
+ //UIUtils.CurrentWindow.CurrentGraph.ResetNodesLocalVariables();
+ for( int i = 0; i < ports.Count; i++ )
+ {
+ TemplateInputData inputData = templateData.InputDataFromId( ports[ i ].PortId );
+ if( ports[ i ].HasOwnOrLinkConnection )
+ {
+ //if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.Lightweight )
+ //{
+ // if( ports[ i ].Name.Contains( "Normal" ) )
+ // {
+ // m_currentDataCollector.AddToDirectives( SRPMaterialNormalMapKeyword, -1, AdditionalLineType.Define );
+ // }
+
+ // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) )
+ // {
+ // m_currentDataCollector.AddToDirectives( SRPMaterialBlendModeAlphaClipThresholdKeyword, -1, AdditionalLineType.Define );
+ // }
+
+ // if( ports[ i ].Name.Contains( "Specular" ) )
+ // {
+ // m_currentDataCollector.AddToDirectives( SRPLWMaterialSpecularKeyword, -1, AdditionalLineType.Define );
+ // }
+ //}
+ //else if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.HD )
+ //{
+ // if( ports[ i ].Name.Contains( "Normal" ) )
+ // {
+ // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialNormalMapKeyword );
+ // }
+
+ // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) )
+ // {
+ // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAlphaTestKeyword );
+ // }
+
+ //}
+
+ m_currentDataCollector.ResetInstructions();
+ m_currentDataCollector.ResetVertexInstructions();
+
+ m_currentDataCollector.PortCategory = ports[ i ].Category;
+ string newPortInstruction = ports[ i ].GeneratePortInstructions( ref m_currentDataCollector );
+
+ if( m_currentDataCollector.DirtySpecialLocalVariables )
+ {
+ string cleanVariables = m_currentDataCollector.SpecialLocalVariables.Replace( "\t", string.Empty );
+ m_currentDataCollector.AddInstructions( cleanVariables, false );
+ m_currentDataCollector.ClearSpecialLocalVariables();
+ }
+
+ if( m_currentDataCollector.DirtyVertexVariables )
+ {
+ string cleanVariables = m_currentDataCollector.VertexLocalVariables.Replace( "\t", string.Empty );
+ m_currentDataCollector.AddVertexInstruction( cleanVariables, UniqueId, false );
+ m_currentDataCollector.ClearVertexLocalVariables();
+ }
+
+ // fill functions
+ for( int j = 0; j < m_currentDataCollector.InstructionsList.Count; j++ )
+ {
+ fragmentInstructions.Add( m_currentDataCollector.InstructionsList[ j ].PropertyName );
+ }
+
+ for( int j = 0; j < m_currentDataCollector.VertexDataList.Count; j++ )
+ {
+ vertexInstructions.Add( m_currentDataCollector.VertexDataList[ j ].PropertyName );
+ }
+
+ m_templateMultiPass.SetPassInputData( m_subShaderIdx, m_passIdx, ports[ i ].PortId, newPortInstruction );
+ isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx, m_passIdx, inputData.TagId, ref shaderBody, newPortInstruction ) && isValid;
+ }
+ else
+ {
+ m_templateMultiPass.SetPassInputData( m_subShaderIdx, m_passIdx, ports[ i ].PortId, inputData.DefaultValue );
+ isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx, m_passIdx, inputData.TagId, ref shaderBody, inputData.DefaultValue ) && isValid;
+ }
+ }
+ return isValid;
+ }
+
+ public string BuildShaderBody( MasterNodeDataCollector inDataCollector, ref MasterNodeDataCollector outDataCollector )
+ {
+ List<TemplateMultiPassMasterNode> list = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList;
+ int currentSubshader = list[ 0 ].SubShaderIdx;
+ m_templateMultiPass.SetShaderName( string.Format( TemplatesManager.NameFormatter, m_shaderName ) );
+ if( string.IsNullOrEmpty( m_customInspectorName ) )
+ {
+ m_templateMultiPass.SetCustomInspector( string.Empty );
+ }
+ else
+ {
+ m_templateMultiPass.SetCustomInspector( CustomInspectorFormatted );
+ }
+
+ m_templateMultiPass.SetFallback( m_fallbackHelper.FallbackShader );
+ m_templateMultiPass.SetDependencies( m_dependenciesHelper.GenerateDependencies() );
+
+ if( inDataCollector != null )
+ outDataCollector.CopyPropertiesFromDataCollector( inDataCollector );
+
+ outDataCollector.TemplateDataCollectorInstance.CurrentSRPType = m_templateMultiPass.SRPtype;
+
+ int lastActivePass = m_passSelector.LastActivePass;
+ int count = list.Count;
+
+ for( int i = 0; i < count; i++ )
+ {
+ bool removePass = !m_passSelector.IsVisible( i );
+
+ list[ 0 ].CurrentTemplate.IdManager.SetPassIdUsage( i, removePass );
+ if( removePass )
+ continue;
+
+ list[ i ].CollectData();
+ list[ i ].FillPassData( this, outDataCollector.TemplateDataCollectorInstance );
+
+ if( list[ i ].SubShaderIdx == currentSubshader )
+ {
+ outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector );
+ }
+ else
+ {
+ list[ i - 1 ].FillPropertyData( outDataCollector );
+ list[ i - 1 ].FillSubShaderData();
+ outDataCollector.Destroy();
+ outDataCollector = new MasterNodeDataCollector();
+ outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector );
+
+ currentSubshader = list[ i ].SubShaderIdx;
+ }
+
+ // Last element must the one filling subshader data
+ // as only there all properties are caught
+ //if( i == ( count - 1 ) )
+ if( i == lastActivePass )
+ {
+ list[ i ].FillPropertyData( outDataCollector );
+ }
+
+ if( list[ i ].IsMainOutputNode )
+ list[ i ].FillSubShaderData();
+ }
+
+ outDataCollector.TemplateDataCollectorInstance.BuildCBuffer( -1 );
+
+ //Fill uniforms is set on last since we need to collect all srp batcher data ( if needed )
+ //To set it into each pass
+ for( int i = 0; i < count; i++ )
+ {
+ bool removePass = !m_passSelector.IsVisible( i );
+ if( removePass )
+ continue;
+
+ list[ i ].FillUniforms( outDataCollector.TemplateDataCollectorInstance );
+ }
+
+ return list[ 0 ].CurrentTemplate.IdManager.BuildShader();
+ }
+
+ public string BuildLOD( MasterNodeDataCollector inDataCollector, ref MasterNodeDataCollector outDataCollector )
+ {
+ UsageListTemplateMultiPassMasterNodes bufferNodesList = ContainerGraph.MultiPassMasterNodes;
+ int bufferMasterNodeId = ContainerGraph.CurrentMasterNodeId;
+
+ ContainerGraph.MultiPassMasterNodes = ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ];
+ ContainerGraph.CurrentMasterNodeId = UniqueId;
+
+ m_templateMultiPass.ResetState();
+ base.Execute( string.Empty, false );
+ string shaderBody = BuildShaderBody( inDataCollector, ref outDataCollector );
+
+
+ ContainerGraph.MultiPassMasterNodes = bufferNodesList;
+ ContainerGraph.CurrentMasterNodeId = bufferMasterNodeId;
+ return shaderBody;
+ }
+
+ public override Shader Execute( string pathname, bool isFullPath )
+ {
+ ForceReordering();
+ MasterNodeDataCollector overallDataCollector = new MasterNodeDataCollector();
+
+ //BUILD LOD
+ string allLodSubShaders = string.Empty;
+ if( ContainerGraph.HasLODs )
+ {
+ for( int lod = 0; lod < ContainerGraph.LodMultiPassMasternodes.Count; lod++ )
+ {
+ if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count == 0 )
+ break;
+
+ TemplateMultiPassMasterNode newMasterNode = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList.Find( ( x ) => x.IsMainOutputNode );
+ string lodSubShaders = newMasterNode.BuildLOD( null, ref overallDataCollector );
+ lodSubShaders = TemplateHelperFunctions.GetSubShaderFrom( lodSubShaders ) + "\n";
+ allLodSubShaders += lodSubShaders;
+ }
+ }
+
+ //BUILD MAIN
+ m_templateMultiPass.ResetState();
+ base.Execute( pathname, isFullPath );
+ MasterNodeDataCollector dummy = new MasterNodeDataCollector();
+ string shaderBody = BuildShaderBody( overallDataCollector, ref dummy );
+
+ //COMBINE LOD WITH MAIN
+ if( !string.IsNullOrEmpty( allLodSubShaders ) )
+ shaderBody = shaderBody.Replace( TemplatesManager.TemplateLODsTag, allLodSubShaders );
+
+ UpdateShaderAsset( ref pathname, ref shaderBody, isFullPath );
+ return m_currentShader;
+ }
+
+ public void CollectData()
+ {
+ if( m_inputPorts.Count == 0 )
+ return;
+
+ ContainerGraph.ResetNodesLocalVariables();
+ m_optionsDefineContainer.RemoveTemporaries();
+ m_currentDataCollector = new MasterNodeDataCollector( this );
+ m_currentDataCollector.TemplateDataCollectorInstance.SetMultipassInfo( m_templateMultiPass, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType );
+ m_currentDataCollector.TemplateDataCollectorInstance.FillSpecialVariables( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ] );
+ SetupNodeCategories();
+ if( m_containerGraph.IsInstancedShader )
+ {
+ string blockName = UIUtils.RemoveInvalidCharacters( ContainerGraph.GetMainMasterNodeOfLOD( -1 ).ShaderName );
+ m_currentDataCollector.SetupInstancePropertiesBlock( blockName );
+ }
+ TemplateData templateData = m_templateMultiPass.CreateTemplateData( m_shaderName, string.Empty, m_subShaderIdx, m_passIdx );
+ m_currentDataCollector.TemplateDataCollectorInstance.BuildFromTemplateData( m_currentDataCollector, templateData );
+
+ if( m_currentDataCollector.TemplateDataCollectorInstance.InterpData.DynamicMax )
+ {
+ int interpolatorAmount = -1;
+ if( m_passModule.ShaderModelHelper.ValidData )
+ {
+ interpolatorAmount = m_passModule.ShaderModelHelper.InterpolatorAmount;
+ }
+ else
+ {
+ TemplateModulesHelper subShaderModule = IsMainOutputNode ? m_subShaderModule : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).SubShaderModule;
+ if( subShaderModule.ShaderModelHelper.ValidData )
+ {
+ interpolatorAmount = subShaderModule.ShaderModelHelper.InterpolatorAmount;
+ }
+ }
+
+ if( interpolatorAmount > -1 )
+ {
+ m_currentDataCollector.TemplateDataCollectorInstance.InterpData.RecalculateAvailableInterpolators( interpolatorAmount );
+ }
+ }
+
+ //Copy Properties
+ {
+ int shaderPropertiesAmount = m_templateMultiPass.AvailableShaderProperties.Count;
+ for( int i = 0; i < shaderPropertiesAmount; i++ )
+ {
+ m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.AvailableShaderProperties[ i ] );
+ }
+ }
+ //Copy Globals from SubShader level
+ {
+ int subShaderGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals.Count;
+ for( int i = 0; i < subShaderGlobalAmount; i++ )
+ {
+ m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals[ i ] );
+ }
+ }
+ //Copy Globals from Pass Level
+ {
+ int passGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals.Count;
+ for( int i = 0; i < passGlobalAmount; i++ )
+ {
+ m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals[ i ] );
+ }
+ }
+ // Check Current Options for property changes on subshader
+ if( m_isMainOutputNode )
+ {
+ CheckPropertyChangesOnOptions( m_subShaderOptions );
+ }
+
+ // Check Current Options for property changes on pass
+ CheckPropertyChangesOnOptions( m_passOptions );
+
+
+ //Set SRP info
+#if UNITY_2018_3_OR_NEWER
+ if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn )
+ ASEPackageManagerHelper.SetSRPInfoOnDataCollector( ref m_currentDataCollector );
+#endif
+ RegisterStandaloneFuntions();
+ m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector );
+
+ //Sort ports by both
+ List<InputPort> fragmentPorts = new List<InputPort>();
+ List<InputPort> vertexPorts = new List<InputPort>();
+
+ SortInputPorts( ref vertexPorts, ref fragmentPorts );
+
+
+ string shaderBody = templateData.TemplateBody;
+
+ List<string> vertexInstructions = new List<string>();
+ List<string> fragmentInstructions = new List<string>();
+
+ bool validBody = true;
+
+ //validBody = CreateInstructionsForList( templateData, ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+ //ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex );
+ //validBody = CreateInstructionsForList( templateData, ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+ validBody = CreateInstructionsForList( templateData, ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+ validBody = CreateInstructionsForList( templateData, ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody;
+
+ if( !m_isMainOutputNode && m_mainMasterNodeRef == null )
+ {
+ m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode;
+ }
+
+ TerrainDrawInstancedHelper drawInstanced = m_isMainOutputNode ? m_drawInstancedHelper : m_mainMasterNodeRef.DrawInstancedHelperInstance;
+ drawInstanced.UpdateDataCollectorForTemplates( ref m_currentDataCollector, ref vertexInstructions );
+
+ templateData.ResetTemplateUsageData();
+
+ // Fill vertex interpolators assignment
+ for( int i = 0; i < m_currentDataCollector.VertexInterpDeclList.Count; i++ )
+ {
+ vertexInstructions.Add( m_currentDataCollector.VertexInterpDeclList[ i ] );
+ }
+
+ vertexInstructions.AddRange( m_currentDataCollector.TemplateDataCollectorInstance.GetInterpUnusedChannels() );
+
+ //Fill common local variables and operations
+ validBody = m_templateMultiPass.FillVertexInstructions( m_subShaderIdx, m_passIdx, vertexInstructions.ToArray() ) && validBody;
+ validBody = m_templateMultiPass.FillFragmentInstructions( m_subShaderIdx, m_passIdx, fragmentInstructions.ToArray() ) && validBody;
+
+ vertexInstructions.Clear();
+ vertexInstructions = null;
+
+ fragmentInstructions.Clear();
+ fragmentInstructions = null;
+
+ // Add Instanced Properties
+ if( m_containerGraph.IsInstancedShader )
+ {
+ m_currentDataCollector.OptimizeInstancedProperties();
+ m_currentDataCollector.TabifyInstancedVars();
+
+ //string cbufferBegin = m_currentDataCollector.IsSRP ?
+ // string.Format( IOUtils.SRPInstancedPropertiesBegin, "UnityPerMaterial" ) :
+ // string.Format( IOUtils.InstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName );
+ //string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.SRPInstancedPropertiesEnd, m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd;
+ string cbufferBegin = m_currentDataCollector.IsSRP ?
+ string.Format( IOUtils.LWSRPInstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName ) :
+ string.Format( IOUtils.InstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName );
+ string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.LWSRPInstancedPropertiesEnd, m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd;
+
+ m_currentDataCollector.InstancedPropertiesList.Insert( 0, new PropertyDataCollector( -1, cbufferBegin ) );
+ m_currentDataCollector.InstancedPropertiesList.Add( new PropertyDataCollector( -1, cBufferEnd ) );
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.InstancedPropertiesList );
+ }
+
+ if( m_currentDataCollector.DotsPropertiesList.Count > 0 )
+ {
+ m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)" ) );
+ m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "#ifdef UNITY_DOTS_INSTANCING_ENABLED" ) );
+ m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "" ) );
+ m_currentDataCollector.DotsPropertiesList.Add( new PropertyDataCollector( -1, "UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)" ) );
+ m_currentDataCollector.DotsDefinesList.Add( new PropertyDataCollector( -1, "#endif" ) );
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsPropertiesList );
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsDefinesList );
+ }
+
+ TemplateShaderModelModule shaderModelModule = m_isMainOutputNode ? m_subShaderModule.ShaderModelHelper : m_mainMasterNodeRef.SubShaderModule.ShaderModelHelper;
+ string shaderModel = string.Empty;
+ if( m_passModule.ShaderModelHelper.ValidData )
+ {
+ shaderModel = m_passModule.ShaderModelHelper.CurrentShaderModel;
+ }
+ else if( shaderModelModule.ValidData )
+ {
+ shaderModel = shaderModelModule.CurrentShaderModel;
+ }
+ else if( m_templateMultiPass.GlobalShaderModel.IsValid )
+ {
+ shaderModel = m_templateMultiPass.GlobalShaderModel.Value;
+ }
+ else
+ {
+ shaderModel = ( m_templateMultiPass.SRPtype == TemplateSRPType.HD ) ? "4.5" : "3.0";
+ }
+
+ m_currentDataCollector.TemplateDataCollectorInstance.CheckInterpolatorOverflow( shaderModel, m_passName );
+ }
+
+ public void CheckPropertyChangesOnOptions( TemplateOptionsUIHelper optionsUI )
+ {
+ //Only Main LOD master node can change shader properties
+ if( !IsLODMainMasterNode )
+ return;
+
+ List<TemplateOptionUIItem> options = optionsUI.PassCustomOptionsUI;
+ for( int optionIdx = 0; optionIdx < options.Count; optionIdx++ )
+ {
+ if( options[ optionIdx ].IsVisible )
+ {
+ TemplateActionItem[] actionItems = options[ optionIdx ].CurrentOptionActions.Columns;
+ for( int actionIdx = 0; actionIdx < actionItems.Length; actionIdx++ )
+ {
+ if( actionItems[ actionIdx ].ActionType == AseOptionsActionType.SetShaderProperty && !string.IsNullOrEmpty( actionItems[ actionIdx ].ActionBuffer ) )
+ {
+ TemplateShaderPropertyData data = m_templateMultiPass.GetShaderPropertyData( actionItems[ actionIdx ].ActionData );
+ if( data != null )
+ {
+ string newPropertyValue = data.CreatePropertyForValue( actionItems[ actionIdx ].ActionBuffer );
+ CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue );
+ }
+ }
+ }
+
+ if( options[ optionIdx ].Options.Type == AseOptionsType.Field )
+ {
+ foreach( var item in CurrentTemplate.IdManager.RegisteredTags )
+ {
+ if( item.Output.Equals( options[ optionIdx ].Options.FieldInlineName ) )
+ {
+ var node = options[ optionIdx ].Options.FieldValue.GetPropertyNode();
+ if( node != null && ( node.IsConnected || node.AutoRegister ) && options[ optionIdx ].Options.FieldValue.Active )
+ {
+ item.Replacement = node.PropertyName;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ public void FillPropertyData( MasterNodeDataCollector dataCollector = null )
+ {
+ MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector;
+
+#if UNITY_2019_2_OR_NEWER
+ // Temporary hack
+ if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_0 )
+ {
+ if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_AlphaCutoff" ) ) == null )
+ {
+ if( !currDataCollector.ContainsProperty("_AlphaCutoff") )
+ {
+ currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _AlphaCutoff(\"Alpha Cutoff \", Range(0, 1)) = 0.5", -1 );
+ }
+ }
+
+ if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_EmissionColor" ) ) == null )
+ {
+ if( !currDataCollector.ContainsProperty( "_EmissionColor" ) )
+ {
+ currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _EmissionColor(\"Emission Color\", Color) = (1,1,1,1)", -1 );
+ }
+ }
+ }
+#endif
+
+ m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() );
+ }
+
+ public void FillSubShaderData( /*MasterNodeDataCollector dataCollector = null */)
+ {
+ //MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector;
+ //// SubShader Data
+
+ //m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() );
+ //templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModulePass, m_subShaderIdx, currDataCollector.GrabPassList );
+ if( ShaderLOD > -1 )
+ {
+ string lodUniqueId = m_templateMultiPass.SubShaders[ m_subShaderIdx ].UniquePrefix + "Module" + m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id;
+ m_templateMultiPass.IdManager.SetReplacementText( lodUniqueId, "LOD " + ShaderLOD );
+ }
+
+ SetModuleData( m_subShaderModule, true );
+ }
+
+ public void FillPassData( TemplateMultiPassMasterNode masterNode, TemplateDataCollector mainTemplateDataCollector )
+ {
+ if( m_isInvisible != InvisibilityStatus.Visible )
+ {
+ if( masterNode.UniqueId != UniqueId )
+ {
+ if( ( m_invisibleOptions & (int)InvisibleOptionsEnum.SyncProperties ) > 0 )
+ {
+ PassModule.SyncWith( masterNode.PassModule );
+ }
+ }
+
+ int inputCount = m_inputPorts.Count;
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].HasExternalLink )
+ {
+ TemplateMultiPassMasterNode linkedNode = m_inputPorts[ i ].ExternalLinkNode as TemplateMultiPassMasterNode;
+ if( linkedNode != null )
+ {
+ SetLinkedModuleData( linkedNode.PassModule );
+ }
+ }
+ }
+ }
+
+ SetModuleData( m_passModule, false );
+ if( m_currentDataCollector != null )
+ {
+ if( Pass.CustomOptionsContainer.CopyOptionsFromMainPass )
+ {
+ SetPassCustomOptionsInfo( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode );
+ }
+ else
+ {
+ SetPassCustomOptionsInfo( this );
+ }
+
+ var inputArray = m_currentDataCollector.VertexInputList.ToArray();
+
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.PassVertexData, m_subShaderIdx, m_passIdx, inputArray );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.PassInterpolatorData, m_subShaderIdx, m_passIdx, m_currentDataCollector.InterpolatorList.ToArray() );
+ SetHDInfoOnPass();
+ List<PropertyDataCollector> afterNativesIncludePragmaDefineList = new List<PropertyDataCollector>();
+ afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.IncludesList );
+ afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.DefinesList );
+ //includePragmaDefineList.AddRange( m_optionsDefineContainer.DefinesList );
+ afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.PragmasList );
+ afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.AfterNativeDirectivesList );
+
+ //includePragmaDefineList.AddRange( m_currentDataCollector.MiscList );
+
+ List<PropertyDataCollector> beforeNatives = new List<PropertyDataCollector>();
+ beforeNatives.AddRange( m_optionsDefineContainer.DefinesList );
+ beforeNatives.AddRange( m_currentDataCollector.BeforeNativeDirectivesList );
+
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragmaBefore, m_subShaderIdx, m_passIdx, beforeNatives );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragma, m_subShaderIdx, m_passIdx, afterNativesIncludePragmaDefineList );
+
+ m_currentDataCollector.TemplateDataCollectorInstance.CloseLateDirectives();
+
+ //Add Functions
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.FunctionsTag.IsValid )
+ {
+ m_currentDataCollector.FunctionsList.InsertRange( 0, m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleFunctions, m_subShaderIdx, m_passIdx, m_currentDataCollector.FunctionsList );
+ }
+ else
+ {
+ m_currentDataCollector.UniformsList.InsertRange( 0, m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList );
+ m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.FunctionsList );
+ }
+
+ //copy srp batch if present
+ //if( m_currentDataCollector.IsSRP )
+ //{
+ // m_currentDataCollector.UniformsList.AddRange( mainTemplateDataCollector.SrpBatcherPropertiesList );
+ //}
+ //m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals, m_subShaderIdx, m_passIdx, m_currentDataCollector.UniformsList );
+
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputVert, m_subShaderIdx, m_passIdx, m_currentDataCollector.TemplateDataCollectorInstance.VertexInputParamsStr );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputFrag, m_subShaderIdx, m_passIdx, m_currentDataCollector.TemplateDataCollectorInstance.FragInputParamsStr );
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag.IsValid )
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.VControl, m_subShaderIdx, m_passIdx, inputArray );
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.IsValid )
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ControlData, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.GenerateControl( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict, m_currentDataCollector.VertexInputList ) );
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.IsValid )
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.DomainData, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.GenerateDomain( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict, m_currentDataCollector.VertexInputList ) );
+
+ afterNativesIncludePragmaDefineList.Clear();
+ afterNativesIncludePragmaDefineList = null;
+
+ beforeNatives.Clear();
+ beforeNatives = null;
+ }
+
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.PassNameData, m_subShaderIdx, m_passIdx, string.Format( PassNameFormateStr, m_passName ) );
+ }
+
+ public List<PropertyDataCollector> CrossCheckSoftRegisteredUniformList( List<PropertyDataCollector> uniformList )
+ {
+ List<PropertyDataCollector> newItems = new List<PropertyDataCollector>();
+ for( int i = 0; i < uniformList.Count; i++ )
+ {
+ if( !m_currentDataCollector.CheckIfSoftRegistered( uniformList[ i ].PropertyName ) )
+ {
+ newItems.Add( uniformList[ i ] );
+ }
+ }
+ return newItems;
+ }
+
+ public void FillUniforms( TemplateDataCollector mainTemplateDataCollector )
+ {
+ if( m_currentDataCollector.IsSRP )
+ {
+
+ if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPBatcherTag.IsValid )
+ {
+ List<PropertyDataCollector> finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.SrpBatcherPropertiesList );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleSRPBatcher, m_subShaderIdx, m_passIdx, finalList );
+ finalList.Clear();
+ finalList = null;
+ }
+ else
+ {
+ List<PropertyDataCollector> finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.FullSrpBatcherPropertiesList );
+ m_currentDataCollector.UniformsList.AddRange( finalList );
+ finalList.Clear();
+ finalList = null;
+ }
+ }
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals, m_subShaderIdx, m_passIdx, m_currentDataCollector.UniformsList );
+ }
+
+ void SetHDInfoOnPass()
+ {
+#if UNITY_2019_3_OR_NEWER
+ if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 )
+ return;
+#endif
+
+ if( m_currentDataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD )
+ {
+ TemplateModulesHelper subShaderHelper = null;
+ TemplateModulesHelper passHelper = null;
+
+ if( m_isMainOutputNode )
+ {
+ subShaderHelper = m_subShaderModule;
+ passHelper = m_passModule;
+ }
+ else
+ {
+ TemplateMultiPassMasterNode masterNode = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode;
+ if( masterNode != null )
+ {
+ subShaderHelper = masterNode.SubShaderModule;
+ passHelper = masterNode.PassModule;
+ }
+ else
+ {
+ subShaderHelper = m_subShaderModule;
+ passHelper = m_passModule;
+ }
+ }
+
+ RenderQueue renderQueue = RenderQueue.Geometry;
+ RenderType renderType = RenderType.Opaque;
+ if( passHelper.TagsHelper.HasRenderInfo( ref renderType, ref renderQueue ) ||
+ subShaderHelper.TagsHelper.HasRenderInfo( ref renderType, ref renderQueue ) )
+ {
+ if( renderType == RenderType.Transparent && renderQueue == RenderQueue.Transparent )
+ {
+ SetExtraDefine( SRPMaterialTransparentKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransparentKeyword );
+ TemplatesBlendModule blendOpHelper = passHelper.BlendOpHelper.ValidBlendMode ? passHelper.BlendOpHelper : subShaderHelper.BlendOpHelper;
+ if( blendOpHelper.IsAdditiveRGB )
+ {
+ SetExtraDefine( SRPMaterialBlendModeAddKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAddKeyword );
+ }
+ else if( blendOpHelper.IsAlphaBlendRGB )
+ {
+ SetExtraDefine( SRPMaterialBlendModeAlphaKeyword );
+ //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAlphaKeyword );
+ }
+ }
+ }
+ }
+ }
+
+ void SetLinkedModuleData( TemplateModulesHelper linkedModule )
+ {
+ //if( linkedModule.AdditionalPragmas.ValidData )
+ //{
+ // linkedModule.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if( linkedModule.AdditionalIncludes.ValidData )
+ //{
+ // linkedModule.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if( linkedModule.AdditionalDefines.ValidData )
+ //{
+ // linkedModule.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ if( linkedModule.AdditionalDirectives.ValidData )
+ {
+ linkedModule.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ }
+ }
+
+ void SetModuleData( TemplateModulesHelper module, bool isSubShader )
+ {
+ if( isSubShader )
+ {
+
+ //if ( module.AdditionalPragmas.ValidData )
+ //{
+ // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if ( module.AdditionalIncludes.ValidData )
+ //{
+ // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if ( module.AdditionalDefines.ValidData )
+ //{
+ // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ if( module.AdditionalDirectives.ValidData )
+ {
+ module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer );
+ }
+
+ if( module.TagsHelper.ValidData )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleTag, m_subShaderIdx, module.TagsHelper.GenerateTags() );
+ }
+
+ if( module.AllModulesMode )
+ {
+ string body = module.GenerateAllModulesString( isSubShader );
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.AllModules, m_subShaderIdx, body.Split( '\n' ) );
+ }
+
+ if( module.ShaderModelHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleShaderModel, m_subShaderIdx, module.ShaderModelHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode, m_subShaderIdx, module.BlendOpHelper.CurrentBlendFactor );
+ }
+
+ if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp, m_subShaderIdx, module.BlendOpHelper.CurrentBlendOp );
+ }
+
+ if( module.BlendOpHelper.AlphaToMaskIndependent && module.BlendOpHelper.ValidAlphaToMask )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleAlphaToMask, m_subShaderIdx, module.BlendOpHelper.CurrentAlphaToMask );
+ }
+
+ if( module.CullModeHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleCullMode, m_subShaderIdx, module.CullModeHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.ColorMaskHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask, m_subShaderIdx, module.ColorMaskHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZTest, m_subShaderIdx, module.DepthOphelper.CurrentZTestMode );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZwrite, m_subShaderIdx, module.DepthOphelper.CurrentZWriteMode );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset )
+ {
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZOffset, m_subShaderIdx, module.DepthOphelper.CurrentOffset );
+ }
+
+ if( module.StencilBufferHelper.ValidAndIndependent )
+ {
+ CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back;
+ string value = module.StencilBufferHelper.CreateStencilOp( cullMode );
+ m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleStencil, m_subShaderIdx, value.Split( '\n' ) );
+ }
+
+ }
+ else
+ {
+ //if ( module.AdditionalPragmas.ValidData )
+ //{
+ // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if ( module.AdditionalIncludes.ValidData )
+ //{
+ // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+
+ //if ( module.AdditionalDefines.ValidData )
+ //{
+ // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ //}
+ List<PropertyDataCollector> aboveUsePass = new List<PropertyDataCollector>();
+ List<PropertyDataCollector> belowUsePass = new List<PropertyDataCollector>();
+ m_usePass.BuildUsePassInfo( m_currentDataCollector, ref aboveUsePass, ref belowUsePass );
+ //TODO Must place this on the correct place
+ aboveUsePass.AddRange( belowUsePass );
+
+ //adding grab pass after use pass on purpose, so it wont be caught by them
+ aboveUsePass.AddRange( m_currentDataCollector.GrabPassList );
+
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePass, m_subShaderIdx, m_passIdx, aboveUsePass );
+ //m_templateMultiPass.SetPassData( TemplateModuleDataType.EndPass, m_subShaderIdx, m_passIdx, bellowUsePass);
+
+ if( module.AdditionalDirectives.ValidData )
+ {
+ module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer );
+ }
+
+ if( module.TagsHelper.ValidData )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleTag, m_subShaderIdx, m_passIdx, module.TagsHelper.GenerateTags() );
+ }
+
+ if( module.AllModulesMode )
+ {
+ string body = module.GenerateAllModulesString( isSubShader );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.AllModules, m_subShaderIdx, m_passIdx, body.Split( '\n' ) );
+ }
+
+ if( module.ShaderModelHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleShaderModel, m_subShaderIdx, m_passIdx, module.ShaderModelHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode, m_subShaderIdx, m_passIdx, module.BlendOpHelper.CurrentBlendFactor );
+ }
+
+ if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp, m_subShaderIdx, m_passIdx, module.BlendOpHelper.CurrentBlendOp );
+ }
+
+ if( module.BlendOpHelper.AlphaToMaskIndependent && module.BlendOpHelper.ValidAlphaToMask )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleAlphaToMask, m_subShaderIdx, m_passIdx, module.BlendOpHelper.CurrentAlphaToMask );
+ }
+
+ if( module.CullModeHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleCullMode, m_subShaderIdx, m_passIdx, module.CullModeHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.ColorMaskHelper.ValidAndIndependent )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask, m_subShaderIdx, m_passIdx, module.ColorMaskHelper.GenerateShaderData( isSubShader ) );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZTest, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentZTestMode );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZwrite, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentZWriteMode );
+ }
+
+ if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset )
+ {
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZOffset, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentOffset );
+ }
+
+ if( module.StencilBufferHelper.ValidAndIndependent )
+ {
+ CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back;
+ string value = module.StencilBufferHelper.CreateStencilOp( cullMode );
+ m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleStencil, m_subShaderIdx, m_passIdx, value.Split( '\n' ) );
+ }
+ }
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ return "0";
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+
+ m_drawInstancedHelper = null;
+
+ m_optionsDefineContainer.Destroy();
+ m_optionsDefineContainer = null;
+
+ m_passSelector.Destroy();
+ m_passSelector = null;
+
+ m_subShaderOptions.Destroy();
+ m_passOptions.Destroy();
+
+ m_fallbackHelper.Destroy();
+ GameObject.DestroyImmediate( m_fallbackHelper );
+ m_fallbackHelper = null;
+
+ m_usePass.Destroy();
+ GameObject.DestroyImmediate( m_usePass );
+ m_usePass = null;
+
+ m_dependenciesHelper.Destroy();
+ m_dependenciesHelper = null;
+
+ m_subShaderModule.Destroy();
+ m_subShaderModule = null;
+ m_passModule.Destroy();
+ m_passModule = null;
+ if( m_lodIndex == -1 )
+ {
+ ContainerGraph.MultiPassMasterNodes.RemoveNode( this );
+ }
+ else
+ {
+ ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ].RemoveNode( this );
+ }
+ }
+
+ void UpdateSubShaderPassStr()
+ {
+ //m_subShaderIdxStr = SubShaderModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Idx;
+ //m_passIdxStr = PassModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Idx;
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+
+ base.ReadFromString( ref nodeParams );
+ try
+ {
+ string currShaderName = GetCurrentParam( ref nodeParams );
+ if( currShaderName.Length > 0 )
+ currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName );
+
+ m_templateGUID = GetCurrentParam( ref nodeParams );
+ bool hasUniqueName = false;
+ if( UIUtils.CurrentShaderVersion() > PASS_UNIQUE_ID_VERSION )
+ {
+ hasUniqueName = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
+ }
+
+ if( hasUniqueName )
+ m_passUniqueId = GetCurrentParam( ref nodeParams );
+
+ m_subShaderIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ m_passIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ if( UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION )
+ {
+
+ if( m_lodIndex != -1 )
+ {
+ m_containerGraph.MultiPassMasterNodes.RemoveNode( this );
+ m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this );
+ }
+ }
+
+ m_passName = GetCurrentParam( ref nodeParams );
+ SetTemplate( null, false, true, m_subShaderIdx, m_passIdx, SetTemplateSource.ShaderLoad );
+ ////If value gotten from template is > -1 then it contains the LOD field
+ ////and we can properly write the value
+ //if( m_subShaderLOD > -1 )
+ //{
+ // m_subShaderLOD = subShaderLOD;
+ //}
+
+ // only in here, after SetTemplate, we know if shader name is to be used as title or not
+ ShaderName = currShaderName;
+ m_visiblePorts = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ m_subShaderModule.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ m_passModule.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ if( UIUtils.CurrentShaderVersion() > 15308 )
+ {
+ m_fallbackHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ m_dependenciesHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 15402 )
+ {
+ m_usePass.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 15409 )
+ {
+ m_hdSrpMaterialType = (HDSRPMaterialType)Enum.Parse( typeof( HDSRPMaterialType ), GetCurrentParam( ref nodeParams ) );
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 15501 )
+ {
+ if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION )
+ m_subShaderOptions.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+
+ m_passOptions.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION )
+ {
+ m_passSelector.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > 16203 )
+ {
+ m_drawInstancedHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION )
+ {
+ m_mainLODName = GetCurrentParam( ref nodeParams );
+ SetupLODNodeName();
+ }
+ else
+ {
+ m_content.text = GenerateClippedTitle( m_passName );
+ }
+
+
+ //if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass )
+ //{
+ // SetClippedTitle( m_passName );
+ //}
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e, this );
+ }
+
+ m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader;
+ m_containerGraph.CurrentPrecision = m_currentPrecisionType;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, ShaderName );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_templateGUID );
+
+ bool hasUniquePassName = Pass.Modules.HasPassUniqueName;
+ IOUtils.AddFieldValueToString( ref nodeInfo, hasUniquePassName );
+ if( hasUniquePassName )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, Pass.Modules.PassUniqueName );
+ }
+
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_subShaderIdx );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passIdx );
+
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passName );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_visiblePorts );
+ m_subShaderModule.WriteToString( ref nodeInfo );
+ m_passModule.WriteToString( ref nodeInfo );
+ m_fallbackHelper.WriteToString( ref nodeInfo );
+ m_dependenciesHelper.WriteToString( ref nodeInfo );
+ m_usePass.WriteToString( ref nodeInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_hdSrpMaterialType );
+ if( m_isMainOutputNode )
+ m_subShaderOptions.WriteToString( ref nodeInfo );
+
+ m_passOptions.WriteToString( ref nodeInfo );
+
+ if( m_isMainOutputNode )
+ {
+ m_passSelector.WriteToString( ref nodeInfo );
+ m_drawInstancedHelper.WriteToString( ref nodeInfo );
+ }
+
+ if( m_isMainOutputNode )
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_mainLODName );
+
+ }
+
+ public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null )
+ {
+ base.ReadFromString( ref nodeParams );
+ try
+ {
+ string currShaderName = GetCurrentParam( ref nodeParams );
+ if( currShaderName.Length > 0 )
+ currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName );
+
+ string templateGUID = GetCurrentParam( ref nodeParams );
+ string templateShaderName = string.Empty;
+ if( UIUtils.CurrentShaderVersion() > 13601 )
+ {
+ templateShaderName = GetCurrentParam( ref nodeParams );
+ }
+
+ TemplateMultiPass template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ) as TemplateMultiPass;
+ if( template != null )
+ {
+ m_templateGUID = templateGUID;
+ SetTemplate( null, false, true, 0, 0,SetTemplateSource.ShaderLoad );
+ }
+ else
+ {
+ template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplateByName( templateShaderName ) as TemplateMultiPass;
+ if( template != null )
+ {
+ m_templateGUID = template.GUID;
+ SetTemplate( null, false, true, 0, 0, SetTemplateSource.ShaderLoad );
+ }
+ else
+ {
+ m_masterNodeCategory = -1;
+ }
+ }
+
+ if( m_invalidNode )
+ return;
+
+ // only in here, after SetTemplate, we know if shader name is to be used as title or not
+ ShaderName = currShaderName;
+ if( UIUtils.CurrentShaderVersion() > 13902 )
+ {
+
+ //BLEND MODULE
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendMode )
+ {
+ m_subShaderModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendMode )
+ {
+ m_passModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendOp )
+ {
+ m_subShaderModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendOp )
+ {
+ m_passModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+
+ //CULL MODE
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_subShaderModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_passModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ //COLOR MASK
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_subShaderModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_passModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ //STENCIL BUFFER
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_subShaderModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_passModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 14202 )
+ {
+ //DEPTH OPTIONS
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZWrite )
+ {
+ m_subShaderModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZWrite )
+ {
+ m_passModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZTest )
+ {
+ m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZTest )
+ {
+ m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidOffset )
+ {
+ m_subShaderModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidOffset )
+ {
+ m_passModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ }
+
+ //TAGS
+ if( UIUtils.CurrentShaderVersion() > 14301 )
+ {
+ if( m_templateMultiPass.SubShaders[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_subShaderModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+ else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid )
+ {
+ m_passModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
+ }
+
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e, this );
+ }
+ m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader;
+ }
+
+ public void ForceOptionsRefresh()
+ {
+ m_passOptions.Refresh();
+ if( m_isMainOutputNode )
+ m_subShaderOptions.Refresh();
+ }
+
+ public void SetPassVisible( string passName, bool visible )
+ {
+ TemplateMultiPassMasterNode node = m_containerGraph.GetMasterNodeOfPass( passName, m_lodIndex );
+ if( node != null )
+ {
+ m_passSelector.SetPassVisible( passName, visible );
+ node.IsInvisible = !visible;
+ }
+
+ }
+
+ public override void RefreshExternalReferences()
+ {
+ if( m_invalidNode )
+ return;
+
+ base.RefreshExternalReferences();
+ if( IsLODMainMasterNode )
+ {
+ SetMasterNodeCategoryFromGUID( m_templateGUID );
+ }
+
+ CheckTemplateChanges();
+ if( m_templateMultiPass != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD && UIUtils.CurrentShaderVersion() < 15410 )
+ {
+ FetchHDPorts();
+ m_hdSrpMaterialType = ( m_specularPort != null && m_specularPort.HasOwnOrLinkConnection ) ? HDSRPMaterialType.Specular : HDSRPMaterialType.Standard;
+ ConfigHDPorts();
+ }
+
+ if( ContainerGraph.HasLODs )
+ {
+ SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) );
+ }
+
+ if( m_isMainOutputNode )
+ {
+ List<TemplateMultiPassMasterNode> masterNodes = ( m_lodIndex == -1 ) ? m_containerGraph.MultiPassMasterNodes.NodesList : m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].NodesList;
+ masterNodes.Sort( ( x, y ) => ( x.PassIdx.CompareTo( y.PassIdx ) ));
+ int passAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].PassAmount;
+ if( passAmount != masterNodes.Count )
+ {
+ UIUtils.ShowMessage( "Template master nodes amount was modified. Could not set correctly its visibility options." );
+ }
+ else
+ {
+ for( int i = 0; i < passAmount; i++ )
+ {
+ if( i != m_passIdx )
+ {
+ masterNodes[ i ].IsInvisible = !m_passSelector.IsVisible( i );
+ }
+ }
+ }
+ }
+ }
+
+ public override void ReadInputDataFromString( ref string[] nodeParams )
+ {
+ //For a Template Master Node an input port data must be set by its template and not meta data
+ if( UIUtils.CurrentShaderVersion() > 17007 )
+ return;
+
+ int count = 0;
+ if( UIUtils.CurrentShaderVersion() > 7003 )
+ {
+ try
+ {
+ count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ else
+ {
+ count = ( m_oldInputCount < 0 ) ? m_inputPorts.Count : m_oldInputCount;
+ }
+
+ for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ )
+ {
+ if( UIUtils.CurrentShaderVersion() < 5003 )
+ {
+ int newId = VersionConvertInputPortId( i );
+ if( UIUtils.CurrentShaderVersion() > 23 )
+ {
+ m_currentReadParamIdx++;
+ }
+
+ m_currentReadParamIdx++;
+ if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length )
+ {
+ m_currentReadParamIdx++;
+ }
+ }
+ else
+ {
+ m_currentReadParamIdx++;
+ m_currentReadParamIdx++;
+ m_currentReadParamIdx++;
+ bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] );
+ if( isEditable && m_currentReadParamIdx < nodeParams.Length )
+ {
+ m_currentReadParamIdx++;
+ }
+ }
+ }
+ }
+
+ //For a Template Master Node an input port data must be set by its template and not meta data
+ public override void WriteInputDataToString( ref string nodeInfo ) { }
+
+ public override float HeightEstimate
+ {
+ get
+ {
+ float heightEstimate = 0;
+ heightEstimate = 32 + Constants.INPUT_PORT_DELTA_Y;
+ if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass )
+ {
+ heightEstimate += 22;
+ }
+ float internalPortSize = 0;
+ for( int i = 0; i < InputPorts.Count; i++ )
+ {
+ if( InputPorts[ i ].Visible )
+ internalPortSize += 18 + Constants.INPUT_PORT_DELTA_Y;
+ }
+
+ return heightEstimate + Mathf.Max( internalPortSize, m_insideSize.y );
+ }
+ }
+
+ public HDSRPMaterialType CurrentHDMaterialType
+ {
+ get { return m_hdSrpMaterialType; }
+ set
+ {
+ m_hdSrpMaterialType = value;
+ if( m_isMainOutputNode )
+ {
+ List<TemplateMultiPassMasterNode> mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList;
+ int count = mpNodes.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( mpNodes[ i ].UniqueId != UniqueId )
+ {
+ mpNodes[ i ].CurrentHDMaterialType = value;
+ }
+ }
+ }
+ }
+ }
+ public TemplateSubShader SubShader { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ]; } }
+ public TemplatePass Pass { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ]; } }
+ public int SubShaderIdx { get { return m_subShaderIdx; } }
+ public int PassIdx { get { return m_passIdx; } }
+ public TemplateMultiPass CurrentTemplate { get { return m_templateMultiPass; } }
+ public TemplateModulesHelper SubShaderModule { get { return m_subShaderModule; } }
+ public TemplateModulesHelper PassModule { get { return m_passModule; } }
+ public string PassName { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; } }
+ public string PassUniqueName
+ {
+ get
+ {
+ return string.IsNullOrEmpty( m_passUniqueId ) ? m_originalPassName : m_passUniqueId;
+ }
+ }
+
+ public string OriginalPassName { get { return m_originalPassName; } }
+ public bool HasLinkPorts { get { return m_hasLinkPorts; } }
+ public bool IsInvisible
+ {
+ get
+ {
+ return m_isInvisible != InvisibilityStatus.Visible;
+ }
+ set
+ {
+ if( m_isInvisible != InvisibilityStatus.LockedInvisible && !m_isMainOutputNode )
+ {
+ m_isInvisible = value ? InvisibilityStatus.Invisible : InvisibilityStatus.Visible;
+ if( value )
+ {
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ m_inputPorts[ i ].FullDeleteConnections();
+ }
+ }
+ }
+ }
+ }
+
+ public TemplatePassSelectorHelper PassSelector { get { return m_passSelector; } }
+ public TemplateOptionsUIHelper PassOptions { get { return m_passOptions; } }
+ public TemplateOptionsUIHelper SubShaderOptions { get { return m_subShaderOptions; } }
+ public TemplateOptionsDefinesContainer OptionsDefineContainer { get { return m_optionsDefineContainer; } }
+ public TerrainDrawInstancedHelper DrawInstancedHelperInstance { get { return m_drawInstancedHelper; } }
+ public bool InvalidNode { get { return m_invalidNode; } }
+ public override void SetName( string name )
+ {
+ ShaderName = name;
+ }
+ public bool IsLODMainFirstPass { get { return m_passIdx == 0 && m_lodIndex == -1; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta
new file mode 100644
index 00000000..a96d88d0
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassMasterNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fce684c26c654d14e927860863cd99dd
+timeCreated: 1517406883
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs
new file mode 100644
index 00000000..e8aeadf8
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs
@@ -0,0 +1,328 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+
+ [Serializable]
+ public class InputSwitchMPHelper
+ {
+ public int SubShaderIdx;
+ public int PassIdx;
+ public InputSwitchMPHelper( int subShaderIdx, int passIdx )
+ {
+ SubShaderIdx = subShaderIdx;
+ PassIdx = passIdx;
+ }
+ }
+
+ [Serializable]
+ [NodeAttributes( "Template Multi-Pass Switch", "Logical Operators", "Relays, in compile time, the correct input port according to current analyzed sub-shader/pass." )]
+ public sealed class TemplateMultiPassSwitchNode : TemplateNodeParent
+ {
+ private const string InputLabelStr = "SubShader {0} Pass {1}";
+
+ [SerializeField]
+ private List<InputSwitchMPHelper> m_inputHelper = new List<InputSwitchMPHelper>();
+
+ [SerializeField]
+ private int m_inputCountHelper = -1;
+
+ protected override void CommonInit( int uniqueId )
+ {
+ m_createAllOutputs = false;
+ base.CommonInit( uniqueId );
+ }
+
+ public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
+ {
+ base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
+ UpdateConnections();
+ }
+
+ public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
+ {
+ base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type );
+ UpdateConnections();
+ }
+
+ public override void OnInputPortDisconnected( int portId )
+ {
+ base.OnInputPortDisconnected( portId );
+ UpdateConnections();
+ }
+
+ private void UpdateConnections()
+ {
+ WirePortDataType mainType = WirePortDataType.FLOAT;
+
+ int highest = UIUtils.GetPriority( mainType );
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ WirePortDataType portType = m_inputPorts[ i ].GetOutputConnection().DataType;
+ if( UIUtils.GetPriority( portType ) > highest )
+ {
+ mainType = portType;
+ highest = UIUtils.GetPriority( portType );
+ }
+ }
+ }
+
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ m_inputPorts[ i ].ChangeType( mainType, false );
+ }
+
+ m_outputPorts[ 0 ].ChangeType( mainType, false );
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ base.Draw( drawInfo );
+
+ if( m_templateMPData == null )
+ {
+ FetchMultiPassTemplate();
+ if( m_inputPorts.Count != m_inputCountHelper )
+ {
+ CreateInputPorts();
+ }
+ else
+ {
+ RefreshInputPorts();
+ }
+ }
+ }
+
+
+ public void RefreshInputPorts()
+ {
+ if( m_multiPassMode )
+ {
+ m_inputHelper.Clear();
+ if( m_templateMPData != null )
+ {
+ int index = 0;
+ int subShaderCount = m_templateMPData.SubShaders.Count;
+ for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ )
+ {
+ int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody )
+ {
+ m_inputPorts[ index ].Name = string.Format( InputLabelStr, subShaderIdx, passIdx );
+ m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx ) );
+ index += 1;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_inputPorts[0].Name = "In";
+ }
+ }
+
+ public int RefreshInputCountHelper()
+ {
+ int inputCountHelper = 0;
+ if( m_multiPassMode )
+ {
+ if( m_templateMPData != null )
+ {
+ int subShaderCount = m_templateMPData.SubShaders.Count;
+ for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ )
+ {
+ int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[passIdx].HasValidFunctionBody )
+ inputCountHelper += 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ inputCountHelper += 1;
+ }
+ return inputCountHelper;
+ }
+
+ public void CreateInputPorts()
+ {
+ m_inputCountHelper = 0;
+ DeleteAllInputConnections( true );
+ if( m_multiPassMode )
+ {
+ m_inputHelper.Clear();
+ if( m_templateMPData != null )
+ {
+ int subShaderCount = m_templateMPData.SubShaders.Count;
+ for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ )
+ {
+ int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody )
+ {
+ AddInputPort( WirePortDataType.FLOAT, false, string.Format( InputLabelStr, subShaderIdx, passIdx ) );
+ m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx ) );
+ m_inputCountHelper += 1;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ AddInputPort( WirePortDataType.FLOAT, false, "In" );
+ m_inputCountHelper += 1;
+ }
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template )
+ {
+ UIUtils.ShowMessage( "Template Multi-Pass Switch Data node is only intended for templates use only" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ int currSubShaderIdx = dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx;
+ int currPassIdx = dataCollector.TemplateDataCollectorInstance.MultipassPassIdx;
+
+ int inputHelperCount = m_inputHelper.Count;
+ for( int i = 0; i< inputHelperCount; i++ )
+ {
+ if(m_inputHelper[i].SubShaderIdx == currSubShaderIdx && m_inputHelper[ i ].PassIdx == currPassIdx )
+ return m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector );
+ }
+
+ UIUtils.ShowMessage( "Invalid subshader or pass on Template Multi-Pass Switch Data" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ public override void OnMasterNodeReplaced( MasterNode newMasterNode )
+ {
+ base.OnMasterNodeReplaced( newMasterNode );
+ if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ FetchMultiPassTemplate( newMasterNode );
+ m_inputCountHelper = RefreshInputCountHelper();
+ if( m_inputPorts.Count != m_inputCountHelper )
+ {
+ CreateInputPorts();
+ }
+ else
+ {
+ RefreshInputPorts();
+ }
+ }
+ else
+ {
+ DeleteAllInputConnections( true );
+ }
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ m_inputCountHelper = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ // Need to add ports here so read internal data is correct
+ for( int i = 0; i < m_inputCountHelper; i++ )
+ {
+ AddInputPort( WirePortDataType.FLOAT, false, Constants.EmptyPortValue );
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputCountHelper );
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_inputHelper.Clear();
+ m_inputHelper = null;
+ }
+
+ public override void RefreshExternalReferences()
+ {
+ base.RefreshExternalReferences();
+ FetchMultiPassTemplate();
+
+ bool create = false;
+ if( m_inputCountHelper == -1 )
+ {
+ create = true;
+ }
+ else
+ {
+ int newInputCount = RefreshInputCountHelper();
+ if( newInputCount != m_inputCountHelper )
+ {
+ create = true;
+ }
+ }
+
+
+ if( m_multiPassMode )
+ {
+ if( m_templateMPData != null )
+ {
+ if( create )
+ {
+ CreateInputPorts();
+ }
+ else
+ {
+ m_inputHelper.Clear();
+ int index = 0;
+ int subShaderCount = m_templateMPData.SubShaders.Count;
+ for( int subShaderIdx = 0; subShaderIdx < subShaderCount; subShaderIdx++ )
+ {
+ int passCount = m_templateMPData.SubShaders[ subShaderIdx ].Passes.Count;
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ if( m_templateMPData.SubShaders[ subShaderIdx ].Passes[ passIdx ].HasValidFunctionBody )
+ {
+ m_inputPorts[ index ].Name = string.Format( InputLabelStr, subShaderIdx, passIdx );
+ m_inputHelper.Add( new InputSwitchMPHelper( subShaderIdx, passIdx ));
+ index += 1;
+ }
+ }
+ }
+
+ if( index != m_inputCountHelper )
+ {
+ Debug.LogWarning( "Something wrong occured in reading MultiPass Switch node" );
+ }
+ }
+ }
+ }
+ else
+ {
+ if( create )
+ {
+ AddInputPort( WirePortDataType.FLOAT, false, "In" );
+ }
+ else
+ {
+ m_inputPorts[ 0 ].Name = "In";
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta
new file mode 100644
index 00000000..4aafb59d
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateMultiPassSwitchNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 58e4eb5fc3fed124384eef956c6c3ee1
+timeCreated: 1519319737
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs
new file mode 100644
index 00000000..1bfc8aa9
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs
@@ -0,0 +1,272 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateNodeParent : ParentNode
+ {
+
+
+ protected const string ErrorMessageStr = "This node can only be used inside a Template category!";
+ protected const string DataLabelStr = "Data";
+ protected const string SubShaderStr = "SubShader";
+ protected const string PassStr = "Pass";
+
+ [SerializeField]
+ private int m_subShaderIdx = 0;
+
+ [SerializeField]
+ private int m_passIdx = 0;
+
+ [SerializeField]
+ private int m_passLocalArrayIdx = 0;
+
+ [SerializeField]
+ protected bool m_multiPassMode = false;
+
+ [SerializeField]
+ protected string[] m_availableSubshaders;
+
+ [SerializeField]
+ protected string[] m_availablePassesLabels;
+
+ [SerializeField]
+ protected int[] m_availablePassesValues;
+
+ [NonSerialized]
+ protected TemplateMultiPass m_templateMPData = null;
+ protected bool m_createAllOutputs = true;
+
+ protected override void CommonInit( int uniqueId )
+ {
+ base.CommonInit( uniqueId );
+ AddOutputPort( WirePortDataType.FLOAT, "Out" );
+ if( m_createAllOutputs )
+ {
+ AddOutputPort( WirePortDataType.FLOAT, "X" );
+ AddOutputPort( WirePortDataType.FLOAT, "Y" );
+ AddOutputPort( WirePortDataType.FLOAT, "Z" );
+ AddOutputPort( WirePortDataType.FLOAT, "W" );
+ }
+ m_textLabelWidth = 67;
+ m_hasLeftDropdown = true;
+ }
+
+ public override void AfterCommonInit()
+ {
+ base.AfterCommonInit();
+
+ if( PaddingTitleLeft == 0 )
+ {
+ PaddingTitleLeft = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin;
+ if( PaddingTitleRight == 0 )
+ PaddingTitleRight = Constants.PropertyPickerWidth + Constants.IconsLeftRightMargin;
+ }
+ }
+
+ protected void ConfigurePorts()
+ {
+ switch( m_outputPorts[ 0 ].DataType )
+ {
+ default:
+ {
+ for( int i = 1; i < 5; i++ )
+ {
+ m_outputPorts[ i ].Visible = false;
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT2:
+ {
+ for( int i = 1; i < 5; i++ )
+ {
+ m_outputPorts[ i ].Visible = ( i < 3 );
+ if( m_outputPorts[ i ].Visible )
+ {
+ m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ];
+ }
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT3:
+ {
+ for( int i = 1; i < 5; i++ )
+ {
+ m_outputPorts[ i ].Visible = ( i < 4 );
+ if( m_outputPorts[ i ].Visible )
+ {
+ m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ];
+ }
+ }
+ }
+ break;
+ case WirePortDataType.FLOAT4:
+ {
+ for( int i = 1; i < 5; i++ )
+ {
+ m_outputPorts[ i ].Visible = true;
+ m_outputPorts[ i ].Name = Constants.ChannelNamesVector[ i - 1 ];
+ }
+ }
+ break;
+ case WirePortDataType.COLOR:
+ {
+ for( int i = 1; i < 5; i++ )
+ {
+ m_outputPorts[ i ].Visible = true;
+ m_outputPorts[ i ].Name = Constants.ChannelNamesColor[ i - 1 ];
+ }
+ }
+ break;
+ }
+ m_sizeIsDirty = true;
+ }
+
+ protected virtual void OnSubShaderChange() { }
+ protected virtual void OnPassChange() { }
+
+ protected void DrawSubShaderUI()
+ {
+ EditorGUI.BeginChangeCheck();
+ m_subShaderIdx = EditorGUILayoutPopup( SubShaderStr, m_subShaderIdx, m_availableSubshaders );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ //UpdateSubShaderAmount();
+ UpdatePassAmount();
+ OnSubShaderChange();
+ }
+ }
+
+ protected void DrawPassUI()
+ {
+ EditorGUI.BeginChangeCheck();
+ m_passLocalArrayIdx = EditorGUILayoutPopup( PassStr, m_passLocalArrayIdx, m_availablePassesLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_passIdx = m_availablePassesValues[ m_passLocalArrayIdx ];
+ //UpdatePassAmount();
+ OnPassChange();
+ }
+ }
+
+ virtual protected void CheckWarningState()
+ {
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ {
+ ShowTab( NodeMessageType.Error, ErrorMessageStr );
+ }
+ else
+ {
+ m_showErrorMessage = false;
+ }
+ }
+
+ protected void FetchMultiPassTemplate( MasterNode masterNode = null )
+ {
+ m_multiPassMode = m_containerGraph.MultiPassMasterNodes.NodesList.Count > 0;
+ if( m_multiPassMode )
+ {
+ m_templateMPData = ( ( ( masterNode == null ) ? m_containerGraph.CurrentMasterNode : masterNode ) as TemplateMultiPassMasterNode ).CurrentTemplate;
+ if( m_templateMPData != null )
+ {
+ UpdateSubShaderAmount();
+ }
+ }
+ }
+
+ protected void UpdateSubShaderAmount()
+ {
+ if( m_templateMPData == null )
+ m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate;
+
+ if( m_templateMPData != null )
+ {
+ int subShaderCount = m_templateMPData.SubShaders.Count;
+ if( m_availableSubshaders == null || subShaderCount != m_availableSubshaders.Length )
+ {
+ m_availableSubshaders = new string[ subShaderCount ];
+ for( int i = 0; i < subShaderCount; i++ )
+ {
+ m_availableSubshaders[ i ] = i.ToString();
+ }
+ }
+ m_subShaderIdx = Mathf.Min( m_subShaderIdx, subShaderCount - 1 );
+ UpdatePassAmount();
+ }
+ }
+ protected virtual bool ValidatePass( int passIdx ) { return true; }
+ protected void UpdatePassAmount()
+ {
+ if( !m_multiPassMode )
+ return;
+
+ if( m_templateMPData == null )
+ m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate;
+
+ List<string> passLabels = new List<string>();
+ List<int> passValues = new List<int>();
+ int minPassIdx = int.MaxValue;
+ int passCount = m_templateMPData.SubShaders[ m_subShaderIdx ].Passes.Count;
+ bool resetPassIdx = true;
+ for( int i = 0; i < passCount; i++ )
+ {
+ if( ValidatePass( i ) )
+ {
+ passLabels.Add( i.ToString() );
+ passValues.Add( i );
+ minPassIdx = Mathf.Min( minPassIdx, i );
+ if( m_passIdx == i )
+ resetPassIdx = false;
+ }
+ }
+ m_availablePassesLabels = passLabels.ToArray();
+ m_availablePassesValues = passValues.ToArray();
+ if( resetPassIdx )
+ m_passIdx = minPassIdx;
+
+ RefreshPassLocalArrayIdx();
+ }
+
+ void RefreshPassLocalArrayIdx( )
+ {
+ for( int i = 0; i < m_availablePassesValues.Length; i++ )
+ {
+ if( m_availablePassesValues[ i ] == m_passIdx )
+ {
+ m_passLocalArrayIdx = i;
+ }
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_templateMPData = null;
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ m_subShaderIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ m_passIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_subShaderIdx );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passIdx );
+ }
+ public int SubShaderIdx { get { return m_subShaderIdx; } }
+ public int PassIdx { get { return m_passIdx; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta
new file mode 100644
index 00000000..134dcd6c
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateNodeParent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b21cb297a12ef0a4281213619e3e76bf
+timeCreated: 1519235586
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs
new file mode 100644
index 00000000..afebbc85
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs
@@ -0,0 +1,958 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ /*ase_pass_options OLDEST
+ DefineOnConnected:portId:definevalue
+ DefineOnUnconnected:portId:definevalue
+ Options:name:defaultOption:opt0:opt1:opt2
+ SetVisible:PortId:OptionName:OptionValue
+ */
+
+ /*ase_pass_options OLD
+ Option:Option Name:UI Type:Default:Item0,Item1,Item3...ItemN
+ Action:Action Type:Action Data:ConditionA && ConditionB || ConditionC:
+ */
+
+ /*ase_pass_options:UniqueId:PropagateDataToHiddenPasses
+ Option:Color Offset:A,B,C:A
+ A:ShowPort:My Port Name
+ B,C:HidePort:My Port Name
+ B:SetDefine:MY_DEFINE
+ C:SetDefine:MY_COLOR_DEFINE
+ Option:My Other Option:True,False
+ True:ShowOption:Color Offset
+ False:HideOption:Color Offset
+ Port:My Port Name
+ On:SetDefine:MY_COLOR_DEFINE
+ Off:UnsetDefine:MY_COLOR_DEFINE
+ */
+ public enum AseOptionsUIWidget
+ {
+ Dropdown,
+ Toggle,
+ Float,
+ FloatRange,
+ Int,
+ IntRange
+ }
+
+ public enum AseOptionsType
+ {
+ Option,
+ Port,
+ Field
+ }
+
+
+ public enum AseOptionItemSetup
+ {
+ None,
+ InvertActionOnDeselection
+ }
+
+ public enum AseOptionsActionType
+ {
+ ShowOption,
+ HideOption,
+ SetOption,
+ HidePort,
+ ShowPort,
+ SetPortName,
+ SetDefine,
+ RemoveDefine,
+ SetUndefine,
+ RemoveUndefine,
+ ExcludePass,
+ IncludePass,
+ SetPropertyOnPass,
+ SetPropertyOnSubShader,
+ SetShaderProperty,
+ SetMaterialProperty
+ }
+
+ public enum PropertyActionsEnum
+ {
+ CullMode,
+ ColorMask,
+ ZWrite,
+ ZTest,
+ ZOffsetFactor,
+ ZOffsetUnits,
+ BlendRGB,
+ BlendAlpha,
+ BlendOpRGB,
+ BlendOpAlpha,
+ StencilReference,
+ StencilReadMask,
+ StencilWriteMask,
+ StencilComparison,
+ StencilPass,
+ StencilFail,
+ StencilZFail,
+ RenderType,
+ RenderQueue
+ }
+
+ public enum AseOptionsSetup
+ {
+ CopyOptionsFromMainPass,
+ Id,
+ Name
+ }
+
+ [Serializable]
+ public class TemplateActionItem
+ {
+ public AseOptionsActionType ActionType;
+ public string ActionData = string.Empty;
+ public int ActionDataIdx = -1;
+
+ public string PassName;
+ public bool AllPasses = false;
+
+ public PropertyActionsEnum PropertyAction;
+ //CULL
+ public CullMode ActionCullMode;
+ //COLOR MASK
+ public bool[] ColorMask = { true, true, true, true };
+
+ //DEPTH
+ public ZWriteMode ActionZWrite;
+ public ZTestMode ActionZTest;
+ public float ActionZOffsetFactor;
+ public float ActionZOffsetUnits;
+
+ //BLEND OPS
+ public AvailableBlendFactor ActionBlendRGBSource;
+ public AvailableBlendFactor ActionBlendRGBDest;
+
+ public AvailableBlendFactor ActionBlendAlphaSource;
+ public AvailableBlendFactor ActionBlendAlphaDest;
+
+ public AvailableBlendOps ActionBlendOpRGB;
+ public AvailableBlendOps ActionBlendOpAlpha;
+
+ //STENCIL
+ public int ActionStencilReference;
+ public int ActionStencilReadMask;
+ public int ActionStencilWriteMask;
+ public int ActionStencilComparison;
+ public int ActionStencilPass;
+ public int ActionStencilFail;
+ public int ActionStencilZFail;
+
+ public bool CopyFromSubShader = false;
+
+ public string ActionBuffer;
+ public override string ToString()
+ {
+ return ActionType + " " + ActionData + " " + ActionDataIdx;
+ }
+ }
+
+ [Serializable]
+ public class TemplateActionItemGrid
+ {
+ [Serializable]
+ public class TemplateActionItemRow
+ {
+ public TemplateActionItem[] Columns;
+ }
+
+ public TemplateActionItemRow[] Rows;
+
+ public TemplateActionItemGrid( int rowsCount )
+ {
+ Rows = new TemplateActionItemRow[ rowsCount ];
+ }
+
+ public TemplateActionItem this[ int row, int column ]
+ {
+ get { return Rows[ row ].Columns[ column ]; }
+ set { Rows[ row ].Columns[ column ] = value; }
+ }
+
+ public TemplateActionItem[] this[ int row ]
+ {
+ get { return Rows[ row ].Columns; }
+
+ set
+ {
+ if( Rows[ row ] == null )
+ Rows[ row ] = new TemplateActionItemRow();
+
+ Rows[ row ].Columns = value;
+ }
+ }
+ }
+
+ [Serializable]
+ public class TemplateOptionsItem
+ {
+ public AseOptionsType Type;
+ public AseOptionsUIWidget UIWidget;
+ public AseOptionItemSetup Setup = AseOptionItemSetup.None;
+
+ public string Id = string.Empty;
+ public string Name = string.Empty;
+ public string DefaultOption = string.Empty;
+ public string[] Options = null;
+ public string[] DisplayOptions = null;
+ public int DisableIdx = -1;
+
+ [SerializeField]
+ private float m_defaultFieldValue;
+
+ public float FieldMin;
+ public float FieldMax;
+
+ public bool FieldInline;
+ public string FieldInlineName;
+ public string FieldInlineOutput = string.Empty;
+
+ [SerializeField]
+ public InlineProperty FieldValue = new InlineProperty();
+
+ public TemplateActionItemGrid ActionsPerOption = null;
+
+ public int Count = 0;
+
+ [SerializeField]
+ private int m_defaultOptionIndex = -1;
+
+ ~TemplateOptionsItem()
+ {
+ Options = null;
+ }
+
+ public int OptionIndexFor( string option )
+ {
+ for( int i = 0; i < Options.Length; i++ )
+ {
+ if( Options[ i ].Equals( option ) )
+ {
+ return i;
+ }
+ }
+ Debug.LogWarning( "Couldn't find index for option: " + option );
+ return 0;
+ }
+
+ public int DefaultOptionIndex
+ {
+ get
+ {
+ if( m_defaultOptionIndex > -1 )
+ return m_defaultOptionIndex;
+
+ for( int i = 0; i < Options.Length; i++ )
+ {
+ if( Options[ i ].Equals( DefaultOption ) )
+ {
+ m_defaultOptionIndex = i;
+ return i;
+ }
+ }
+ Debug.LogWarning( "Couldn't find index for default option: " + DefaultOption );
+ return 0;
+ }
+ }
+
+ public float DefaultFieldValue
+ {
+ get
+ {
+ return m_defaultFieldValue;
+ }
+ set
+ {
+ m_defaultFieldValue = value;
+ }
+ }
+ }
+
+ [Serializable]
+ public class TemplateOptionsContainer
+ {
+ public bool Enabled = false;
+ public string Body = string.Empty;
+ public int Index = -1;
+ public int Id = -1;
+ public string Name = string.Empty;
+ public bool CopyOptionsFromMainPass = false;
+ public TemplateOptionsItem[] Options = null;
+ ~TemplateOptionsContainer()
+ {
+ Options = null;
+ }
+
+ public void CopyPortOptionsFrom( TemplateOptionsContainer container, string passName )
+ {
+ if( container == null || container.Options == null )
+ return;
+
+ List<TemplateOptionsItem> newItems = new List<TemplateOptionsItem>();
+ for( int i = 0; i < container.Options.Length; i++ )
+ {
+ if( container.Options[ i ].Type == AseOptionsType.Port &&
+ container.Options[ i ].Id.Equals( passName ) )
+ {
+ newItems.Add( container.Options[ i ] );
+ }
+ }
+
+ if( newItems.Count > 0 )
+ {
+ Enabled = true;
+ if( Options == null )
+ {
+ Options = newItems.ToArray();
+ }
+ else
+ {
+ Array.Resize<TemplateOptionsItem>( ref Options, Options.Length + newItems.Count );
+ Array.Copy( newItems.ToArray(), Options, newItems.Count );
+ }
+ }
+ newItems.Clear();
+ newItems = null;
+ }
+
+ public int EndIndex { get { return Index + Body.Length; } }
+ }
+
+ public class TemplateOptionsToolsHelper
+ {
+ //public const string PassOptionsMainPattern = @"\/\*ase_pass_options:([\w:= ]*)[\n]([\w: \t;\n&|,_\+-]*)\*\/";
+ //public const string SubShaderOptionsMainPattern = @"\/\*ase_subshader_options:([\w:= ]*)[\n]([\w: \t;\n&|,_\+-]*)\*\/";
+ public const string PassOptionsMainPattern = "\\/\\*ase_pass_options:([\\w:= ]*)[\n]([\\w: \t;\n&|,_\\+\\-\\(\\)\\[\\]\\\"\\=\\/\\.]*)\\*\\/";
+ public const string SubShaderOptionsMainPattern = "\\/\\*ase_subshader_options:([\\w:= ]*)[\n]([\\w: \t;\n&|,_\\+\\-\\(\\)\\[\\]\\\"\\=\\/\\.]*)\\*\\/";
+ public static readonly char OptionsDataSeparator = ',';
+ public static Dictionary<string, AseOptionsSetup> AseOptionsSetupDict = new Dictionary<string, AseOptionsSetup>()
+ {
+ { "CopyOptionsFromMainPass",AseOptionsSetup.CopyOptionsFromMainPass},
+ { "Id",AseOptionsSetup.Id},
+ { "Name",AseOptionsSetup.Name},
+ };
+
+ public static Dictionary<string, AseOptionsUIWidget> AseOptionsUITypeDict = new Dictionary<string, AseOptionsUIWidget>()
+ {
+ { "Dropdown",AseOptionsUIWidget.Dropdown },
+ { "Toggle", AseOptionsUIWidget.Toggle }
+ };
+
+ public static Dictionary<string, AseOptionsActionType> AseOptionsActionTypeDict = new Dictionary<string, AseOptionsActionType>()
+ {
+ {"ShowOption", AseOptionsActionType.ShowOption },
+ {"HideOption", AseOptionsActionType.HideOption },
+ {"SetOption", AseOptionsActionType.SetOption },
+ {"HidePort", AseOptionsActionType.HidePort },
+ {"ShowPort", AseOptionsActionType.ShowPort },
+ {"SetPortName", AseOptionsActionType.SetPortName },
+ {"SetDefine", AseOptionsActionType.SetDefine },
+ {"RemoveDefine", AseOptionsActionType.RemoveDefine },
+ {"SetUndefine", AseOptionsActionType.SetUndefine },
+ {"RemoveUndefine", AseOptionsActionType.RemoveUndefine },
+ {"ExcludePass", AseOptionsActionType.ExcludePass },
+ {"IncludePass", AseOptionsActionType.IncludePass },
+ {"SetPropertyOnPass", AseOptionsActionType.SetPropertyOnPass },
+ {"SetPropertyOnSubShader", AseOptionsActionType.SetPropertyOnSubShader },
+ {"SetShaderProperty", AseOptionsActionType.SetShaderProperty },
+ {"SetMaterialProperty", AseOptionsActionType.SetMaterialProperty }
+ };
+
+ public static Dictionary<string, AseOptionItemSetup> AseOptionItemSetupDict = new Dictionary<string, AseOptionItemSetup>
+ {
+ {"None", AseOptionItemSetup.None },
+ { "InvertActionOnDeselection", AseOptionItemSetup.InvertActionOnDeselection}
+ };
+
+ public static bool InvertAction( AseOptionsActionType original, ref AseOptionsActionType inverted )
+ {
+ bool success = true;
+ switch( original )
+ {
+ case AseOptionsActionType.ShowOption:
+ inverted = AseOptionsActionType.HideOption;
+ break;
+ case AseOptionsActionType.HideOption:
+ inverted = AseOptionsActionType.ShowOption;
+ break;
+ case AseOptionsActionType.HidePort:
+ inverted = AseOptionsActionType.ShowPort;
+ break;
+ case AseOptionsActionType.ShowPort:
+ inverted = AseOptionsActionType.HidePort;
+ break;
+ case AseOptionsActionType.SetDefine:
+ inverted = AseOptionsActionType.RemoveDefine;
+ break;
+ case AseOptionsActionType.RemoveDefine:
+ inverted = AseOptionsActionType.SetDefine;
+ break;
+ case AseOptionsActionType.SetUndefine:
+ inverted = AseOptionsActionType.RemoveUndefine;
+ break;
+ case AseOptionsActionType.RemoveUndefine:
+ inverted = AseOptionsActionType.SetUndefine;
+ break;
+ case AseOptionsActionType.ExcludePass:
+ inverted = AseOptionsActionType.IncludePass;
+ break;
+ case AseOptionsActionType.IncludePass:
+ inverted = AseOptionsActionType.ExcludePass;
+ break;
+ case AseOptionsActionType.SetPortName:
+ case AseOptionsActionType.SetOption:
+ case AseOptionsActionType.SetPropertyOnPass:
+ case AseOptionsActionType.SetPropertyOnSubShader:
+ success = false;
+ break;
+ }
+ return success;
+ }
+
+
+ public static TemplateOptionsContainer GenerateOptionsContainer( bool isSubShader, string data )
+ {
+ TemplateOptionsContainer optionsContainer = new TemplateOptionsContainer();
+
+ Match match = Regex.Match( data, isSubShader ? SubShaderOptionsMainPattern : PassOptionsMainPattern );
+ optionsContainer.Enabled = match.Success;
+ if( match.Success )
+ {
+ try
+ {
+ optionsContainer.Body = match.Value;
+ optionsContainer.Index = match.Index;
+
+ List<TemplateOptionsItem> optionItemsList = new List<TemplateOptionsItem>();
+ List<List<TemplateActionItem>> actionItemsList = new List<List<TemplateActionItem>>();
+ Dictionary<string, int> optionItemToIndex = new Dictionary<string, int>();
+ TemplateOptionsItem currentOption = null;
+
+ //OPTIONS OVERALL SETUP
+ string[] setupLines = match.Groups[ 1 ].Value.Split( ':' );
+ for( int i = 0; i < setupLines.Length; i++ )
+ {
+ if( AseOptionsSetupDict.ContainsKey( setupLines[ i ] ) )
+ {
+ AseOptionsSetup setup = AseOptionsSetupDict[ setupLines[ i ] ];
+ switch( setup )
+ {
+ case AseOptionsSetup.CopyOptionsFromMainPass: optionsContainer.CopyOptionsFromMainPass = true; break;
+ }
+ }
+ else
+ {
+ string[] args = setupLines[ i ].Split( '=' );
+ if( args.Length > 1 && AseOptionsSetupDict.ContainsKey( args[ 0 ] ) )
+ {
+ AseOptionsSetup setup = AseOptionsSetupDict[ args[ 0 ] ];
+ switch( setup )
+ {
+ case AseOptionsSetup.Id: if( !int.TryParse( args[ 1 ], out optionsContainer.Id ) ) optionsContainer.Id = -1; break;
+ case AseOptionsSetup.Name: optionsContainer.Name = args[ 1 ]; break;
+ }
+ }
+ }
+ }
+
+ //AVAILABLE OPTIONS
+ string body = match.Groups[ 2 ].Value.Replace( "\t", string.Empty );
+ string[] optionLines = body.Split( '\n' );
+ for( int oL = 0; oL < optionLines.Length; oL++ )
+ {
+ string[] optionItems = optionLines[ oL ].Split( ':' );
+ if( optionItems.Length > 0 )
+ {
+ string[] itemIds = optionItems[ 0 ].Split( OptionsDataSeparator );
+ switch( itemIds[ 0 ] )
+ {
+ case "Option":
+ {
+ //Fills previous option with its actions
+ //actionItemsList is cleared over here
+ FillOptionAction( currentOption, ref actionItemsList );
+
+ optionItemToIndex.Clear();
+ currentOption = new TemplateOptionsItem();
+ currentOption.Type = AseOptionsType.Option;
+ string[] optionItemSetup = optionItems[ 1 ].Split( OptionsDataSeparator );
+ currentOption.Name = optionItemSetup[ 0 ];
+ if( optionItemSetup.Length > 1 )
+ {
+ if( AseOptionItemSetupDict.ContainsKey( optionItemSetup[ 1 ] ) )
+ currentOption.Setup = AseOptionItemSetupDict[ optionItemSetup[ 1 ] ];
+ }
+
+ currentOption.Id = itemIds.Length > 1 ? itemIds[ 1 ] : optionItems[ 1 ];
+ currentOption.DisplayOptions = optionItems[ 2 ].Split( OptionsDataSeparator );
+ currentOption.DisableIdx = currentOption.DisplayOptions.Length;
+ optionItems[ 2 ] += ",disable";
+ currentOption.Options = optionItems[ 2 ].Split( OptionsDataSeparator );
+ currentOption.Count = currentOption.Options.Length;
+
+ for( int opIdx = 0; opIdx < currentOption.Options.Length; opIdx++ )
+ {
+ optionItemToIndex.Add( currentOption.Options[ opIdx ], opIdx );
+ actionItemsList.Add( new List<TemplateActionItem>() );
+ }
+
+ if( optionItems.Length > 3 )
+ {
+ currentOption.DefaultOption = optionItems[ 3 ];
+ }
+ else
+ {
+ currentOption.DefaultOption = currentOption.Options[ 0 ];
+ }
+
+ if( currentOption.Options.Length == 2 || ( currentOption.Options.Length == 3 && currentOption.Options[ 2 ].Equals( "disable" ) ) )
+ {
+ if( ( currentOption.Options[ 0 ].Equals( "true" ) && currentOption.Options[ 1 ].Equals( "false" ) ) ||
+ ( currentOption.Options[ 0 ].Equals( "false" ) && currentOption.Options[ 1 ].Equals( "true" ) ) )
+ {
+ // Toggle 0 is false and 1 is true
+ currentOption.Options[ 0 ] = "false";
+ currentOption.Options[ 1 ] = "true";
+ currentOption.UIWidget = AseOptionsUIWidget.Toggle;
+ }
+ }
+ else if( currentOption.Options.Length > 2 )
+ {
+ currentOption.UIWidget = AseOptionsUIWidget.Dropdown;
+ }
+ else
+ {
+ Debug.LogWarning( "Detected an option with less than two items:" + optionItems[ 1 ] );
+ }
+ optionItemsList.Add( currentOption );
+ }
+ break;
+ case "Port":
+ {
+ //Fills previous option with its actions
+ //actionItemsList is cleared over here
+ FillOptionAction( currentOption, ref actionItemsList );
+
+ optionItemToIndex.Clear();
+
+ currentOption = new TemplateOptionsItem();
+ currentOption.Type = AseOptionsType.Port;
+ if( isSubShader && optionItems.Length > 2 )
+ {
+ currentOption.Id = optionItems[ 1 ];
+ currentOption.Name = optionItems[ 2 ];
+ }
+ else
+ {
+ currentOption.Name = optionItems[ 1 ];
+ }
+
+ currentOption.Options = new string[] { "On", "Off" };
+ optionItemToIndex.Add( currentOption.Options[ 0 ], 0 );
+ optionItemToIndex.Add( currentOption.Options[ 1 ], 1 );
+
+ actionItemsList.Add( new List<TemplateActionItem>() );
+ actionItemsList.Add( new List<TemplateActionItem>() );
+
+ optionItemsList.Add( currentOption );
+ }
+ break;
+ case "Field":
+ {
+ //Fills previous option with its actions
+ //actionItemsList is cleared over here
+ FillOptionAction( currentOption, ref actionItemsList );
+
+ optionItemToIndex.Clear();
+ currentOption = new TemplateOptionsItem();
+ currentOption.Type = AseOptionsType.Field;
+
+ currentOption.Id = optionItems[ 1 ];
+ currentOption.Name = optionItems[ 1 ];
+
+ currentOption.UIWidget = AseOptionsUIWidget.Float;
+ if( optionItems[ 2 ].Equals( "Int" ) )
+ currentOption.UIWidget = AseOptionsUIWidget.Int;
+
+ if( optionItems.Length >= 3 )
+ {
+ currentOption.DefaultFieldValue = Convert.ToSingle( optionItems[ 3 ], System.Globalization.CultureInfo.InvariantCulture );
+ }
+
+ if( optionItems.Length >= 6 )
+ {
+ if( currentOption.UIWidget == AseOptionsUIWidget.Int )
+ currentOption.UIWidget = AseOptionsUIWidget.Int;
+ else
+ currentOption.UIWidget = AseOptionsUIWidget.FloatRange;
+
+ currentOption.FieldMin = Convert.ToSingle( optionItems[ 4 ], System.Globalization.CultureInfo.InvariantCulture );
+ currentOption.FieldMax = Convert.ToSingle( optionItems[ 5 ], System.Globalization.CultureInfo.InvariantCulture );
+ }
+
+ if( optionItems.Length == 5 || optionItems.Length == 7 )
+ {
+ currentOption.FieldInline = true;
+ currentOption.FieldInlineName = optionItems[ optionItems.Length - 1 ];
+ }
+
+ currentOption.Options = new string[] { "Change", "Inline", "disable" };
+
+ optionItemToIndex.Add( currentOption.Options[ 0 ], 0 );
+ optionItemToIndex.Add( currentOption.Options[ 1 ], 1 );
+ optionItemToIndex.Add( currentOption.Options[ 2 ], 2 );
+ currentOption.DisableIdx = 2;
+
+ actionItemsList.Add( new List<TemplateActionItem>() );
+ actionItemsList.Add( new List<TemplateActionItem>() );
+ actionItemsList.Add( new List<TemplateActionItem>() );
+
+ optionItemsList.Add( currentOption );
+ }
+ break;
+ default:
+ {
+ if( optionItemToIndex.ContainsKey( optionItems[ 0 ] ) )
+ {
+ int idx = 0;
+ if( currentOption != null && currentOption.UIWidget == AseOptionsUIWidget.Toggle )
+ {
+ idx = ( optionItems[ 0 ].Equals( "true" ) ) ? 1 : 0;
+ if( optionItems[ 0 ].Equals( "disable" ) )
+ idx = 2;
+ }
+ else
+ {
+ idx = optionItemToIndex[ optionItems[ 0 ] ];
+ }
+ actionItemsList[ idx ].Add( CreateActionItem( isSubShader, optionItems ) );
+ }
+ else
+ {
+ //string[] ids = optionItems[ 0 ].Split( ',' );
+ if( itemIds.Length > 1 )
+ {
+ for( int i = 0; i < itemIds.Length; i++ )
+ {
+ if( optionItemToIndex.ContainsKey( itemIds[ i ] ) )
+ {
+ int idx = optionItemToIndex[ itemIds[ i ] ];
+ actionItemsList[ idx ].Add( CreateActionItem( isSubShader, optionItems ) );
+ }
+ }
+ }
+ }
+
+ }
+ break;
+ }
+ }
+ }
+
+ //Fills last option with its actions
+ FillOptionAction( currentOption, ref actionItemsList );
+
+ actionItemsList.Clear();
+ actionItemsList = null;
+
+ optionsContainer.Options = optionItemsList.ToArray();
+ optionItemsList.Clear();
+ optionItemsList = null;
+
+ optionItemToIndex.Clear();
+ optionItemToIndex = null;
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ return optionsContainer;
+ }
+
+ static void FillOptionAction( TemplateOptionsItem currentOption, ref List<List<TemplateActionItem>> actionItemsList )
+ {
+ if( currentOption != null )
+ {
+ int count = actionItemsList.Count;
+ currentOption.ActionsPerOption = new TemplateActionItemGrid( count );
+ for( int i = 0; i < count; i++ )
+ {
+ currentOption.ActionsPerOption[ i ] = actionItemsList[ i ].ToArray();
+ actionItemsList[ i ].Clear();
+ }
+ actionItemsList.Clear();
+ }
+ }
+
+ static TemplateActionItem CreateActionItem( bool isSubshader, string[] optionItems )
+ {
+ TemplateActionItem actionItem = new TemplateActionItem();
+ try
+ {
+ actionItem.ActionType = AseOptionsActionTypeDict[ optionItems[ 1 ] ];
+ int optionsIdx = 2;
+ if( optionItems.Length > 3 )
+ {
+ optionsIdx = 3;
+ actionItem.PassName = optionItems[ 2 ];
+ }
+ else
+ {
+ actionItem.AllPasses = isSubshader;
+ }
+
+ actionItem.ActionData = optionItems[ optionsIdx ];
+
+ switch( actionItem.ActionType )
+ {
+ case AseOptionsActionType.ShowOption:
+ case AseOptionsActionType.HideOption:
+ {
+ string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator );
+ if( arr.Length > 1 )
+ {
+ actionItem.ActionData = arr[ 0 ];
+ if( !int.TryParse( arr[ 1 ], out actionItem.ActionDataIdx ) )
+ {
+ actionItem.ActionDataIdx = -1;
+ }
+ }
+ }
+ break;
+ case AseOptionsActionType.SetOption:
+ {
+ string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator );
+ if( arr.Length > 1 )
+ {
+ actionItem.ActionData = arr[ 0 ];
+ if( !int.TryParse( arr[ 1 ], out actionItem.ActionDataIdx ) )
+ {
+ Debug.LogWarning( "SetOption value must be a the selection index" );
+ }
+ }
+ }
+ break;
+ case AseOptionsActionType.HidePort:
+ case AseOptionsActionType.ShowPort:
+ {
+ if( !int.TryParse( actionItem.ActionData, out actionItem.ActionDataIdx ) )
+ actionItem.ActionDataIdx = -1;
+ }
+ break;
+ case AseOptionsActionType.SetPortName:
+ {
+ string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator );
+ if( arr.Length > 1 )
+ {
+ int.TryParse( arr[ 0 ], out actionItem.ActionDataIdx );
+ actionItem.ActionData = arr[ 1 ];
+ }
+ }
+ break;
+ case AseOptionsActionType.SetDefine:
+ case AseOptionsActionType.RemoveDefine:
+ case AseOptionsActionType.SetUndefine:
+ case AseOptionsActionType.RemoveUndefine:
+ case AseOptionsActionType.ExcludePass:
+ case AseOptionsActionType.IncludePass:
+ break;
+ case AseOptionsActionType.SetShaderProperty:
+ {
+ int optIndex = optionItems[ optionsIdx ].IndexOf( OptionsDataSeparator );
+ if( optIndex > -1 )
+ {
+ actionItem.ActionData = optionItems[ optionsIdx ].Substring( 0, optIndex );
+ actionItem.ActionBuffer = optionItems[ optionsIdx ].Substring( optIndex + 1, optionItems[ optionsIdx ].Length - optIndex - 1);
+ }
+ }break;
+ case AseOptionsActionType.SetMaterialProperty:
+ {
+ int optIndex = optionItems[ optionsIdx ].IndexOf( OptionsDataSeparator );
+ if( optIndex > -1 )
+ {
+ actionItem.ActionData = optionItems[ optionsIdx ].Substring( 0, optIndex );
+ }
+ }
+ break;
+ case AseOptionsActionType.SetPropertyOnPass:
+ case AseOptionsActionType.SetPropertyOnSubShader:
+ {
+ string[] arr = optionItems[ optionsIdx ].Split( OptionsDataSeparator );
+ actionItem.PropertyAction = (PropertyActionsEnum)Enum.Parse( typeof( PropertyActionsEnum ), arr[ 0 ] );
+ if( arr.Length == 1 && actionItem.ActionType == AseOptionsActionType.SetPropertyOnPass )
+ {
+ actionItem.CopyFromSubShader = true;
+ }
+ else
+ {
+ switch( actionItem.PropertyAction )
+ {
+ case PropertyActionsEnum.CullMode:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionCullMode = (CullMode)Enum.Parse( typeof( CullMode ), arr[ 1 ] );
+ }
+ break;
+ case PropertyActionsEnum.ColorMask:
+ {
+ if( arr.Length > 4 )
+ {
+ actionItem.ColorMask[ 0 ] = Convert.ToBoolean( arr[ 1 ] );
+ actionItem.ColorMask[ 1 ] = Convert.ToBoolean( arr[ 2 ] );
+ actionItem.ColorMask[ 2 ] = Convert.ToBoolean( arr[ 3 ] );
+ actionItem.ColorMask[ 3 ] = Convert.ToBoolean( arr[ 4 ] );
+ }
+ }
+ break;
+ case PropertyActionsEnum.ZWrite:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionZWrite = (ZWriteMode)Enum.Parse( typeof( ZWriteMode ), arr[ 1 ] );
+ }
+ break;
+ case PropertyActionsEnum.ZTest:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionZTest = (ZTestMode)Enum.Parse( typeof( ZTestMode ), arr[ 1 ] );
+ }
+ break;
+ case PropertyActionsEnum.ZOffsetFactor:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionZOffsetFactor = Convert.ToSingle( arr[ 1 ] );
+ }
+ break;
+ case PropertyActionsEnum.ZOffsetUnits:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionZOffsetUnits = Convert.ToSingle( arr[ 1 ] );
+ }
+ break;
+ case PropertyActionsEnum.BlendRGB:
+ {
+ if( arr.Length > 2 )
+ {
+ actionItem.ActionBlendRGBSource = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] );
+ actionItem.ActionBlendRGBDest = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] );
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendAlpha:
+ {
+ if( arr.Length > 2 )
+ {
+ actionItem.ActionBlendAlphaSource = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 1 ] );
+ actionItem.ActionBlendAlphaDest = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), arr[ 2 ] );
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendOpRGB:
+ {
+ if( arr.Length > 1 )
+ {
+ actionItem.ActionBlendOpRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), arr[ 1 ] );
+
+ }
+ }
+ break;
+ case PropertyActionsEnum.BlendOpAlpha:
+ {
+ if( arr.Length > 1 )
+ {
+ actionItem.ActionBlendOpAlpha = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), arr[ 1 ] );
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilReference:
+ {
+ if( arr.Length > 1 )
+ {
+ int.TryParse( arr[ 1 ], out actionItem.ActionStencilReference );
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilReadMask:
+ {
+ if( arr.Length > 1 )
+ {
+ int.TryParse( arr[ 1 ], out actionItem.ActionStencilReadMask );
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilWriteMask:
+ {
+ if( arr.Length > 1 )
+ {
+ int.TryParse( arr[ 1 ], out actionItem.ActionStencilWriteMask );
+ }
+ }
+ break;
+ case PropertyActionsEnum.StencilComparison:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionStencilComparison = StencilBufferOpHelper.StencilComparisonValuesDict[ arr[ 1 ] ];
+ }
+ break;
+ case PropertyActionsEnum.StencilPass:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionStencilPass = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ];
+ }
+ break;
+ case PropertyActionsEnum.StencilFail:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionStencilFail = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ];
+ }
+ break;
+ case PropertyActionsEnum.StencilZFail:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionStencilZFail = StencilBufferOpHelper.StencilOpsValuesDict[ arr[ 1 ] ];
+ }
+ break;
+ case PropertyActionsEnum.RenderType:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionData = arr[ 1 ];
+ }
+ break;
+ case PropertyActionsEnum.RenderQueue:
+ {
+ if( arr.Length > 1 )
+ actionItem.ActionData = arr[ 1 ];
+ if( arr.Length > 2 )
+ {
+ int.TryParse( arr[ 2 ], out actionItem.ActionDataIdx );
+ }
+ else
+ {
+ actionItem.ActionDataIdx = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ return actionItem;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta
new file mode 100644
index 00000000..55c0596b
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 019dfacde4ed75a41851c7f15f69963f
+timeCreated: 1533143812
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs
new file mode 100644
index 00000000..affbd406
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs
@@ -0,0 +1,69 @@
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateOptionsDefinesContainer
+ {
+ [SerializeField]
+ private List<PropertyDataCollector> m_definesList = new List<PropertyDataCollector>();
+
+ [NonSerialized]
+ private Dictionary<string, PropertyDataCollector> m_definesDict = new Dictionary<string, PropertyDataCollector>();
+
+ void Refresh()
+ {
+ if( m_definesDict.Count != m_definesList.Count )
+ {
+ m_definesDict.Clear();
+ for( int i = 0; i < m_definesList.Count; i++ )
+ {
+ m_definesDict.Add( m_definesList[ i ].PropertyName, m_definesList[ i ] );
+ }
+ }
+ }
+
+ public void RemoveTemporaries()
+ {
+ List<PropertyDataCollector> temporaries = m_definesList.FindAll( ( x ) => ( x.NodeId == 1 ) );
+ for( int i = 0; i < temporaries.Count; i++ )
+ {
+ m_definesList.Remove( temporaries[ i ] );
+ m_definesDict.Remove( temporaries[ i ].PropertyName );
+ }
+ }
+
+ public void AddDefine( string define , bool temporary )
+ {
+ Refresh();
+ if( !m_definesDict.ContainsKey( define ) )
+ {
+ int nodeId = temporary ? 1 : 0;
+ PropertyDataCollector data = new PropertyDataCollector( nodeId, define );
+ m_definesDict.Add( define, data );
+ m_definesList.Add( data );
+ }
+ }
+
+ public void RemoveDefine( string define )
+ {
+ Refresh();
+ if( m_definesDict.ContainsKey( define ) )
+ {
+ m_definesList.Remove( m_definesDict[define] );
+ m_definesDict.Remove( define );
+ }
+ }
+
+ public void Destroy()
+ {
+ m_definesDict.Clear();
+ m_definesDict = null;
+ m_definesList.Clear();
+ m_definesList = null;
+ }
+ public List<PropertyDataCollector> DefinesList { get { return m_definesList; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta
new file mode 100644
index 00000000..151a9abc
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsDefinesContainer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0f32755ee64bb1542ad9598810d9faf9
+timeCreated: 1543339825
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs
new file mode 100644
index 00000000..04c11872
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs
@@ -0,0 +1,174 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ // PORT CONTROLLERS
+ [Serializable]
+ public class TemplateOptionPortItem
+ {
+ [SerializeField]
+ private int m_portId = -1;
+
+ [SerializeField]
+ private TemplateOptionsItem m_options;
+
+ public TemplateOptionPortItem( TemplateMultiPassMasterNode owner, TemplateOptionsItem options )
+ {
+ m_options = options;
+ InputPort port = owner.InputPorts.Find( x => x.Name.Equals( options.Name ) );
+ if( port != null )
+ {
+ m_portId = port.PortId;
+ }
+ }
+
+ public void FillDataCollector( TemplateMultiPassMasterNode owner, ref MasterNodeDataCollector dataCollector )
+ {
+ InputPort port = null;
+ if( m_portId > -1 )
+ {
+ port = owner.GetInputPortByUniqueId( m_portId );
+ }
+ else
+ {
+ port = owner.InputPorts.Find( x => x.Name.Equals( m_options.Name ) );
+ }
+
+ if( port != null )
+ {
+ int optionId = port.HasOwnOrLinkConnection ? 0 : 1;
+ for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ )
+ {
+ switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType )
+ {
+ case AseOptionsActionType.SetDefine:
+ {
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( "#define "+m_options.ActionsPerOption[ optionId ][ i ].ActionData, false );
+ }
+ //dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ optionId ][ i ].ActionData );
+ }
+ break;
+ case AseOptionsActionType.SetUndefine:
+ {
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( "#undef " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, false );
+ }
+ //dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ optionId ][ i ].ActionData, false );
+ }
+ break;
+ case AseOptionsActionType.SetShaderProperty:
+ {
+ TemplateShaderPropertyData data = owner.CurrentTemplate.GetShaderPropertyData( m_options.ActionsPerOption[ optionId ][ i ].ActionData );
+ if( data != null )
+ {
+ string newPropertyValue = data.CreatePropertyForValue( m_options.ActionsPerOption[ optionId ][ i ].ActionBuffer );
+ owner.CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue );
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ public void SubShaderFillDataCollector( TemplateMultiPassMasterNode owner, ref MasterNodeDataCollector dataCollector )
+ {
+
+ //TemplateMultiPassMasterNode targetNode = string.IsNullOrEmpty(m_options.Id) ? owner:owner.ContainerGraph.GetMasterNodeOfPass( m_options.Id , owner.LODIndex );
+ TemplateMultiPassMasterNode targetNode = string.IsNullOrEmpty( m_options.Id ) ?
+ owner.ContainerGraph.GetMainMasterNodeOfLOD( owner.LODIndex ) :
+ owner.ContainerGraph.GetMasterNodeOfPass( m_options.Id , owner.LODIndex );
+
+ InputPort port = null;
+ if( m_portId > -1 )
+ {
+ port = targetNode.GetInputPortByUniqueId( m_portId );
+ }
+ else
+ {
+ port = targetNode.InputPorts.Find( x => x.Name.Equals( m_options.Name ) );
+ }
+
+ if( port != null )
+ {
+ int optionId = port.HasOwnOrLinkConnection ? 0 : 1;
+ for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ )
+ {
+ if( string.IsNullOrEmpty( m_options.ActionsPerOption[ optionId ][ i ].PassName ) ||
+ m_options.ActionsPerOption[ optionId ][ i ].PassName.Equals( owner.PassName ) )
+ {
+ switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType )
+ {
+ case AseOptionsActionType.SetDefine:
+ {
+ owner.OptionsDefineContainer.AddDefine( "#define " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, true );
+ }
+ break;
+ case AseOptionsActionType.SetUndefine:
+ {
+ owner.OptionsDefineContainer.AddDefine( "#undef " + m_options.ActionsPerOption[ optionId ][ i ].ActionData, true );
+ }
+ break;
+ case AseOptionsActionType.SetShaderProperty:
+ {
+ TemplateShaderPropertyData data = owner.CurrentTemplate.GetShaderPropertyData( m_options.ActionsPerOption[ optionId ][ i ].ActionData );
+ if( data != null )
+ {
+ string newPropertyValue = data.CreatePropertyForValue( m_options.ActionsPerOption[ optionId ][ i ].ActionBuffer );
+ owner.CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue );
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void CheckImediateActionsForPort( TemplateMultiPassMasterNode owner, int portId )
+ {
+ if( portId != m_portId )
+ return;
+
+ InputPort port = null;
+ if( m_portId > -1 )
+ {
+ port = owner.GetInputPortByUniqueId( m_portId );
+ }
+ else
+ {
+ port = owner.InputPorts.Find( x => x.Name.Equals( m_options.Name ) );
+ }
+
+ if( port != null )
+ {
+ int optionId = port.HasOwnOrLinkConnection ? 0 : 1;
+ for( int i = 0; i < m_options.ActionsPerOption[ optionId ].Length; i++ )
+ {
+ switch( m_options.ActionsPerOption[ optionId ][ i ].ActionType )
+ {
+ case AseOptionsActionType.SetPortName:
+ {
+ port.Name = m_options.ActionsPerOption[ optionId ][ i ].ActionData;
+ owner.SizeIsDirty = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ public TemplateOptionsItem Options { get { return m_options; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta
new file mode 100644
index 00000000..a9c15d28
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsPort.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fa2d25bd070cde046876bd1fa77bf116
+timeCreated: 1535044953
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs
new file mode 100644
index 00000000..559f3a44
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs
@@ -0,0 +1,300 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ // UI STRUCTURES
+ [Serializable]
+ public class TemplateOptionUIItem
+ {
+ public delegate void OnActionPerformed( bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions );
+ public event OnActionPerformed OnActionPerformedEvt;
+
+ [SerializeField]
+ private bool m_isVisible = true;
+
+ [SerializeField]
+ private bool m_wasVisible = true;
+
+ [SerializeField]
+ private int m_currentOption = 0;
+
+ [SerializeField]
+ private TemplateOptionsItem m_options;
+
+ [SerializeField]
+ private bool m_checkOnExecute = false;
+
+ [SerializeField]
+ private bool m_invertActionOnDeselection = false;
+
+ public TemplateOptionUIItem( TemplateOptionsItem options )
+ {
+ m_options = options;
+ if( m_options.Type == AseOptionsType.Field )
+ {
+ m_options.FieldValue.FloatValue = m_options.DefaultFieldValue;
+ }
+ else
+ {
+ m_currentOption = m_options.DefaultOptionIndex;
+ }
+ m_invertActionOnDeselection = options.Setup == AseOptionItemSetup.InvertActionOnDeselection;
+ }
+
+ public void CopyValuesFrom( TemplateOptionUIItem origin )
+ {
+ m_isVisible = origin.IsVisible;
+ m_wasVisible = origin.WasVisible;
+ m_currentOption = origin.CurrentOption;
+ m_options.FieldValue.FloatValue = origin.CurrentFieldValue;
+ m_checkOnExecute = origin.CheckOnExecute;
+ m_invertActionOnDeselection = origin.InvertActionOnDeselection;
+ }
+
+ public void Draw( UndoParentNode owner )
+ {
+ if( m_isVisible )
+ {
+ int lastOption = m_currentOption;
+ EditorGUI.BeginChangeCheck();
+ switch( m_options.UIWidget )
+ {
+ case AseOptionsUIWidget.Dropdown:
+ {
+ m_currentOption = owner.EditorGUILayoutPopup( m_options.Name, m_currentOption, m_options.DisplayOptions );
+ }
+ break;
+ case AseOptionsUIWidget.Toggle:
+ {
+ m_currentOption = owner.EditorGUILayoutToggle( m_options.Name, m_currentOption == 1 ) ? 1 : 0;
+ }
+ break;
+ case AseOptionsUIWidget.Float:
+ {
+ if( m_options.FieldInline )
+ {
+ m_options.FieldValue.FloatField( ref owner, m_options.Name );
+ if( m_options.FieldValue.Active )
+ m_currentOption = 1;
+ else
+ m_currentOption = 0;
+ }
+ else
+ {
+ m_options.FieldValue.FloatValue = owner.EditorGUILayoutFloatField( m_options.Name, m_options.FieldValue.FloatValue );
+ }
+ }
+ break;
+ case AseOptionsUIWidget.Int:
+ {
+ if( m_options.FieldInline )
+ {
+ m_options.FieldValue.IntField( ref owner, m_options.Name );
+ if( m_options.FieldValue.Active )
+ m_currentOption = 1;
+ else
+ m_currentOption = 0;
+ }
+ else
+ m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntField( m_options.Name, (int)m_options.FieldValue.FloatValue );
+ }
+ break;
+ case AseOptionsUIWidget.FloatRange:
+ {
+ if( m_options.FieldInline )
+ {
+ m_options.FieldValue.SliderField( ref owner, m_options.Name, m_options.FieldMin, m_options.FieldMax );
+ if( m_options.FieldValue.Active )
+ m_currentOption = 1;
+ else
+ m_currentOption = 0;
+ }
+ else
+ m_options.FieldValue.FloatValue = owner.EditorGUILayoutSlider( m_options.Name, m_options.FieldValue.FloatValue, m_options.FieldMin, m_options.FieldMax );
+ }
+ break;
+ case AseOptionsUIWidget.IntRange:
+ {
+ if( m_options.FieldInline )
+ {
+ m_options.FieldValue.IntSlider( ref owner, m_options.Name, (int)m_options.FieldMin, (int)m_options.FieldMax );
+ if( m_options.FieldValue.Active )
+ m_currentOption = 1;
+ else
+ m_currentOption = 0;
+ }
+ else
+ m_options.FieldValue.FloatValue = owner.EditorGUILayoutIntSlider( m_options.Name, (int)m_options.FieldValue.FloatValue, (int)m_options.FieldMin, (int)m_options.FieldMax );
+ }
+ break;
+ }
+ if( EditorGUI.EndChangeCheck() )
+ {
+ if( OnActionPerformedEvt != null )
+ {
+ if( m_invertActionOnDeselection )
+ OnActionPerformedEvt( false, lastOption != m_options.DisableIdx, this, m_options.ActionsPerOption[ lastOption ] );
+
+ OnActionPerformedEvt( false, false, this, m_options.ActionsPerOption[ m_currentOption ] );
+ }
+ }
+ }
+ }
+
+ public void CheckEnDisable()
+ {
+ //string deb = string.Empty;// "-- Checked --" + m_options.Name+" "+ m_isVisible + " "+ m_wasVisible;
+ if( m_isVisible )
+ {
+ if( !m_wasVisible )
+ {
+ //deb = "-- Enable --" + m_options.Name;
+ //Debug.Log( deb );
+ if( OnActionPerformedEvt != null )
+ {
+ if( m_invertActionOnDeselection )
+ {
+ for( int i = 0; i < m_options.Count; i++ )
+ {
+ if( i != m_currentOption && i != m_options.DisableIdx )
+ {
+ OnActionPerformedEvt( false, true, this, m_options.ActionsPerOption[ i ] );
+ }
+ }
+ }
+
+ OnActionPerformedEvt( false, false, this, m_options.ActionsPerOption[ m_currentOption ] );
+ //if( !m_isVisible )
+ //OnActionPerformedEvt( isRefreshing, false, this, m_options.ActionsPerOption[ m_options.DisableIdx ] );
+ }
+ }
+
+ m_wasVisible = true;
+ }
+ else if( m_wasVisible )
+ {
+ //deb = "-- Disable --" + m_options.Name;
+ //Debug.Log( deb );
+ m_wasVisible = false;
+
+ if( OnActionPerformedEvt != null )
+ {
+ OnActionPerformedEvt( false, false, this, m_options.ActionsPerOption[ m_options.DisableIdx ] );
+ }
+ }
+ }
+
+ public void FillDataCollector( ref MasterNodeDataCollector dataCollector )
+ {
+ if( m_isVisible && m_checkOnExecute )
+ {
+ for( int i = 0; i < m_options.ActionsPerOption[ m_currentOption ].Length; i++ )
+ {
+ switch( m_options.ActionsPerOption[ m_currentOption ][ i ].ActionType )
+ {
+ case AseOptionsActionType.SetDefine:
+ {
+ dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData );
+ }
+ break;
+ case AseOptionsActionType.SetUndefine:
+ {
+ dataCollector.AddToDefines( -1, m_options.ActionsPerOption[ m_currentOption ][ i ].ActionData, false );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ public void Refresh()
+ {
+ if( OnActionPerformedEvt != null )
+ {
+ if( m_invertActionOnDeselection )
+ {
+ for( int i = 0; i < m_options.Count; i++ )
+ {
+ if( i != m_currentOption && i != m_options.DisableIdx )
+ {
+ OnActionPerformedEvt( true, true, this, m_options.ActionsPerOption[ i ] );
+ }
+ }
+ }
+
+ OnActionPerformedEvt( true, false, this, m_options.ActionsPerOption[ m_currentOption ] );
+ }
+ }
+
+ public TemplateOptionsItem Options { get { return m_options; } }
+
+ public void Destroy()
+ {
+ OnActionPerformedEvt = null;
+ }
+
+ public bool IsVisible
+ {
+ get { return m_isVisible; }
+ set { m_isVisible = value; }
+ }
+
+ public bool WasVisible
+ {
+ get { return m_wasVisible; }
+ set { m_wasVisible = value; }
+ }
+
+ public bool CheckOnExecute
+ {
+ get { return m_checkOnExecute; }
+ set { m_checkOnExecute = value; }
+ }
+
+ public InlineProperty FieldValue
+ {
+ get { return m_options.FieldValue; }
+ set { m_options.FieldValue = value; }
+ }
+
+ public float CurrentFieldValue
+ {
+ get { return m_options.FieldValue.FloatValue; }
+ set { m_options.FieldValue.FloatValue = value; }
+ }
+
+ public int CurrentOption
+ {
+ get { return m_currentOption; }
+ set
+ {
+ m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 );
+ // why refreshing here?
+ //Refresh();
+ }
+ }
+
+ public int CurrentOptionIdx
+ {
+ set
+ {
+ m_currentOption = Mathf.Clamp( value, 0, m_options.Options.Length - 1 );
+ }
+ }
+ public bool EmptyEvent { get { return OnActionPerformedEvt == null; } }
+ public TemplateActionItemGrid.TemplateActionItemRow CurrentOptionActions
+ {
+ get
+ {
+ return m_options.ActionsPerOption.Rows[m_currentOption];
+ }
+ }
+ public bool InvertActionOnDeselection { get { return m_invertActionOnDeselection; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta
new file mode 100644
index 00000000..b3f17647
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUI.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 081c72eb35d61c84e9a5c34522c3ff33
+timeCreated: 1534775306
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs
new file mode 100644
index 00000000..06d346b3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs
@@ -0,0 +1,862 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateOptionsUIHelper
+ {
+ private const string CustomOptionsLabel = " Custom Options";
+
+ private bool m_isSubShader = false;
+
+ [SerializeField]
+ private bool m_passCustomOptionsFoldout = true;
+
+ [SerializeField]
+ private string m_passCustomOptionsLabel = CustomOptionsLabel;
+
+ [SerializeField]
+ private int m_passCustomOptionsSizeCheck = 0;
+
+ [SerializeField]
+ private List<TemplateOptionUIItem> m_passCustomOptionsUI = new List<TemplateOptionUIItem>();
+
+ [NonSerialized]
+ private Dictionary<string, TemplateOptionUIItem> m_passCustomOptionsUIDict = new Dictionary<string, TemplateOptionUIItem>();
+
+ [NonSerialized]
+ private TemplateMultiPassMasterNode m_owner;
+
+ [NonSerialized]
+ private string[] m_readOptionNames;
+
+ [NonSerialized]
+ private string[] m_readOptionSelections;
+
+ [SerializeField]
+ private List<TemplateOptionPortItem> m_passCustomOptionsPorts = new List<TemplateOptionPortItem>();
+
+ public TemplateOptionsUIHelper( bool isSubShader )
+ {
+ m_isSubShader = isSubShader;
+ }
+
+ public void CopyOptionsValuesFrom( TemplateOptionsUIHelper origin )
+ {
+ for( int i = 0; i < origin.PassCustomOptionsUI.Count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].CopyValuesFrom( origin.PassCustomOptionsUI[ i ] );
+ }
+ }
+
+ public void Destroy()
+ {
+ for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].Destroy();
+ }
+
+ m_passCustomOptionsUI.Clear();
+ m_passCustomOptionsUI = null;
+
+ m_passCustomOptionsUIDict.Clear();
+ m_passCustomOptionsUIDict = null;
+
+ m_passCustomOptionsPorts.Clear();
+ m_passCustomOptionsPorts = null;
+ }
+
+ public void DrawCustomOptions( TemplateMultiPassMasterNode owner )
+ {
+ m_owner = owner;
+
+ if( m_passCustomOptionsUI.Count > 0 )
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref m_passCustomOptionsFoldout, m_passCustomOptionsLabel, DrawCustomOptionsBlock );
+ }
+ }
+
+ public void DrawCustomOptionsBlock()
+ {
+ float currWidth = EditorGUIUtility.labelWidth;
+#if UNITY_2019_3_OR_NEWER
+ float size = Mathf.Max( UIUtils.CurrentWindow.ParametersWindow.TransformedArea.width * 0.385f, 0 );
+#else
+ float size = Mathf.Max( UIUtils.CurrentWindow.ParametersWindow.TransformedArea.width * 0.34f, 0 );
+#endif
+ EditorGUIUtility.labelWidth = size;
+ for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].Draw( m_owner );
+ }
+ EditorGUILayout.Space();
+ EditorGUIUtility.labelWidth = currWidth;
+ }
+
+ public void OnCustomOptionSelected( bool isRefreshing, bool invertAction, TemplateMultiPassMasterNode owner, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions )
+ {
+ uiItem.CheckOnExecute = false;
+ for( int i = 0; i < validActions.Length; i++ )
+ {
+ AseOptionsActionType actionType = validActions[ i ].ActionType;
+ if( invertAction )
+ {
+ if( !TemplateOptionsToolsHelper.InvertAction( validActions[ i ].ActionType, ref actionType ) )
+ {
+ continue;
+ }
+ }
+
+ switch( actionType )
+ {
+ case AseOptionsActionType.ShowOption:
+ {
+ TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
+ if( item != null )
+ {
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option";
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
+ }
+
+ // this prevents options from showing up when loading by checking if they were hidden by another option
+ // it works on the assumption that an option that may possible hide this one is checked first
+ if( !isRefreshing )
+ item.IsVisible = true;
+ else if( item.WasVisible )
+ item.IsVisible = true;
+
+ if( !invertAction && validActions[ i ].ActionDataIdx > -1 )
+ item.CurrentOption = validActions[ i ].ActionDataIdx;
+
+ item.CheckEnDisable();
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ break;
+ case AseOptionsActionType.HideOption:
+ {
+ TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
+ if( item != null )
+ {
+ bool flag = false;
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + validActions[ i ].ActionData + "Option";
+ flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
+ }
+
+ item.IsVisible = false || flag;
+ if( !invertAction && validActions[ i ].ActionDataIdx > -1 )
+ item.CurrentOption = validActions[ i ].ActionDataIdx;
+
+ item.CheckEnDisable();
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ break;
+ case AseOptionsActionType.SetOption:
+ {
+ if( !uiItem.IsVisible )
+ break;
+
+ TemplateOptionUIItem item = m_passCustomOptionsUI.Find( x => ( x.Options.Name.Equals( validActions[ i ].ActionData ) ) );
+ if( item != null )
+ {
+ item.CurrentOption = validActions[ i ].ActionDataIdx;
+ item.Refresh();
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find Option {0} for action {1}", validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ break;
+ case AseOptionsActionType.HidePort:
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner;
+ if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName,owner.LODIndex );
+ }
+
+ if( passMasterNode != null )
+ {
+ InputPort port = validActions[ i ].ActionDataIdx > -1 ?
+ passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx ) :
+ passMasterNode.InputPorts.Find( x => x.Name.Equals( validActions[ i ].ActionData ) );
+ if( port != null )
+ {
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + port.Name;
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, port.IsConnected );
+ port.Visible = port.IsConnected;
+ }
+ else
+ {
+ port.Visible = false;
+ }
+ passMasterNode.SizeIsDirty = true;
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ break;
+ case AseOptionsActionType.ShowPort:
+ {
+ if( !uiItem.IsVisible )
+ break;
+
+ TemplateMultiPassMasterNode passMasterNode = owner;
+ if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ }
+
+ if( passMasterNode != null )
+ {
+ InputPort port = validActions[ i ].ActionDataIdx > -1 ?
+ passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx ) :
+ passMasterNode.InputPorts.Find( x => x.Name.Equals( validActions[ i ].ActionData ) );
+ if( port != null )
+ {
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + port.Name;
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
+ }
+
+ port.Visible = true;
+ passMasterNode.SizeIsDirty = true;
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ break;
+ case AseOptionsActionType.SetPortName:
+ {
+ if( !uiItem.IsVisible )
+ break;
+
+ TemplateMultiPassMasterNode passMasterNode = owner;
+ if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ }
+
+ if( passMasterNode != null )
+ {
+ InputPort port = passMasterNode.GetInputPortByUniqueId( validActions[ i ].ActionDataIdx );
+ if( port != null )
+ {
+ port.Name = validActions[ i ].ActionData;
+ passMasterNode.SizeIsDirty = true;
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find port {0},{1} for action {2}", validActions[ i ].ActionDataIdx, validActions[ i ].ActionData, validActions[ i ].ActionType );
+ }
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ break;
+ case AseOptionsActionType.SetDefine:
+ {
+ if( !uiItem.IsVisible )
+ {
+ uiItem.CheckOnExecute = true;
+ break;
+ }
+
+ //Debug.Log( "DEFINE " + validActions[ i ].ActionData );
+ if( validActions[ i ].AllPasses )
+ {
+ string actionData = validActions[ i ].ActionData;
+ string defineValue = string.Empty;
+ if( actionData.StartsWith( "pragma" ) )
+ {
+ defineValue = "#" + actionData;
+ }
+ else
+ {
+ defineValue = "#define " + validActions[ i ].ActionData;
+ }
+ if( isRefreshing )
+ {
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true );
+ }
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( defineValue, false );
+ }
+ }
+ else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ if( passMasterNode != null )
+ {
+ string actionData = validActions[ i ].ActionData;
+ string defineValue = string.Empty;
+ if( actionData.StartsWith( "pragma" ) )
+ {
+ defineValue = "#" + actionData;
+ }
+ else
+ {
+ defineValue = "#define " + validActions[ i ].ActionData;
+ }
+ if( isRefreshing )
+ {
+ string optionsId = validActions[ i ].PassName + defineValue;
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true );
+ }
+ passMasterNode.OptionsDefineContainer.AddDefine( defineValue, false );
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ else
+ {
+ uiItem.CheckOnExecute = true;
+ }
+ }
+ break;
+ case AseOptionsActionType.RemoveDefine:
+ {
+ //Debug.Log( "UNDEFINE " + validActions[ i ].ActionData );
+ if( validActions[ i ].AllPasses )
+ {
+ string actionData = validActions[ i ].ActionData;
+ string defineValue = string.Empty;
+ if( actionData.StartsWith( "pragma" ) )
+ {
+ defineValue = "#" + actionData;
+ }
+ else
+ {
+ defineValue = "#define " + validActions[ i ].ActionData;
+ }
+
+ bool flag = false;
+ if( isRefreshing )
+ {
+ flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false );
+ }
+
+ if( !flag )
+ {
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.RemoveDefine( defineValue );
+ }
+ }
+ }
+ else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ if( passMasterNode != null )
+ {
+ string actionData = validActions[ i ].ActionData;
+ string defineValue = string.Empty;
+ if( actionData.StartsWith( "pragma" ) )
+ {
+ defineValue = "#" + actionData;
+ }
+ else
+ {
+ defineValue = "#define " + validActions[ i ].ActionData;
+ }
+ bool flag = false;
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + defineValue;
+ flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
+ }
+ if( !flag )
+ {
+ passMasterNode.OptionsDefineContainer.RemoveDefine( defineValue );
+ }
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ else
+ {
+ uiItem.CheckOnExecute = false;
+ }
+ }
+ break;
+ case AseOptionsActionType.SetUndefine:
+ {
+ if( !uiItem.IsVisible )
+ {
+ uiItem.CheckOnExecute = true;
+ break;
+ }
+
+ if( validActions[ i ].AllPasses )
+ {
+ string defineValue = "#undef " + validActions[ i ].ActionData;
+ if( isRefreshing )
+ {
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, true );
+ }
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes(owner.LODIndex);
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( defineValue, false );
+ }
+ }
+ else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ if( passMasterNode != null )
+ {
+ string defineValue = "#undef " + validActions[ i ].ActionData;
+ if( isRefreshing )
+ {
+ string optionsId = validActions[ i ].PassName + defineValue;
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionsId, true );
+ }
+ passMasterNode.OptionsDefineContainer.AddDefine( defineValue, false );
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ else
+ {
+ uiItem.CheckOnExecute = true;
+ }
+ }
+ break;
+ case AseOptionsActionType.RemoveUndefine:
+ {
+ if( validActions[ i ].AllPasses )
+ {
+ string defineValue = "#undef " + validActions[ i ].ActionData;
+ bool flag = false;
+ if( isRefreshing )
+ {
+ flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( defineValue, false );
+ }
+
+ if( !flag )
+ {
+ List<TemplateMultiPassMasterNode> nodes = owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex );
+ int count = nodes.Count;
+ for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ )
+ {
+ nodes[ nodeIdx ].OptionsDefineContainer.RemoveDefine( defineValue );
+ }
+ }
+ }
+ else if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ if( passMasterNode != null )
+ {
+ bool flag = false;
+ string defineValue = "#undef " + validActions[ i ].ActionData;
+ if( isRefreshing )
+ {
+ string optionId = validActions[ i ].PassName + defineValue;
+ flag = owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false );
+ }
+
+ if( !flag )
+ {
+ passMasterNode.OptionsDefineContainer.RemoveDefine( defineValue );
+ }
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ else
+ {
+ uiItem.CheckOnExecute = false;
+ }
+ }
+ break;
+ case AseOptionsActionType.ExcludePass:
+ {
+ string optionId = validActions[ i ].ActionData + "Pass";
+ bool flag = isRefreshing ? owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, false ) : false;
+ if( !flag )
+ owner.SetPassVisible( validActions[ i ].ActionData, false );
+ }
+ break;
+ case AseOptionsActionType.IncludePass:
+ {
+ if( !uiItem.IsVisible )
+ break;
+
+ string optionId = validActions[ i ].ActionData + "Pass";
+ owner.ContainerGraph.ParentWindow.TemplatesManagerInstance.SetOptionsValue( optionId, true );
+ owner.SetPassVisible( validActions[ i ].ActionData, true );
+ }
+ break;
+ case AseOptionsActionType.SetPropertyOnPass:
+ {
+ //Debug.Log( "PASSPROP " + validActions[ i ].ActionData );
+ //Refresh happens on hotcode reload and shader load and in those situation
+ // The property own serialization handles its setup
+ if( isRefreshing )
+ continue;
+
+ if( !string.IsNullOrEmpty( validActions[ i ].PassName ) )
+ {
+ TemplateMultiPassMasterNode passMasterNode = owner.ContainerGraph.GetMasterNodeOfPass( validActions[ i ].PassName, owner.LODIndex );
+ if( passMasterNode != null )
+ {
+ passMasterNode.SetPropertyActionFromItem( passMasterNode.PassModule, validActions[ i ] );
+ }
+ else
+ {
+ Debug.LogFormat( "Could not find pass {0} for action {1} on {2}", validActions[ i ].PassName, validActions[ i ].ActionType, validActions[ i ].ActionData );
+ }
+ }
+ else
+ {
+ owner.SetPropertyActionFromItem( owner.PassModule, validActions[ i ] );
+ }
+ }
+ break;
+ case AseOptionsActionType.SetPropertyOnSubShader:
+ {
+ //Refresh happens on hotcode reload and shader load and in those situation
+ // The property own serialization handles its setup
+ if( isRefreshing )
+ continue;
+
+ owner.SetPropertyActionFromItem( owner.SubShaderModule, validActions[ i ] );
+ }
+ break;
+ case AseOptionsActionType.SetShaderProperty:
+ {
+ //This action is only check when shader is compiled over
+ //the TemplateMultiPassMasterNode via the on CheckPropertyChangesOnOptions() method
+ }
+ break;
+ case AseOptionsActionType.SetMaterialProperty:
+ {
+ if( isRefreshing )
+ continue;
+
+ if( !uiItem.IsVisible )
+ break;
+
+ if( owner.ContainerGraph.CurrentMaterial != null )
+ {
+ string prop = validActions[ i ].ActionData;
+ if( owner.ContainerGraph.CurrentMaterial.HasProperty( prop ) )
+ {
+ if( uiItem.Options.UIWidget == AseOptionsUIWidget.Float || uiItem.Options.UIWidget == AseOptionsUIWidget.FloatRange )
+ owner.ContainerGraph.CurrentMaterial.SetFloat( prop, uiItem.CurrentFieldValue );
+ else
+ owner.ContainerGraph.CurrentMaterial.SetInt( prop, (int)uiItem.CurrentFieldValue );
+
+ if( ASEMaterialInspector.Instance != null )
+ ASEMaterialInspector.Instance.Repaint();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ public void SetupCustomOptionsFromTemplate( TemplateMultiPassMasterNode owner, bool newTemplate )
+ {
+ TemplateOptionsContainer customOptionsContainer = m_isSubShader ? owner.SubShader.CustomOptionsContainer : owner.Pass.CustomOptionsContainer;
+
+ if( !newTemplate && customOptionsContainer.Body.Length == m_passCustomOptionsSizeCheck )
+ {
+ for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
+ {
+ if( m_passCustomOptionsUI[ i ].EmptyEvent )
+ {
+ if( m_isSubShader )
+ {
+ m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
+ }
+ else
+ {
+ m_passCustomOptionsUI[ i ].OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
+ }
+ }
+ }
+ return;
+ }
+
+ m_passCustomOptionsLabel = string.IsNullOrEmpty( customOptionsContainer.Name ) ? CustomOptionsLabel : " " + customOptionsContainer.Name;
+
+ for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].Destroy();
+ }
+
+ m_passCustomOptionsUI.Clear();
+ m_passCustomOptionsUIDict.Clear();
+ m_passCustomOptionsPorts.Clear();
+
+ if( customOptionsContainer.Enabled )
+ {
+ m_passCustomOptionsSizeCheck = customOptionsContainer.Body.Length;
+ for( int i = 0; i < customOptionsContainer.Options.Length; i++ )
+ {
+ switch( customOptionsContainer.Options[ i ].Type )
+ {
+ case AseOptionsType.Option:
+ {
+ TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] );
+ if( m_isSubShader )
+ {
+ item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
+ }
+ else
+ {
+ item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
+ }
+
+ m_passCustomOptionsUI.Add( item );
+ m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item );
+ }
+ break;
+ case AseOptionsType.Port:
+ {
+ TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
+ m_passCustomOptionsPorts.Add( item );
+ //if( m_isSubShader )
+ //{
+ // if( string.IsNullOrEmpty( customOptionsContainer.Options[ i ].Id ) )
+ // {
+ // //No pass name selected. inject on all passes
+ // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
+ // m_passCustomOptionsPorts.Add( item );
+ // }
+ // else if( customOptionsContainer.Options[ i ].Id.Equals( owner.PassName ) )
+ // {
+ // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
+ // m_passCustomOptionsPorts.Add( item );
+ // }
+ //}
+ //else
+ //{
+ // TemplateOptionPortItem item = new TemplateOptionPortItem( owner, customOptionsContainer.Options[ i ] );
+ // m_passCustomOptionsPorts.Add( item );
+ //}
+ }
+ break;
+ case AseOptionsType.Field:
+ {
+ TemplateOptionUIItem item = new TemplateOptionUIItem( customOptionsContainer.Options[ i ] );
+ if( m_isSubShader )
+ {
+ item.OnActionPerformedEvt += owner.OnCustomSubShaderOptionSelected;
+ }
+ else
+ {
+ item.OnActionPerformedEvt += owner.OnCustomPassOptionSelected;
+ }
+
+ m_passCustomOptionsUI.Add( item );
+ m_passCustomOptionsUIDict.Add( customOptionsContainer.Options[ i ].Id, item );
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ m_passCustomOptionsSizeCheck = 0;
+ }
+ }
+
+ public void SetCustomOptionsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector )
+ {
+ if( masterNode == null )
+ return;
+
+ for( int i = 0; i < m_passCustomOptionsUI.Count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].FillDataCollector( ref dataCollector );
+ }
+
+ for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
+ {
+ m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector );
+ }
+ }
+
+ public void CheckImediateActionsForPort( TemplateMultiPassMasterNode masterNode , int portId )
+ {
+ for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
+ {
+ m_passCustomOptionsPorts[ i ].CheckImediateActionsForPort( masterNode, portId );
+ }
+ }
+
+ public void SetSubShaderCustomOptionsPortsInfo( TemplateMultiPassMasterNode masterNode, ref MasterNodeDataCollector dataCollector )
+ {
+ if( masterNode == null )
+ return;
+
+
+ //for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
+ //{
+ // if( string.IsNullOrEmpty( m_passCustomOptionsPorts[ i ].Options.Id ) ||
+ // masterNode.PassUniqueName.Equals( m_passCustomOptionsPorts[ i ].Options.Id ) )
+ // {
+ // m_passCustomOptionsPorts[ i ].FillDataCollector( masterNode, ref dataCollector );
+ // }
+ //}
+
+ for( int i = 0; i < m_passCustomOptionsPorts.Count; i++ )
+ {
+ m_passCustomOptionsPorts[ i ].SubShaderFillDataCollector( masterNode, ref dataCollector );
+ }
+ }
+
+ public void RefreshCustomOptionsDict()
+ {
+ if( m_passCustomOptionsUIDict.Count != m_passCustomOptionsUI.Count )
+ {
+ m_passCustomOptionsUIDict.Clear();
+ int count = m_passCustomOptionsUI.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_passCustomOptionsUIDict.Add( m_passCustomOptionsUI[ i ].Options.Id, m_passCustomOptionsUI[ i ] );
+ }
+ }
+ }
+
+ public void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ RefreshCustomOptionsDict();
+ int savedOptions = Convert.ToInt32( nodeParams[ index++ ] );
+
+ m_readOptionNames = new string[ savedOptions ];
+ m_readOptionSelections = new string[ savedOptions ];
+
+ for( int i = 0; i < savedOptions; i++ )
+ {
+ string optionName = nodeParams[ index++ ];
+ string optionSelection = nodeParams[ index++ ];
+ m_readOptionNames[ i ] = optionName;
+ m_readOptionSelections[ i ] = optionSelection;
+
+ }
+ }
+
+ public void SetReadOptions()
+ {
+ if( m_readOptionNames != null && m_readOptionSelections != null )
+ {
+ for( int i = 0; i < m_readOptionNames.Length; i++ )
+ {
+ if( m_passCustomOptionsUIDict.ContainsKey( m_readOptionNames[ i ] ) )
+ {
+ if( m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].Options.Type == AseOptionsType.Field )
+ {
+ m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].FieldValue.ReadFromSingle( m_readOptionSelections[ i ] );
+ foreach( var item in m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].Options.ActionsPerOption.Rows )
+ {
+ if( item.Columns.Length>0 && item.Columns[ 0 ].ActionType == AseOptionsActionType.SetMaterialProperty )
+ {
+ if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial != null )
+ {
+ if( UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.HasProperty( item.Columns[ 0 ].ActionData ) )
+ {
+ m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].CurrentFieldValue = UIUtils.CurrentWindow.CurrentGraph.CurrentMaterial.GetFloat( item.Columns[ 0 ].ActionData );
+ }
+ }
+ }
+ }
+ }
+ else
+ m_passCustomOptionsUIDict[ m_readOptionNames[ i ] ].CurrentOptionIdx = Convert.ToInt32( m_readOptionSelections[ i ] );
+ }
+ }
+ }
+ }
+
+ public void Refresh()
+ {
+ int count = m_passCustomOptionsUI.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].Refresh();
+ }
+ }
+
+ public void CheckDisable()
+ {
+ int count = m_passCustomOptionsUI.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_passCustomOptionsUI[ i ].CheckEnDisable();
+ }
+ }
+
+ public void WriteToString( ref string nodeInfo )
+ {
+ int optionsCount = m_passCustomOptionsUI.Count;
+ IOUtils.AddFieldValueToString( ref nodeInfo, optionsCount );
+ for( int i = 0; i < optionsCount; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].Options.Id );
+ if( m_passCustomOptionsUI[ i ].Options.Type == AseOptionsType.Field )
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].FieldValue.WriteToSingle() );
+ else
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_passCustomOptionsUI[ i ].CurrentOption );
+ }
+ }
+
+ public List<TemplateOptionUIItem> PassCustomOptionsUI { get { return m_passCustomOptionsUI; } }
+
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta
new file mode 100644
index 00000000..077260b0
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateOptionsUIHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 389dcf32e61ce9d47b9a92ab691365d3
+timeCreated: 1544089703
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs
new file mode 100644
index 00000000..22ea92f4
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs
@@ -0,0 +1,631 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+#define CUSTOM_OPTIONS_AVAILABLE
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace AmplifyShaderEditor
+{
+
+ [Serializable]
+ public class TemplatePass
+ {
+ private const string DefaultPassNameStr = "SubShader {0} Pass {1}";
+
+ [SerializeField]
+ private int m_idx = -1;
+
+ [SerializeField]
+ private bool m_isInvisible = false;
+
+ [SerializeField]
+ private int m_invisibleOptions = 0;
+
+ [SerializeField]
+ private bool m_isMainPass = false;
+
+ [SerializeField]
+ private TemplateModulesData m_modules;
+
+ [SerializeField]
+ private List<TemplateInputData> m_inputDataList = new List<TemplateInputData>();
+ private Dictionary<int, TemplateInputData> m_inputDataDict = new Dictionary<int, TemplateInputData>();
+
+ [SerializeField]
+ private TemplateFunctionData m_vertexFunctionData;
+
+ [SerializeField]
+ private TemplateFunctionData m_fragmentFunctionData;
+
+ [SerializeField]
+ private VertexDataContainer m_vertexDataContainer;
+
+ [SerializeField]
+ private TemplateInterpData m_interpolatorDataContainer;
+
+ [SerializeField]
+ private TemplateTessVControlTag m_tessVControlTag;
+
+ [SerializeField]
+ private TemplateTessControlData m_tessControlData;
+
+ [SerializeField]
+ private TemplateTessDomainData m_tessDomainData;
+
+ [SerializeField]
+ private List<TemplateLocalVarData> m_localVarsList = new List<TemplateLocalVarData>();
+
+ [SerializeField]
+ private string m_uniquePrefix;
+
+ [SerializeField]
+ private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer();
+
+ [SerializeField]
+ private List<TemplateShaderPropertyData> m_availableShaderGlobals = new List<TemplateShaderPropertyData>();
+
+ [SerializeField]
+ TemplateInfoContainer m_passNameContainer = new TemplateInfoContainer();
+#if CUSTOM_OPTIONS_AVAILABLE
+ [SerializeField]
+ TemplateOptionsContainer m_customOptionsContainer = new TemplateOptionsContainer();
+#endif
+ public TemplatePass( TemplateMultiPass template, TemplateSubShader subShader, int subshaderIdx, int passIdx, TemplateIdManager idManager, string uniquePrefix, int offsetIdx, TemplatePassInfo passInfo, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ m_idx = passIdx;
+
+ m_uniquePrefix = uniquePrefix;
+ idManager.RegisterPassId( passInfo.Data );
+ m_isMainPass = passInfo.Data.Contains( TemplatesManager.TemplateMainPassTag );
+ if( !m_isMainPass )
+ {
+ string id = string.Empty;
+ int idIndex = 0;
+ m_isInvisible = TemplateHelperFunctions.FetchInvisibleInfo( passInfo.Data, ref m_invisibleOptions, ref id, ref idIndex );
+ if( m_isInvisible )
+ {
+ idManager.RegisterId( idIndex, uniquePrefix + id, id, true );
+ }
+ }
+
+ FetchPassName( offsetIdx, passInfo.Data );
+ if( m_passNameContainer.Index > -1 )
+ {
+ idManager.RegisterId( m_passNameContainer.Index, uniquePrefix + m_passNameContainer.Id, m_passNameContainer.Id );
+ }
+ else
+ {
+ m_passNameContainer.Data = string.Format( DefaultPassNameStr, subshaderIdx, passIdx );
+ }
+
+#if CUSTOM_OPTIONS_AVAILABLE
+ m_customOptionsContainer = TemplateOptionsToolsHelper.GenerateOptionsContainer( false, passInfo.Data );
+ if( m_customOptionsContainer.Enabled )
+ {
+ idManager.RegisterId( m_customOptionsContainer.Index, uniquePrefix + m_customOptionsContainer.Body, m_customOptionsContainer.Body, true );
+ }
+ //m_customOptionsContainer.CopyPortOptionsFrom( subShader.CustomOptionsContainer, m_passNameContainer.Data );
+#endif
+ m_modules = new TemplateModulesData( m_customOptionsContainer,idManager, m_templateProperties, uniquePrefix + "Module", offsetIdx, passInfo.Data, false );
+
+ if( !m_modules.PassTag.IsValid )
+ {
+ m_modules.PassTag.StartIdx = passInfo.GlobalStartIdx;
+ m_templateProperties.AddId( passInfo.Data, m_modules.PassTag.Id, passInfo.LocalStartIdx, false );
+ //m_modules.PassTag.StartIdx -= m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].Indentation.Length;
+ //m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].UseIndentationAtStart = false;
+ idManager.RegisterId( m_modules.PassTag.StartIdx, m_modules.UniquePrefix + m_modules.PassTag.Id, string.Empty );
+ }
+ m_modules.SetPassUniqueNameIfUndefined( m_passNameContainer.Data );
+
+ m_modules.SRPType = subShader.Modules.SRPType;
+ if( m_modules.SRPType == TemplateSRPType.HD )
+ {
+ m_modules.SRPIsPBR = passInfo.Data.Contains( TemplateHelperFunctions.HDPBRTag );
+
+ }
+
+ Dictionary<string, TemplateShaderPropertyData> ownDuplicatesDict = new Dictionary<string, TemplateShaderPropertyData>( duplicatesHelper );
+ TemplateHelperFunctions.CreateShaderGlobalsList( passInfo.Data, ref m_availableShaderGlobals, ref ownDuplicatesDict );
+
+ // Vertex and Interpolator data
+ FetchVertexAndInterpData( template, subShader.Modules, offsetIdx, passInfo.Data );
+ if( m_vertexDataContainer != null )
+ idManager.RegisterId( m_vertexDataContainer.VertexDataStartIdx, uniquePrefix + m_vertexDataContainer.VertexDataId, m_vertexDataContainer.VertexDataId );
+
+ if( m_interpolatorDataContainer != null )
+ idManager.RegisterId( m_interpolatorDataContainer.InterpDataStartIdx, uniquePrefix + m_interpolatorDataContainer.InterpDataId, m_interpolatorDataContainer.InterpDataId );
+
+ //Fetch function code areas
+ FetchCodeAreas( offsetIdx, TemplatesManager.TemplateVertexCodeBeginArea, MasterNodePortCategory.Vertex, passInfo.Data );
+ if( m_vertexFunctionData != null )
+ idManager.RegisterId( m_vertexFunctionData.Position, uniquePrefix + m_vertexFunctionData.Id, m_vertexFunctionData.Id );
+
+ FetchCodeAreas( offsetIdx, TemplatesManager.TemplateFragmentCodeBeginArea, MasterNodePortCategory.Fragment, passInfo.Data );
+ if( m_fragmentFunctionData != null )
+ idManager.RegisterId( m_fragmentFunctionData.Position, uniquePrefix + m_fragmentFunctionData.Id, m_fragmentFunctionData.Id );
+
+ //Fetching inputs, must be do
+ if( m_fragmentFunctionData != null )
+ FetchInputs( offsetIdx, MasterNodePortCategory.Fragment, passInfo.Data );
+
+ if( m_vertexFunctionData != null )
+ FetchInputs( offsetIdx, MasterNodePortCategory.Vertex, passInfo.Data );
+
+ FetchTessellationData( template, subShader.Modules, offsetIdx, passInfo.Data );
+ if( m_tessVControlTag != null )
+ idManager.RegisterId( m_tessVControlTag.StartIdx, uniquePrefix + m_tessVControlTag.Id, m_tessVControlTag.Id );
+
+ if( m_tessControlData != null )
+ idManager.RegisterId( m_tessControlData.StartIdx, uniquePrefix + m_tessControlData.Id, m_tessControlData.Id );
+
+ if( m_tessDomainData != null )
+ idManager.RegisterId( m_tessDomainData.StartIdx, uniquePrefix + m_tessDomainData.Id, m_tessDomainData.Id );
+
+ TemplateHelperFunctions.FetchInlineVars( passInfo.Data, ref idManager );
+
+ //Fetch local variables must be done after fetching code areas as it needs them to see is variable is on vertex or fragment
+ TemplateHelperFunctions.FetchLocalVars( passInfo.Data, ref m_localVarsList, m_vertexFunctionData, m_fragmentFunctionData );
+
+ int localVarCount = m_localVarsList.Count;
+ if( localVarCount > 0 )
+ {
+ idManager.RegisterTag( TemplatesManager.TemplateLocalVarTag );
+ for( int i = 0; i < localVarCount; i++ )
+ {
+ if( m_localVarsList[ i ].IsSpecialVar )
+ {
+ idManager.RegisterTag( m_localVarsList[ i ].Id );
+ }
+ }
+ }
+
+ int inputsCount = m_inputDataList.Count;
+ for( int i = 0; i < inputsCount; i++ )
+ {
+ if( m_inputDataList[ i ] != null )
+ idManager.RegisterId( m_inputDataList[ i ].TagGlobalStartIdx, uniquePrefix + m_inputDataList[ i ].TagId, m_inputDataList[ i ].TagId );
+ }
+
+ //int passEndIndex = passInfo.Data.LastIndexOf( "}" );
+ //if( passEndIndex > 0 )
+ //{
+ // int identationIndex = -1;
+ // for( int i = passEndIndex; i >= 0; i-- )
+ // {
+ // if( passInfo.Data[ i ] == TemplatesManager.TemplateNewLine )
+ // {
+ // identationIndex = i + 1;
+ // break;
+ // }
+
+ // if( i == 0 )
+ // {
+ // identationIndex = 0;
+ // }
+ // }
+
+ // if( identationIndex > -1 )
+ // {
+ // int length = passEndIndex - identationIndex;
+ // string indentation = ( length > 0 ) ? passInfo.Data.Substring( identationIndex, length ) : string.Empty;
+ // TemplateProperty templateProperty = new TemplateProperty( TemplatesManager.TemplateEndPassTag, indentation, false );
+ // m_templateProperties.AddId( templateProperty );
+ // idManager.RegisterId( offsetIdx + passEndIndex, uniquePrefix + TemplatesManager.TemplateEndPassTag, string.Empty );
+ // }
+ //}
+
+ ownDuplicatesDict.Clear();
+ ownDuplicatesDict = null;
+ }
+
+ public void Destroy()
+ {
+ m_passNameContainer = null;
+#if CUSTOM_OPTIONS_AVAILABLE
+ m_customOptionsContainer = null;
+#endif
+ if( m_templateProperties != null )
+ m_templateProperties.Destroy();
+
+ m_templateProperties = null;
+
+ if( m_modules != null )
+ m_modules.Destroy();
+
+ m_modules = null;
+
+ if( m_inputDataList != null )
+ m_inputDataList.Clear();
+
+ m_inputDataList = null;
+
+ if( m_inputDataDict != null )
+ m_inputDataDict.Clear();
+
+ m_inputDataDict = null;
+
+ m_vertexFunctionData = null;
+ m_fragmentFunctionData = null;
+
+ if( m_vertexDataContainer != null )
+ m_vertexDataContainer.Destroy();
+
+ m_vertexDataContainer = null;
+
+ m_tessVControlTag = null;
+
+ m_tessControlData = null;
+
+ m_tessDomainData = null;
+
+ if( m_interpolatorDataContainer != null )
+ m_interpolatorDataContainer.Destroy();
+
+ if( m_localVarsList != null )
+ {
+ m_localVarsList.Clear();
+ m_localVarsList = null;
+ }
+
+ m_interpolatorDataContainer = null;
+
+ if( m_availableShaderGlobals != null )
+ m_availableShaderGlobals.Clear();
+
+ m_availableShaderGlobals = null;
+ }
+
+ public TemplateInputData InputDataFromId( int id )
+ {
+ if( m_inputDataDict == null )
+ m_inputDataDict = new Dictionary<int, TemplateInputData>();
+
+ if( m_inputDataDict.Count != m_inputDataList.Count )
+ {
+ m_inputDataDict.Clear();
+ for( int i = 0; i < m_inputDataList.Count; i++ )
+ {
+ m_inputDataDict.Add( m_inputDataList[ i ].PortUniqueId, m_inputDataList[ i ] );
+ }
+ }
+
+ if( m_inputDataDict.ContainsKey( id ) )
+ return m_inputDataDict[ id ];
+
+ return null;
+ }
+
+ void FetchPassName( int offsetIdx, string body )
+ {
+ Match match = Regex.Match( body, TemplateHelperFunctions.PassNamePattern );
+ if( match != null && match.Groups.Count > 1 )
+ {
+ m_passNameContainer.Id = match.Groups[ 0 ].Value;
+ m_passNameContainer.Data = match.Groups[ 1 ].Value;
+ m_passNameContainer.Index = offsetIdx + match.Index;
+ }
+ }
+
+ void FetchTessellationData( TemplateMultiPass template, TemplateModulesData subShaderModule, int offsetIdx, string body )
+ {
+ // Tessellation VControl Tag
+ try
+ {
+ int vcontrolcodeBegin = body.IndexOf( TemplatesManager.TemplateTessVControlTag );
+ if( vcontrolcodeBegin > -1 )
+ {
+ m_tessVControlTag = new TemplateTessVControlTag();
+ m_tessVControlTag.Id = TemplatesManager.TemplateTessVControlTag;
+ m_tessVControlTag.StartIdx = offsetIdx + vcontrolcodeBegin;
+
+ m_templateProperties.AddId( body, m_tessVControlTag.Id );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ // Tessellation Control Data
+ try
+ {
+ int controlCodeBegin = body.IndexOf( TemplatesManager.TemplateTessControlCodeArea );
+ if( controlCodeBegin > -1 )
+ {
+ int beginIdx = controlCodeBegin + TemplatesManager.TemplateTessControlCodeArea.Length;
+ int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx );
+ int length = endIdx - beginIdx;
+
+ string parameters = body.Substring( beginIdx, length );
+
+ string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR );
+
+ string id = body.Substring( controlCodeBegin, endIdx + TemplatesManager.TemplateEndOfLine.Length - controlCodeBegin );
+ string inParameters = parametersArr[ 0 ];
+ string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty;
+
+ m_tessControlData = new TemplateTessControlData( offsetIdx + controlCodeBegin, id, inParameters, outParameters );
+
+ m_templateProperties.AddId( body, id );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ // Tessellation Domain Data
+ try
+ {
+ int domainCodeBegin = body.IndexOf( TemplatesManager.TemplateTessDomainCodeArea );
+ if( domainCodeBegin > -1 )
+ {
+ int beginIdx = domainCodeBegin + TemplatesManager.TemplateTessDomainCodeArea.Length;
+ int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx );
+ int length = endIdx - beginIdx;
+
+ string parameters = body.Substring( beginIdx, length );
+
+ string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR );
+
+ string id = body.Substring( domainCodeBegin, endIdx + TemplatesManager.TemplateEndOfLine.Length - domainCodeBegin );
+ string inParameters = ( parametersArr.Length > 0 ) ? parametersArr[ 0 ] : string.Empty;
+ string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty;
+ string baryParameters = ( parametersArr.Length > 2 ) ? parametersArr[ 2 ] : string.Empty;
+
+ m_tessDomainData = new TemplateTessDomainData( offsetIdx + domainCodeBegin, id, inParameters, outParameters, baryParameters );
+
+ m_templateProperties.AddId( body, id );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ void FetchVertexAndInterpData(TemplateMultiPass template, TemplateModulesData subShaderModule, int offsetIdx, string body )
+ {
+ // Vertex Data
+ try
+ {
+ int vertexDataTagBegin = body.IndexOf( TemplatesManager.TemplateVertexDataTag );
+ if( vertexDataTagBegin > -1 )
+ {
+ m_vertexDataContainer = new VertexDataContainer();
+ m_vertexDataContainer.VertexDataStartIdx = offsetIdx + vertexDataTagBegin;
+ int vertexDataTagEnd = body.IndexOf( TemplatesManager.TemplateEndOfLine, vertexDataTagBegin );
+ m_vertexDataContainer.VertexDataId = body.Substring( vertexDataTagBegin, vertexDataTagEnd + TemplatesManager.TemplateEndOfLine.Length - vertexDataTagBegin );
+ int dataBeginIdx = body.LastIndexOf( '{', vertexDataTagBegin, vertexDataTagBegin );
+ string vertexData = body.Substring( dataBeginIdx + 1, vertexDataTagBegin - dataBeginIdx );
+
+ int parametersBegin = vertexDataTagBegin + TemplatesManager.TemplateVertexDataTag.Length;
+ string parameters = body.Substring( parametersBegin, vertexDataTagEnd - parametersBegin );
+ m_vertexDataContainer.VertexData = TemplateHelperFunctions.CreateVertexDataList( vertexData, parameters );
+ m_templateProperties.AddId( body, m_vertexDataContainer.VertexDataId );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ // Available interpolators
+ try
+ {
+ int interpDataBegin = body.IndexOf( TemplatesManager.TemplateInterpolatorBeginTag );
+ if( interpDataBegin > -1 )
+ {
+ int interpDataEnd = body.IndexOf( TemplatesManager.TemplateEndOfLine, interpDataBegin );
+ string interpDataId = body.Substring( interpDataBegin, interpDataEnd + TemplatesManager.TemplateEndOfLine.Length - interpDataBegin );
+
+ int dataBeginIdx = body.LastIndexOf( '{', interpDataBegin, interpDataBegin );
+ string interpData = body.Substring( dataBeginIdx + 1, interpDataBegin - dataBeginIdx );
+
+ int interpolatorAmount = TemplateHelperFunctions.AvailableInterpolators[ "2.5" ];
+
+ if( m_modules.ShaderModel.IsValid )
+ {
+ interpolatorAmount = m_modules.ShaderModel.InterpolatorAmount;
+ }
+ else if( subShaderModule.ShaderModel.IsValid )
+ {
+ interpolatorAmount = subShaderModule.ShaderModel.InterpolatorAmount;
+ }
+ else if( template.GlobalShaderModel.IsValid )
+ {
+ interpolatorAmount = template.GlobalShaderModel.InterpolatorAmount;
+ }
+
+ m_interpolatorDataContainer = TemplateHelperFunctions.CreateInterpDataList( interpData, interpDataId, interpolatorAmount );
+ m_interpolatorDataContainer.InterpDataId = interpDataId;
+ m_interpolatorDataContainer.InterpDataStartIdx = offsetIdx + interpDataBegin;
+ m_templateProperties.AddId( body, interpDataId );
+
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ void FetchCodeAreas( int offsetIdx, string begin, MasterNodePortCategory category, string body )
+ {
+ int areaBeginIndexes = body.IndexOf( begin );
+ if( areaBeginIndexes > -1 )
+ {
+ int beginIdx = areaBeginIndexes + begin.Length;
+ int endIdx = body.IndexOf( TemplatesManager.TemplateEndOfLine, beginIdx );
+ int length = endIdx - beginIdx;
+
+ string parameters = body.Substring( beginIdx, length );
+
+ string[] parametersArr = parameters.Split( IOUtils.FIELD_SEPARATOR );
+
+ string id = body.Substring( areaBeginIndexes, endIdx + TemplatesManager.TemplateEndOfLine.Length - areaBeginIndexes );
+ string inParameters = parametersArr[ 0 ];
+ string outParameters = ( parametersArr.Length > 1 ) ? parametersArr[ 1 ] : string.Empty;
+ if( category == MasterNodePortCategory.Fragment )
+ {
+ string mainBodyName = string.Empty;
+ int mainBodyLocalIndex = -1;
+
+ Match mainBodyNameMatch = Regex.Match( body, TemplateHelperFunctions.FragmentPragmaPattern );
+ if( mainBodyNameMatch != null && mainBodyNameMatch.Groups.Count == 2 )
+ {
+ mainBodyName = mainBodyNameMatch.Groups[ 1 ].Value;
+ string pattern = string.Format( TemplateHelperFunctions.FunctionBodyStartPattern, mainBodyName );
+ Match mainBodyIdMatch = Regex.Match( body, pattern );
+ if( mainBodyIdMatch != null && mainBodyIdMatch.Groups.Count > 0 )
+ {
+ mainBodyLocalIndex = mainBodyIdMatch.Index;
+ }
+
+ }
+
+ m_fragmentFunctionData = new TemplateFunctionData( mainBodyLocalIndex, mainBodyName, id, offsetIdx + areaBeginIndexes, inParameters, outParameters, category );
+ }
+ else
+ {
+ string mainBodyName = string.Empty;
+ int mainBodyLocalIndex = -1;
+
+ Match mainBodyNameMatch = Regex.Match( body, TemplateHelperFunctions.VertexPragmaPattern );
+ if( mainBodyNameMatch != null && mainBodyNameMatch.Groups.Count == 2 )
+ {
+ mainBodyName = mainBodyNameMatch.Groups[ 1 ].Value;
+ string pattern = string.Format( TemplateHelperFunctions.FunctionBodyStartPattern, mainBodyName );
+ Match mainBodyIdMatch = Regex.Match( body, pattern );
+ if( mainBodyIdMatch != null && mainBodyIdMatch.Groups.Count > 0 )
+ {
+ mainBodyLocalIndex = mainBodyIdMatch.Index;
+ }
+ }
+
+ m_vertexFunctionData = new TemplateFunctionData( mainBodyLocalIndex, mainBodyName, id, offsetIdx + areaBeginIndexes, inParameters, outParameters, category );
+ }
+ m_templateProperties.AddId( body, id, true );
+ }
+ }
+
+ void FetchInputs( int offset, MasterNodePortCategory portCategory, string body )
+ {
+ string beginTag = ( portCategory == MasterNodePortCategory.Fragment ) ? TemplatesManager.TemplateInputsFragBeginTag : TemplatesManager.TemplateInputsVertBeginTag;
+ int[] inputBeginIndexes = body.AllIndexesOf( beginTag );
+ if( inputBeginIndexes != null && inputBeginIndexes.Length > 0 )
+ {
+ for( int i = 0; i < inputBeginIndexes.Length; i++ )
+ {
+ int inputEndIdx = body.IndexOf( TemplatesManager.TemplateEndSectionTag, inputBeginIndexes[ i ] );
+ int defaultValueBeginIdx = inputEndIdx + TemplatesManager.TemplateEndSectionTag.Length;
+ int endLineIdx = body.IndexOf( TemplatesManager.TemplateFullEndTag, defaultValueBeginIdx );
+
+ string defaultValue = body.Substring( defaultValueBeginIdx, endLineIdx - defaultValueBeginIdx );
+ string tagId = body.Substring( inputBeginIndexes[ i ], endLineIdx + TemplatesManager.TemplateFullEndTag.Length - inputBeginIndexes[ i ] );
+
+ int beginIndex = inputBeginIndexes[ i ] + beginTag.Length;
+ int length = inputEndIdx - beginIndex;
+ string inputData = body.Substring( beginIndex, length );
+ string[] inputDataArray = inputData.Split( IOUtils.FIELD_SEPARATOR );
+
+ if( inputDataArray != null && inputDataArray.Length > 0 )
+ {
+ try
+ {
+ string portName = inputDataArray[ (int)TemplatePortIds.Name ];
+ WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), inputDataArray[ (int)TemplatePortIds.DataType ].ToUpper() );
+ if( inputDataArray.Length == 3 )
+ {
+ int portOrderId = m_inputDataList.Count;
+ int portUniqueId = -1;
+ bool isInt = int.TryParse( inputDataArray[ 2 ], out portUniqueId );
+ if( isInt )
+ {
+ if( portUniqueId < 0 )
+ portUniqueId = m_inputDataList.Count;
+
+ m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, string.Empty ) );
+ m_templateProperties.AddId( body, tagId, false );
+ }
+ else
+ {
+ portUniqueId = m_inputDataList.Count;
+ m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, inputDataArray[ 2 ] ) );
+ m_templateProperties.AddId( body, tagId, false );
+ }
+ }
+ else
+ {
+ int portUniqueIDArrIdx = (int)TemplatePortIds.UniqueId;
+ int portUniqueId = ( portUniqueIDArrIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portUniqueIDArrIdx ] ) : -1;
+ if( portUniqueId < 0 )
+ portUniqueId = m_inputDataList.Count;
+
+ int portOrderArrayIdx = (int)TemplatePortIds.OrderId;
+ int portOrderId = ( portOrderArrayIdx < inputDataArray.Length ) ? Convert.ToInt32( inputDataArray[ portOrderArrayIdx ] ) : -1;
+ if( portOrderId < 0 )
+ portOrderId = m_inputDataList.Count;
+
+ int portLinkIdx = (int)TemplatePortIds.Link;
+ string linkId = ( portLinkIdx < inputDataArray.Length ) ? inputDataArray[ portLinkIdx ] : string.Empty;
+ m_inputDataList.Add( new TemplateInputData( inputBeginIndexes[ i ], offset + inputBeginIndexes[ i ], tagId, portName, defaultValue, dataType, portCategory, portUniqueId, portOrderId, linkId ) );
+ m_templateProperties.AddId( body, tagId, false );
+ }
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ }
+ }
+ }
+
+#if CUSTOM_OPTIONS_AVAILABLE
+ public TemplateOptionsContainer CustomOptionsContainer { get { return m_customOptionsContainer; } }
+#endif
+ public TemplateModulesData Modules { get { return m_modules; } }
+ public List<TemplateInputData> InputDataList { get { return m_inputDataList; } }
+ public TemplateFunctionData VertexFunctionData { get { return m_vertexFunctionData; } }
+ public TemplateFunctionData FragmentFunctionData { get { return m_fragmentFunctionData; } }
+ public VertexDataContainer VertexDataContainer { get { return m_vertexDataContainer; } }
+ public TemplateInterpData InterpolatorDataContainer { get { return m_interpolatorDataContainer; } }
+ public TemplateTessVControlTag TessVControlTag { get { return m_tessVControlTag; } }
+ public TemplateTessControlData TessControlData { get { return m_tessControlData; } }
+ public TemplateTessDomainData TessDomainData { get { return m_tessDomainData; } }
+ public string UniquePrefix { get { return m_uniquePrefix; } }
+ public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } }
+ public List<TemplateShaderPropertyData> AvailableShaderGlobals { get { return m_availableShaderGlobals; } }
+ public List<TemplateLocalVarData> LocalVarsList { get { return m_localVarsList; } }
+ public TemplateInfoContainer PassNameContainer { get { return m_passNameContainer; } }
+ public bool IsMainPass { get { return m_isMainPass; } set { m_isMainPass = value; } }
+ public bool IsInvisible { get { return m_isInvisible; } }
+ public int InvisibleOptions { get { return m_invisibleOptions; } }
+ public int Idx { get { return m_idx; } }
+ public bool AddToList
+ {
+ get
+ {
+ if( m_isInvisible )
+ {
+ return ( m_inputDataList.Count > 0 );
+ }
+
+ return true;
+ }
+ }
+ public bool HasValidFunctionBody
+ {
+ get
+ {
+ if( m_fragmentFunctionData != null || m_vertexFunctionData != null )
+ return true;
+ return false;
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta
new file mode 100644
index 00000000..e36dee49
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePass.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1e6749bf88e2d0f4ab5812f084973f4c
+timeCreated: 1517831575
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs
new file mode 100644
index 00000000..e85a92d3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs
@@ -0,0 +1,167 @@
+using UnityEditor;
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class PassVisibleOptionsItems
+ {
+ public bool Visible;
+ public string Name;
+ public int Idx = -1;
+ }
+
+ [Serializable]
+ public class TemplatePassSelectorHelper
+ {
+ private const string Label = " Available Passes";
+
+ [SerializeField]
+ private bool m_foldout;
+
+ [SerializeField]
+ private PassVisibleOptionsItems[] m_currentPasses;
+
+ [NonSerialized]
+ private Dictionary<string, PassVisibleOptionsItems> m_currentPassesDict;
+
+ [SerializeField]
+ private int m_mainPassId;
+
+ public void CopyFrom( TemplatePassSelectorHelper from )
+ {
+ for( int i = 0; i < from.AvailablePasses.Length; i++ )
+ {
+ SetPassVisible( from.AvailablePasses[ i ].Name, from.AvailablePasses[ i ].Visible );
+ }
+ }
+
+ public void Setup( TemplateSubShader subShader )
+ {
+ if( m_currentPasses == null )
+ {
+ m_currentPassesDict = new Dictionary<string, PassVisibleOptionsItems>();
+ m_currentPasses = new PassVisibleOptionsItems[ subShader.Passes.Count ];
+ for( int i = 0; i < m_currentPasses.Length; i++ )
+ {
+ if( subShader.Passes[ i ].IsMainPass )
+ m_mainPassId = i;
+
+ m_currentPasses[ i ] = new PassVisibleOptionsItems() { Name = subShader.Passes[ i ].PassNameContainer.Data, Visible = true, Idx = i };
+ m_currentPassesDict.Add( m_currentPasses[ i ].Name, m_currentPasses[ i ] );
+ }
+ }
+ }
+
+ public void Clear()
+ {
+ m_currentPasses = null;
+
+ if( m_currentPassesDict != null )
+ m_currentPassesDict.Clear();
+
+ m_currentPassesDict = null;
+ }
+
+ public void Destroy()
+ {
+ m_currentPasses = null;
+
+ if( m_currentPassesDict != null )
+ m_currentPassesDict.Clear();
+
+ m_currentPassesDict = null;
+ }
+
+ public void Draw( TemplateMultiPassMasterNode owner )
+ {
+ if( m_currentPasses.Length < 2 )
+ return;
+
+ NodeUtils.DrawNestedPropertyGroup( ref m_foldout, Label, () =>
+ {
+ for( int i = 0; i < m_currentPasses.Length; i++ )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentPasses[ i ].Visible = owner.EditorGUILayoutToggleLeft( m_currentPasses[ i ].Name, m_currentPasses[ i ].Visible );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ owner.ContainerGraph.GetMultiPassMasterNodes( owner.LODIndex)[ m_currentPasses[ i ].Idx ].IsInvisible = !m_currentPasses[ i ].Visible;
+ }
+
+ }
+ EditorGUILayout.Space();
+ } );
+ }
+
+ public void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ int passAmount = Convert.ToInt32( nodeParams[ index++ ] );
+ for( int i = 0; i < passAmount; i++ )
+ {
+ bool value = Convert.ToBoolean( nodeParams[ index++ ] );
+ if( i < m_currentPasses.Length )
+ {
+ m_currentPasses[ i ].Visible = value;
+ }
+ }
+ }
+
+ public void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPasses.Length );
+ for( int i = 0; i < m_currentPasses.Length; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPasses[ i ].Visible );
+ }
+ }
+
+ public void SetPassVisible( string passName, bool visible )
+ {
+ bool refresh = false;
+ if( m_currentPassesDict == null )
+ {
+ m_currentPassesDict = new Dictionary<string, PassVisibleOptionsItems>();
+ refresh = true;
+ }
+ else if( m_currentPassesDict.Count != m_currentPasses.Length )
+ {
+ refresh = true;
+ }
+
+ if( refresh )
+ {
+ for( int i = 0; i < m_currentPasses.Length; i++ )
+ {
+ m_currentPassesDict.Add( m_currentPasses[ i ].Name, m_currentPasses[ i ] );
+ }
+ }
+
+ if( m_currentPassesDict.ContainsKey( passName ) )
+ {
+ m_currentPassesDict[ passName ].Visible = visible;
+ }
+ }
+
+ public int LastActivePass
+ {
+ get
+ {
+ if( m_currentPasses != null )
+ {
+ for( int i = m_currentPasses.Length - 1; i > -1; i-- )
+ {
+ if( m_currentPasses[ i ].Visible )
+ return i;
+ }
+ }
+ m_currentPasses[ m_mainPassId ].Visible = true;
+ return m_mainPassId;
+ }
+ }
+ public bool IsVisible( int passId ) { return m_currentPasses[ passId ].Visible; }
+ private PassVisibleOptionsItems[] AvailablePasses { get { return m_currentPasses; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta
new file mode 100644
index 00000000..2f45a9d5
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePassSelectorHelper.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1340693b71fe44846bb72eb1035f138d
+timeCreated: 1542731803
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs
new file mode 100644
index 00000000..e9ee8c71
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs
@@ -0,0 +1,157 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEditor;
+using UnityEngine;
+using System.IO;
+using System.Security.AccessControl;
+using System.Security.Principal;
+using System.Text.RegularExpressions;
+using Debug = UnityEngine.Debug;
+
+namespace AmplifyShaderEditor
+{
+ public sealed class TemplatePostProcessor : AssetPostprocessor
+ {
+ public static TemplatesManager DummyManager;
+ public static void Destroy()
+ {
+ if( DummyManager != null )
+ {
+ DummyManager.Destroy();
+ ScriptableObject.DestroyImmediate( DummyManager );
+ DummyManager = null;
+ }
+ }
+
+ static void OnPostprocessAllAssets( string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths )
+ {
+ TemplatesManager templatesManager;
+ bool firstTimeDummyFlag = false;
+ if( UIUtils.CurrentWindow == null )
+ {
+ if( DummyManager == null )
+ {
+ DummyManager = ScriptableObject.CreateInstance<TemplatesManager>();
+ DummyManager.hideFlags = HideFlags.HideAndDontSave;
+ firstTimeDummyFlag = true;
+ }
+ templatesManager = DummyManager;
+ }
+ else
+ {
+ Destroy();
+ templatesManager = UIUtils.CurrentWindow.TemplatesManagerInstance;
+ }
+
+ if( templatesManager == null )
+ {
+ return;
+ }
+
+ if( !templatesManager.Initialized )
+ {
+ templatesManager.Init();
+ }
+
+ bool refreshMenuItems = false;
+ for( int i = 0; i < importedAssets.Length; i++ )
+ {
+ if( TemplateHelperFunctions.CheckIfTemplate( importedAssets[ i ] ) )
+ {
+ string guid = AssetDatabase.AssetPathToGUID( importedAssets[ i ] );
+ TemplateDataParent templateData = templatesManager.GetTemplate( guid );
+ if( templateData != null )
+ {
+ refreshMenuItems = templateData.Reload() || refreshMenuItems || firstTimeDummyFlag;
+ int windowCount = IOUtils.AllOpenedWindows.Count;
+ AmplifyShaderEditorWindow currWindow = UIUtils.CurrentWindow;
+ for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ )
+ {
+ if( IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.CurrentCanvasMode == NodeAvailability.TemplateShader )
+ {
+ if( IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.MultiPassMasterNodes.NodesList[ 0 ].CurrentTemplate == templateData )
+ {
+ UIUtils.CurrentWindow = IOUtils.AllOpenedWindows[ windowIdx ];
+ IOUtils.AllOpenedWindows[ windowIdx ].OutsideGraph.ForceMultiPassMasterNodesRefresh();
+ }
+ }
+ }
+ UIUtils.CurrentWindow = currWindow;
+ }
+ else
+ {
+ refreshMenuItems = true;
+ string name = TemplatesManager.OfficialTemplates.ContainsKey( guid ) ? TemplatesManager.OfficialTemplates[ guid ] : string.Empty;
+ TemplateMultiPass mp = TemplateMultiPass.CreateInstance<TemplateMultiPass>();
+ mp.Init( name, guid, true );
+ templatesManager.AddTemplate( mp );
+ }
+ }
+ }
+
+ if( deletedAssets.Length > 0 )
+ {
+ if( deletedAssets[ 0 ].IndexOf( Constants.InvalidPostProcessDatapath ) < 0 )
+ {
+ for( int i = 0; i < deletedAssets.Length; i++ )
+ {
+ string guid = AssetDatabase.AssetPathToGUID( deletedAssets[ i ] );
+ TemplateDataParent templateData = templatesManager.GetTemplate( guid );
+ if( templateData != null )
+ {
+ // Close any window using that template
+ int windowCount = IOUtils.AllOpenedWindows.Count;
+ for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ )
+ {
+ TemplateMasterNode masterNode = IOUtils.AllOpenedWindows[ windowIdx ].CurrentGraph.CurrentMasterNode as TemplateMasterNode;
+ if( masterNode != null && masterNode.CurrentTemplate.GUID.Equals( templateData.GUID ) )
+ {
+ IOUtils.AllOpenedWindows[ windowIdx ].Close();
+ }
+ }
+
+ templatesManager.RemoveTemplate( templateData );
+ refreshMenuItems = true;
+ }
+ }
+ }
+ }
+
+ //for ( int i = 0; i < movedAssets.Length; i++ )
+ //{
+ // if ( TemplateHelperFunctions.CheckIfTemplate( movedAssets[ i ] ) )
+ // {
+ // refreshMenuItems = true;
+ // break;
+ // }
+ //}
+
+ //for ( int i = 0; i < movedFromAssetPaths.Length; i++ )
+ //{
+ // if ( TemplateHelperFunctions.CheckIfTemplate( movedFromAssetPaths[ i ] ) )
+ // {
+ // refreshMenuItems = true;
+ // break;
+ // }
+ //}
+
+ if( refreshMenuItems )
+ {
+ //UnityEngine.Debug.Log( "Refresh Menu Items" );
+ refreshMenuItems = false;
+ templatesManager.CreateTemplateMenuItems();
+
+ AmplifyShaderEditorWindow currWindow = UIUtils.CurrentWindow;
+
+ int windowCount = IOUtils.AllOpenedWindows.Count;
+ for( int windowIdx = 0; windowIdx < windowCount; windowIdx++ )
+ {
+ UIUtils.CurrentWindow = IOUtils.AllOpenedWindows[ windowIdx ];
+ IOUtils.AllOpenedWindows[ windowIdx ].CurrentGraph.ForceCategoryRefresh();
+ }
+ UIUtils.CurrentWindow = currWindow;
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta
new file mode 100644
index 00000000..3598b89a
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatePostProcessor.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d5f63490d6402e9488add7cbdfdd6872
+timeCreated: 1496739732
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs
new file mode 100644
index 00000000..6f42c6f9
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs
@@ -0,0 +1,121 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplatePassInfo
+ {
+ public string Modules;
+ public string Data;
+ public int GlobalStartIdx = -1;
+ public int LocalStartIdx = -1;
+ }
+
+ [Serializable]
+ public class TemplateSubShaderInfo
+ {
+ public string Data;
+ public string Modules;
+ public int StartIdx = -1;
+ public List<TemplatePassInfo> Passes = new List<TemplatePassInfo>();
+ public void Destroy()
+ {
+ Passes.Clear();
+ Passes = null;
+ }
+ }
+
+ [Serializable]
+ public class TemplateShaderInfo
+ {
+ public string Body;
+ public string Properties;
+ public int PropertyStartIdx = -1;
+ public List<TemplateSubShaderInfo> SubShaders = new List<TemplateSubShaderInfo>();
+ public void Destroy()
+ {
+ int count = SubShaders.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ SubShaders[ i ].Destroy();
+ }
+ SubShaders.Clear();
+ SubShaders = null;
+ }
+ }
+
+ public class TemplateShaderInfoUtil
+ {
+ public static TemplateShaderInfo CreateShaderData( string body )
+ {
+ int nameBegin = body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag );
+ if( nameBegin < 0 )
+ {
+ // Not a template
+ return null;
+ }
+
+ TemplateShaderInfo shaderData = null;
+ //SHADER
+ MatchCollection shaderMatch = Regex.Matches( body, "\\bShader\\b" );
+ if( shaderMatch.Count > 0 )
+ {
+ //SUBSHADER
+ MatchCollection subShaderMatch = Regex.Matches( body, TemplatesManager.TemplateMPSubShaderTag );
+ int subShaderAmount = subShaderMatch.Count;
+ if( subShaderAmount > 0 )
+ {
+ shaderData = new TemplateShaderInfo();
+ shaderData.Body = body;
+ int length = subShaderMatch[ 0 ].Index - shaderMatch[ 0 ].Groups[ 0 ].Index;
+ shaderData.Properties = body.Substring( shaderMatch[ 0 ].Index, length );
+ shaderData.PropertyStartIdx = body.IndexOf( TemplatesManager.TemplatePropertyTag );
+
+ for( int subShaderIdx = 0; subShaderIdx < subShaderAmount; subShaderIdx++ )
+ {
+ TemplateSubShaderInfo subShaderData = new TemplateSubShaderInfo();
+ int subshaderBeginIndex = subShaderMatch[ subShaderIdx ].Index;
+ int subShaderEndIndex = ( subShaderIdx == ( subShaderAmount - 1 ) ) ? body.Length - 1 : subShaderMatch[ subShaderIdx + 1 ].Index;
+ subShaderData.Data = body.Substring( subshaderBeginIndex, subShaderEndIndex - subshaderBeginIndex );
+ subShaderData.StartIdx = subshaderBeginIndex;
+
+ //PASS
+ MatchCollection passMatch = Regex.Matches( subShaderData.Data, TemplatesManager.TemplatePassTagPattern );
+ if( passMatch.Count == 0 )
+ {
+ passMatch = Regex.Matches( subShaderData.Data, TemplatesManager.TemplateMPPassTag );
+ }
+
+ int passCount = passMatch.Count;
+ if( passCount > 0 )
+ {
+ int lastPassIndex = subShaderData.Data.LastIndexOf( TemplatesManager.TemplatePassesEndTag );
+ if( lastPassIndex < 0 )
+ {
+ lastPassIndex = subShaderData.Data.Length - 1;
+ }
+
+ subShaderData.Modules = subShaderData.Data.Substring( 0, passMatch[ 0 ].Index );
+ for( int passIdx = 0; passIdx < passCount; passIdx++ )
+ {
+ int passBeginIndex = passMatch[ passIdx ].Index;
+ int passEndIdx = ( passIdx == ( passCount - 1 ) ) ? lastPassIndex : passMatch[ passIdx + 1 ].Index;
+ TemplatePassInfo passData = new TemplatePassInfo();
+ passData.Data = subShaderData.Data.Substring( passBeginIndex, passEndIdx - passBeginIndex );
+ passData.GlobalStartIdx = subshaderBeginIndex + passBeginIndex;
+ passData.LocalStartIdx = passBeginIndex;
+ subShaderData.Passes.Add( passData );
+ }
+ shaderData.SubShaders.Add( subShaderData );
+ }
+ }
+ }
+ }
+ return shaderData;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta
new file mode 100644
index 00000000..8ae726ee
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 33fdd6a5fbc437a489acf58f5d82885c
+timeCreated: 1516879445
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs
new file mode 100644
index 00000000..e1de14b2
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs
@@ -0,0 +1,107 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public sealed class TemplateShaderModelModule : TemplateModuleParent
+ {
+ private const string ShaderModelStr = "Shader Model";
+ private const string ShaderModelFormatStr = "#pragma target ";
+ private const string ShaderModelEncapsulateFormatStr = "CGINCLUDE\n#pragma target {0}\nENDCG";
+
+ [SerializeField]
+ private int m_shaderModelIdx = 2;
+
+ [SerializeField]
+ private bool m_encapsulateOnCGInlude = false;
+
+ public TemplateShaderModelModule() : base("Shader Model"){ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_shaderModelIdx = owner.EditorGUILayoutPopup( ShaderModelStr, m_shaderModelIdx, TemplateHelperFunctions.AvailableShaderModels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ }
+
+ public void CopyFrom( TemplateShaderModelModule other , bool allData )
+ {
+ if( allData )
+ {
+ m_independentModule = other.IndependentModule;
+ m_encapsulateOnCGInlude = other.EncapsulateOnCGInlude;
+ }
+
+ m_shaderModelIdx = other.CurrentShaderModelIdx;
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validData;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ m_shaderModelIdx = Convert.ToInt32( nodeParams[ index++ ] );
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validData );
+ if( m_validData )
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_shaderModelIdx );
+ }
+
+ public override string GenerateShaderData( bool isSubShader )
+ {
+ if( m_encapsulateOnCGInlude )
+ {
+ return string.Format( ShaderModelEncapsulateFormatStr, TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ] );
+ }
+ else
+ {
+ return ShaderModelFormatStr + TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ];
+ }
+ }
+
+ public void ConfigureFromTemplateData( TemplateShaderModelData data )
+ {
+ bool newValidData = ( data.DataCheck == TemplateDataCheck.Valid );
+
+ if( newValidData && m_validData != newValidData )
+ {
+ m_independentModule = data.IndependentModule;
+
+ if( TemplateHelperFunctions.ShaderModelToArrayIdx.ContainsKey( data.Value ) )
+ {
+ m_shaderModelIdx = TemplateHelperFunctions.ShaderModelToArrayIdx[ data.Value ];
+ }
+ m_encapsulateOnCGInlude = data.Encapsulate;
+ }
+
+ m_validData = newValidData;
+ }
+
+ public int CurrentShaderModelIdx { get { return m_shaderModelIdx; } }
+ public string CurrentShaderModel { get { return TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ]; } }
+ public bool EncapsulateOnCGInlude { get { return m_encapsulateOnCGInlude; } }
+ public int InterpolatorAmount
+ {
+ get
+ {
+ return TemplateHelperFunctions.AvailableInterpolators[ TemplateHelperFunctions.AvailableShaderModels[ m_shaderModelIdx ] ];
+ }
+ }
+
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta
new file mode 100644
index 00000000..9afc9c9f
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderModelModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 33c15b597b8db18499c1b4a76035a552
+timeCreated: 1519899350
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs
new file mode 100644
index 00000000..2b67f816
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs
@@ -0,0 +1,44 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateShaderPropertyData
+ {
+ public string PropertyInspectorName;
+ public string PropertyName;
+ public WirePortDataType PropertyDataType;
+ public PropertyType PropertyType;
+
+ public int Index;
+ public string FullValue;
+ public string ReplacementValueHelper;
+ public string Identation;
+
+ public TemplateShaderPropertyData( int index, string fullValue,string identation, string propertyInspectorName, string propertyName, WirePortDataType propertyDataType , PropertyType propertyType )
+ {
+ Index = index;
+ FullValue = fullValue;
+ Identation = identation;
+ PropertyInspectorName = string.IsNullOrEmpty( propertyInspectorName )?propertyName: propertyInspectorName;
+ PropertyName = propertyName;
+ PropertyDataType = propertyDataType;
+ PropertyType = propertyType;
+ int idx = FullValue.LastIndexOf( "=" );
+ ReplacementValueHelper = ( idx >= 0 ) ? FullValue.Substring( 0, idx + 1 ) +" ": FullValue + " = ";
+ }
+
+ public string CreatePropertyForValue( string value )
+ {
+ return value.Contains( PropertyName ) ? Identation + value : ReplacementValueHelper + value;
+ }
+
+ public override string ToString()
+ {
+ return string.Format( "{0}(\"{1}\", {2})", PropertyName, PropertyInspectorName,UIUtils.WirePortToCgType( PropertyDataType ) );
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta
new file mode 100644
index 00000000..411f0535
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7d16f1d82f69ac945ac524dd877ce7fe
+timeCreated: 1496341538
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs
new file mode 100644
index 00000000..40266c37
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs
@@ -0,0 +1,650 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ public enum ShaderPropertyScope
+ {
+ Shader,
+ SubShader,
+ Pass
+ }
+
+ [Serializable]
+ [NodeAttributes( "Template Parameter", "Constants And Properties", "Select and use one of the pre-existing properties given by the template" )]
+ public sealed class TemplateShaderPropertyNode : TemplateNodeParent
+ {
+ private const string CurrentScopeStr = "Scope";
+ private const string WarningStr = "Preview doesn't work with global variables";
+ private const string PropertyLabelStr = "Parameter";
+ private const string TypeLabelStr = "Type: ";
+ private const string PropertyNameStr = "Property Name: ";
+
+ private int IntPropertyId;
+ private int FloatPropertyId;
+ private int VectorPropertyId;
+ private int Sampler2DPropertyId;
+ private int Sampler3DPropertyId;
+ private int SamplerCubePropertyId;
+
+ [SerializeField]
+ private int m_currentPropertyIdx = -1;
+
+ [SerializeField]
+ private string m_propertyName = string.Empty;
+
+ [SerializeField]
+ private int m_propertyNameId = 0;
+
+ [SerializeField]
+ private string m_typeName = string.Empty;
+
+ [SerializeField]
+ private string m_propertyNameLabel = string.Empty;
+
+ private bool m_fetchPropertyId = false;
+ private bool m_fetchScopeFromProperty = false;
+
+ private List<TemplateShaderPropertyData> m_shaderProperties = null;
+ private string[] m_propertyLabels = null;
+
+ private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper();
+
+ //Multi-Pass only properties
+ [SerializeField]
+ private ShaderPropertyScope m_currentScope = ShaderPropertyScope.Shader;
+
+ protected override void CommonInit( int uniqueId )
+ {
+ base.CommonInit( uniqueId );
+ m_previewShaderGUID = "4feb2016be0ece148b8bf234508f6aa4";
+ }
+
+ void FetchScope()
+ {
+ int shaderScopeCount = m_templateMPData.AvailableShaderProperties.Count;
+ for( int i = 0; i < shaderScopeCount; i++ )
+ {
+ if( m_templateMPData.AvailableShaderProperties[ i ].PropertyName.Equals( m_propertyName ) )
+ {
+ m_currentScope = ShaderPropertyScope.Shader;
+ }
+ }
+
+ int subShaderScopeCount = m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals.Count;
+ for( int i = 0; i < subShaderScopeCount; i++ )
+ {
+ if( m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals[ i ].PropertyName.Equals( m_propertyName ) )
+ {
+ m_currentScope = ShaderPropertyScope.SubShader;
+ }
+ }
+
+ int passScopeCount = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals.Count;
+ for( int i = 0; i < passScopeCount; i++ )
+ {
+ if( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals[ i ].PropertyName.Equals( m_propertyName ) )
+ {
+ m_currentScope = ShaderPropertyScope.Pass;
+ }
+ }
+ }
+
+ void FetchShaderProperties()
+ {
+ if( m_templateMPData == null )
+ m_templateMPData = ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).CurrentTemplate;
+
+ if( m_templateMPData != null )
+ {
+ switch( m_currentScope )
+ {
+ case ShaderPropertyScope.Shader:
+ m_shaderProperties = m_templateMPData.AvailableShaderProperties;
+ break;
+ case ShaderPropertyScope.SubShader:
+ m_shaderProperties = m_templateMPData.SubShaders[ SubShaderIdx ].AvailableShaderGlobals;
+ break;
+ case ShaderPropertyScope.Pass:
+ m_shaderProperties = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].AvailableShaderGlobals;
+ break;
+ }
+ }
+ }
+
+ public override void OnEnable()
+ {
+ base.OnEnable();
+ IntPropertyId = Shader.PropertyToID( "_IntData" );
+ FloatPropertyId = Shader.PropertyToID( "_FloatData" );
+ VectorPropertyId = Shader.PropertyToID( "_VectorData" );
+ Sampler2DPropertyId = Shader.PropertyToID( "_Sampler2DData" );
+ Sampler3DPropertyId = Shader.PropertyToID( "_Sampler3DData" );
+ SamplerCubePropertyId = Shader.PropertyToID( "_SamplerCubeData" );
+ }
+
+ public override void DrawProperties()
+ {
+ base.DrawProperties();
+ if( m_multiPassMode )
+ {
+ DrawMultipassProperties();
+ }
+
+ if( m_currentPropertyIdx > -1 )
+ {
+
+ bool hasProperties = ( m_shaderProperties != null && m_shaderProperties.Count > 0 );
+ if( hasProperties )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentPropertyIdx = EditorGUILayoutPopup( PropertyLabelStr, m_currentPropertyIdx, m_propertyLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ EditorGUILayout.LabelField( m_typeName );
+ if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType != PropertyType.Global )
+ {
+ EditorGUILayout.LabelField( m_propertyNameLabel );
+ }
+ }
+ }
+ }
+
+ void DrawMultipassProperties()
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentScope = (ShaderPropertyScope)EditorGUILayoutEnumPopup( CurrentScopeStr, m_currentScope );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ FetchShaderProperties();
+ FetchPropertyId();
+ }
+
+ bool showSubShader = false;
+ bool showPass = false;
+ switch( m_currentScope )
+ {
+ case ShaderPropertyScope.SubShader:
+ {
+ showSubShader = true;
+ }
+ break;
+ case ShaderPropertyScope.Pass:
+ {
+ showSubShader = true;
+ showPass = true;
+ }
+ break;
+ }
+
+ if( showSubShader )
+ {
+ DrawSubShaderUI();
+ }
+
+ if( showPass )
+ {
+ DrawPassUI();
+ }
+ }
+
+ protected override void OnSubShaderChange()
+ {
+ FetchShaderProperties();
+ FetchPropertyId();
+ }
+
+ protected override void OnPassChange()
+ {
+ FetchShaderProperties();
+ FetchPropertyId();
+ }
+
+ override protected void CheckWarningState()
+ {
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ {
+ ShowTab( NodeMessageType.Error, ErrorMessageStr );
+ }
+ else
+ {
+ if( m_shaderProperties != null &&
+ m_shaderProperties.Count > 0 &&
+ m_shaderProperties.Count > m_currentPropertyIdx &&
+ m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global &&
+ m_showPreview )
+ {
+ ShowTab( NodeMessageType.Info, WarningStr );
+ }
+ else
+ {
+ m_showErrorMessage = false;
+ }
+ }
+ }
+
+ public override void SetPreviewInputs()
+ {
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ return;
+
+ if( m_shaderProperties == null || m_currentPropertyIdx >= m_shaderProperties.Count )
+ return;
+
+ if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global )
+ {
+ m_additionalContent.text = string.Empty;
+ PreviewMaterial.SetInt( IntPropertyId, 0 );
+ return;
+ }
+
+ Material currMat = m_containerGraph.CurrentMaterial;
+ if( currMat != null && currMat.HasProperty( m_propertyNameId ) )
+ {
+ switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType )
+ {
+ case WirePortDataType.INT:
+ {
+ int value = currMat.GetInt( m_propertyNameId );
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value ) ) );
+ PreviewMaterial.SetInt( IntPropertyId, value );
+ }
+ break;
+ case WirePortDataType.FLOAT:
+ {
+ float value = currMat.GetFloat( m_propertyNameId );
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value ) ) );
+ PreviewMaterial.SetFloat( FloatPropertyId, value );
+ }
+ break;
+ case WirePortDataType.FLOAT4:
+ {
+ Vector4 value = currMat.GetVector( m_propertyNameId );
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value.x, value.y, value.z, value.w ) ) );
+ PreviewMaterial.SetVector( VectorPropertyId, value );
+ }
+ break;
+ case WirePortDataType.COLOR:
+ {
+ Color value = currMat.GetColor( m_propertyNameId );
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, GenerateTitle( value.r, value.g, value.b, value.a ) ) );
+ PreviewMaterial.SetColor( VectorPropertyId, value );
+ }
+ break;
+ case WirePortDataType.SAMPLER2D:
+ {
+ Texture value = currMat.GetTexture( m_propertyNameId );
+ if( value )
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) );
+ else
+ SetAdditonalTitleText( string.Empty );
+ PreviewMaterial.SetTexture( Sampler2DPropertyId, value );
+ }
+ break;
+ case WirePortDataType.SAMPLER3D:
+ {
+ Texture value = currMat.GetTexture( m_propertyNameId );
+ if( value )
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) );
+ else
+ SetAdditonalTitleText( string.Empty );
+ PreviewMaterial.SetTexture( Sampler3DPropertyId, value );
+ }
+ break;
+ case WirePortDataType.SAMPLERCUBE:
+ {
+ Texture value = currMat.GetTexture( m_propertyNameId );
+ if( value )
+ SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr, value.name ) );
+ else
+ SetAdditonalTitleText( string.Empty );
+ PreviewMaterial.SetTexture( SamplerCubePropertyId, value );
+ }
+ break;
+ }
+ }
+ else
+ {
+ SetAdditonalTitleText( string.Empty );
+ }
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ {
+ if( !m_showErrorMessage || m_errorMessageTypeIsError == NodeMessageType.Info )
+ {
+ ShowTab( NodeMessageType.Error, ErrorMessageStr );
+ }
+ }
+ else if( m_showErrorMessage )
+ {
+ if( m_errorMessageTypeIsError == NodeMessageType.Error )
+ HideTab();
+ }
+
+ base.Draw( drawInfo );
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ return;
+
+ if( m_shaderProperties == null )
+ {
+ MasterNode masterNode = m_containerGraph.CurrentMasterNode;
+ if( masterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ if( SetTemplate( masterNode ) )
+ {
+ m_fetchPropertyId = true;
+ }
+ }
+ }
+
+ if( m_fetchScopeFromProperty )
+ {
+ m_fetchScopeFromProperty = false;
+ FetchScope();
+ FetchShaderProperties();
+ }
+
+ if( m_fetchPropertyId )
+ {
+ m_fetchPropertyId = false;
+ FetchPropertyId();
+ }
+
+ if( m_currentPropertyIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentPropertyIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentPropertyIdx, m_propertyLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+
+ void FetchPropertyId()
+ {
+ if( m_shaderProperties != null )
+ {
+ m_currentPropertyIdx = 0;
+ m_propertyLabels = new string[ m_shaderProperties.Count ];
+ for( int i = 0; i < m_shaderProperties.Count; i++ )
+ {
+ if( m_shaderProperties[ i ].PropertyName.Equals( m_propertyName ) )
+ {
+ m_currentPropertyIdx = i;
+ }
+ m_propertyLabels[ i ] = m_shaderProperties[ i ].PropertyInspectorName;
+ }
+ UpdateFromId();
+ }
+ else
+ {
+ m_currentPropertyIdx = -1;
+ }
+ }
+
+ void UpdateFromId()
+ {
+
+ if( m_shaderProperties != null )
+ {
+ if( m_shaderProperties.Count == 0 )
+ {
+ for( int i = 0; i < 4; i++ )
+ m_containerGraph.DeleteConnection( false, UniqueId, i, false, true );
+
+ m_headerColor = UIUtils.GetColorFromCategory( "Default" );
+ m_content.text = "None";
+ m_additionalContent.text = string.Empty;
+ m_previewMaterialPassId = 1;
+ PreviewMaterial.SetFloat( FloatPropertyId, 0 );
+ m_showPreview = false;
+ m_drawPreviewExpander = false;
+ m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.FLOAT, false );
+ ConfigurePorts();
+ return;
+ }
+
+ m_drawPreviewExpander = true;
+ bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType );
+ switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType )
+ {
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ m_outputPorts[ 0 ].ChangeProperties( "Tex", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false );
+ m_headerColor = UIUtils.GetColorFromCategory( "Textures" );
+ break;
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false );
+ m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" );
+ break;
+ case WirePortDataType.FLOAT4:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false );
+ m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" );
+ break;
+ case WirePortDataType.COLOR:
+ m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false );
+ m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" );
+ break;
+ default:
+ case WirePortDataType.OBJECT:
+ case WirePortDataType.FLOAT3x3:
+ case WirePortDataType.FLOAT4x4:
+ m_outputPorts[ 0 ].ChangeProperties( "Out", m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType, false );
+ m_headerColor = UIUtils.GetColorFromCategory( "Constants And Properties" );
+ break;
+ }
+
+ if( !areCompatible )
+ {
+ for( int i = 0; i < 4; i++ )
+ m_containerGraph.DeleteConnection( false, UniqueId, i, false, true );
+ }
+
+ ConfigurePorts();
+
+ m_propertyName = m_shaderProperties[ m_currentPropertyIdx ].PropertyName;
+ m_content.text = m_shaderProperties[ m_currentPropertyIdx ].PropertyInspectorName;
+ m_propertyNameId = Shader.PropertyToID( m_propertyName );
+ m_typeName = TypeLabelStr + m_shaderProperties[ m_currentPropertyIdx ].PropertyType.ToString();
+ if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType != PropertyType.Global )
+ {
+ m_propertyNameLabel = PropertyNameStr + m_shaderProperties[ m_currentPropertyIdx ].PropertyName;
+ }
+
+ m_sizeIsDirty = true;
+ Material currMat = m_containerGraph.CurrentMaterial;
+ if( currMat != null )
+ {
+ if( m_shaderProperties[ m_currentPropertyIdx ].PropertyType == PropertyType.Global )
+ {
+ m_previewMaterialPassId = 0;
+ if( !m_showErrorMessage && m_showPreview )
+ {
+ ShowTab( NodeMessageType.Info, WarningStr );
+ }
+ }
+ else
+ {
+ if( m_showErrorMessage && m_errorMessageTypeIsError != NodeMessageType.Error )
+ {
+ HideTab();
+ }
+ switch( m_shaderProperties[ m_currentPropertyIdx ].PropertyDataType )
+ {
+ case WirePortDataType.INT: m_previewMaterialPassId = 0; break;
+ case WirePortDataType.FLOAT: m_previewMaterialPassId = 1; break;
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR: m_previewMaterialPassId = 2; break;
+ case WirePortDataType.SAMPLER2D: m_previewMaterialPassId = 3; break;
+ case WirePortDataType.SAMPLER3D: m_previewMaterialPassId = 4; break;
+ case WirePortDataType.SAMPLERCUBE: m_previewMaterialPassId = 5; break;
+ default: PreviewMaterial.SetPass( 0 ); break;
+ }
+ }
+ }
+
+ CheckWarningState();
+ }
+ }
+
+ string GenerateTitle( params float[] values )
+ {
+ //string finalResult = "( ";
+ string finalResult = string.Empty;
+ if( values.Length == 1 )
+ {
+ finalResult += values[ 0 ].ToString( Mathf.Abs( values[ 0 ] ) > 1000 ? Constants.PropertyBigFloatFormatLabel : Constants.PropertyFloatFormatLabel );
+ }
+ else
+ {
+ for( int i = 0; i < values.Length; i++ )
+ {
+ finalResult += values[ i ].ToString( Mathf.Abs( values[ i ] ) > 1000 ? Constants.PropertyBigVectorFormatLabel : Constants.PropertyVectorFormatLabel );
+ if( i < ( values.Length - 1 ) )
+ finalResult += ",";
+ }
+ }
+ //finalResult += " )";
+ return finalResult;
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template )
+ {
+ UIUtils.ShowMessage( UniqueId, "Template Parameter node is only intended for templates use only" );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+
+ if( m_shaderProperties == null || m_shaderProperties.Count ==0 )
+ {
+ UIUtils.ShowMessage( UniqueId, "Attempting to fetch inexistant parameter on " + m_nodeAttribs.Name +" node");
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+
+ if( m_multiPassMode )
+ {
+ switch( m_currentScope )
+ {
+ case ShaderPropertyScope.SubShader:
+ {
+ if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1}", m_propertyLabels[ m_currentPropertyIdx ], SubShaderIdx ) );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+ }
+ break;
+ case ShaderPropertyScope.Pass:
+ {
+ if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx ||
+ dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx
+ )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_propertyLabels[ m_currentPropertyIdx ], SubShaderIdx, PassIdx ) );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+ }
+ break;
+ }
+ }
+
+ return GetOutputVectorItem( 0, outputId, m_propertyName );
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ m_propertyName = GetCurrentParam( ref nodeParams );
+ m_propertyNameId = Shader.PropertyToID( m_propertyName );
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ m_currentScope = (ShaderPropertyScope)Enum.Parse( typeof( ShaderPropertyScope ), GetCurrentParam( ref nodeParams ) );
+ }
+ else
+ {
+ m_fetchScopeFromProperty = true;
+ }
+ m_fetchPropertyId = true;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_propertyName );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentScope );
+ }
+
+ public override void OnMasterNodeReplaced( MasterNode newMasterNode )
+ {
+ base.OnMasterNodeReplaced( newMasterNode );
+ if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ SetTemplate( newMasterNode );
+ if( m_fetchScopeFromProperty )
+ {
+ m_fetchScopeFromProperty = false;
+ FetchScope();
+ }
+ FetchShaderProperties();
+ FetchPropertyId();
+ //m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true );
+ }
+ }
+
+ bool SetTemplate( MasterNode newMasterNode )
+ {
+ if( m_containerGraph.MultiPassMasterNodes.NodesList.Count > 0 )
+ {
+ m_multiPassMode = true;
+ TemplateMultiPassMasterNode templateMasterNode = ( newMasterNode as TemplateMultiPassMasterNode );
+ if( templateMasterNode != null )
+ {
+ m_templateMPData = templateMasterNode.CurrentTemplate;
+ UpdateSubShaderAmount();
+ FetchShaderProperties();
+ return true;
+ }
+ }
+ else
+ {
+ m_multiPassMode = false;
+ TemplateMasterNode templateMasterNode = ( newMasterNode as TemplateMasterNode );
+ if( templateMasterNode != null )
+ {
+ m_shaderProperties = templateMasterNode.CurrentTemplate.AvailableShaderProperties;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override void RefreshExternalReferences()
+ {
+ base.RefreshExternalReferences();
+ CheckWarningState();
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_propertyLabels = null;
+ m_shaderProperties = null;
+ m_upperLeftWidgetHelper = null;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta
new file mode 100644
index 00000000..825090da
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateShaderPropertyNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1579d32d6529f33418f210a5bd730436
+timeCreated: 1496398185
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs
new file mode 100644
index 00000000..6dc3f834
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs
@@ -0,0 +1,168 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateSubShader
+ {
+ [SerializeField]
+ private int m_idx = -1;
+
+ [SerializeField]
+ private List<TemplatePass> m_passes = new List<TemplatePass>();
+
+ [SerializeField]
+ private TemplateModulesData m_modules;
+
+ [SerializeField]
+ private string m_uniquePrefix;
+
+ [SerializeField]
+ private TemplatePropertyContainer m_templateProperties = new TemplatePropertyContainer();
+
+ [SerializeField]
+ private List<TemplateShaderPropertyData> m_availableShaderGlobals = new List<TemplateShaderPropertyData>();
+
+ [SerializeField]
+ private TemplateInfoContainer m_LODContainer = new TemplateInfoContainer();
+
+ [SerializeField]
+ private int m_passAmount = 0;
+
+ [SerializeField]
+ private int m_mainPass = -1;
+
+ [SerializeField]
+ private bool m_foundMainPassTag = false;
+
+ [SerializeField]
+ TemplateOptionsContainer m_customOptionsContainer = new TemplateOptionsContainer();
+
+ public TemplateSubShader(TemplateMultiPass template, int subShaderIx, TemplateIdManager idManager, string uniquePrefix, TemplateSubShaderInfo subShaderInfo, ref Dictionary<string, TemplateShaderPropertyData> duplicatesHelper )
+ {
+ m_idx = subShaderIx;
+
+ m_uniquePrefix = uniquePrefix;
+
+ FetchLOD( subShaderInfo.StartIdx, subShaderInfo.Modules );
+ if( m_LODContainer.Index > -1 )
+ {
+ idManager.RegisterId( m_LODContainer.Index, uniquePrefix + "Module" + m_LODContainer.Id, m_LODContainer.Id );
+ }
+
+ m_customOptionsContainer = TemplateOptionsToolsHelper.GenerateOptionsContainer( true, subShaderInfo.Data );
+ if( m_customOptionsContainer.Enabled )
+ {
+ idManager.RegisterId( m_customOptionsContainer.Index, uniquePrefix + m_customOptionsContainer.Body, m_customOptionsContainer.Body, true );
+ }
+
+ m_modules = new TemplateModulesData( m_customOptionsContainer, idManager, m_templateProperties, uniquePrefix + "Module", subShaderInfo.StartIdx, subShaderInfo.Modules, true );
+ if( m_modules.SRPType == TemplateSRPType.HD )
+ {
+ m_modules.SRPIsPBR = subShaderInfo.Data.Contains( TemplateHelperFunctions.HDPBRTag );
+ }
+
+ Dictionary<string, TemplateShaderPropertyData> ownDuplicatesDict = new Dictionary<string, TemplateShaderPropertyData>( duplicatesHelper );
+
+ TemplateHelperFunctions.CreateShaderGlobalsList( subShaderInfo.Modules, ref m_availableShaderGlobals, ref ownDuplicatesDict );
+
+ m_passAmount = subShaderInfo.Passes.Count;
+
+ //if( !m_modules.PassTag.IsValid )
+ //{
+ // m_modules.PassTag.StartIdx = subShaderData.Passes[ 0 ].GlobalStartIdx;
+ // m_templateProperties.AddId( subShaderData.Data, m_modules.PassTag.Id, subShaderData.Passes[ 0 ].LocalStartIdx, m_modules.PassTag.SearchIndentation );
+ // m_modules.PassTag.StartIdx -= m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].Indentation.Length;
+ // m_templateProperties.PropertyDict[ m_modules.PassTag.Id ].UseIndentationAtStart = true;
+ // idManager.RegisterId( m_modules.PassTag.StartIdx, m_modules.UniquePrefix + m_modules.PassTag.Id, string.Empty );
+ //}
+
+ int firstVisible = -1;
+ int currAddedPassIdx = 0;
+ for( int passIdx = 0; passIdx < m_passAmount; passIdx++ )
+ {
+ TemplatePass newPass = new TemplatePass( template, this,subShaderIx, passIdx, idManager, uniquePrefix + "Pass" + passIdx, subShaderInfo.Passes[ passIdx ].GlobalStartIdx, subShaderInfo.Passes[ passIdx ], ref ownDuplicatesDict );
+ if( newPass.AddToList )
+ {
+ if( newPass.IsMainPass && m_mainPass < 0 )
+ {
+ m_mainPass = currAddedPassIdx;
+ m_foundMainPassTag = true;
+ }
+ else if(!newPass.IsInvisible && firstVisible < 0 )
+ {
+ firstVisible = currAddedPassIdx;
+ }
+
+ m_passes.Add( newPass );
+ currAddedPassIdx++;
+ }
+ else
+ {
+ newPass.Destroy();
+ newPass = null;
+ }
+
+ }
+
+ if( m_mainPass < 0 )
+ {
+ // If no main pass was set then choose the first visible one
+ m_mainPass = ( firstVisible < 0 ) ? 0 : firstVisible;
+ m_passes[ m_mainPass ].IsMainPass = true;
+ }
+
+ ownDuplicatesDict.Clear();
+ ownDuplicatesDict = null;
+ }
+
+ public void Destroy()
+ {
+ m_LODContainer = null;
+
+ m_customOptionsContainer = null;
+
+ m_templateProperties.Destroy();
+ m_templateProperties = null;
+
+ m_passes.Clear();
+ m_passes = null;
+
+ m_modules.Destroy();
+ m_modules = null;
+
+ m_availableShaderGlobals.Clear();
+ m_availableShaderGlobals = null;
+
+ }
+
+ void FetchLOD( int offsetIdx, string body )
+ {
+ Match match = Regex.Match( body, TemplateHelperFunctions.SubShaderLODPattern );
+ if( match != null && match.Groups.Count > 1 )
+ {
+ m_LODContainer.Id = match.Groups[ 0 ].Value;
+ m_LODContainer.Data = match.Groups[ 1 ].Value;
+ m_LODContainer.Index = offsetIdx + match.Index;
+ }
+ }
+
+ public List<TemplatePass> Passes { get { return m_passes; } }
+ public TemplateModulesData Modules { get { return m_modules; } }
+ public string UniquePrefix { get { return m_uniquePrefix; } }
+ public TemplatePropertyContainer TemplateProperties { get { return m_templateProperties; } }
+ public List<TemplateShaderPropertyData> AvailableShaderGlobals { get { return m_availableShaderGlobals; } }
+ public TemplateInfoContainer LODContainer { get { return m_LODContainer; } }
+ public int PassAmount { get { return m_passAmount; } }
+ public bool FoundMainPass { get { return m_foundMainPassTag; } }
+ public int MainPass { get { return m_mainPass; } }
+ public int Idx { get { return m_idx; } }
+ public TemplateOptionsContainer CustomOptionsContainer { get { return m_customOptionsContainer; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta
new file mode 100644
index 00000000..41a78861
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateSubShader.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f4ff24a5a4c92f745a159f247574c07a
+timeCreated: 1517854017
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs
new file mode 100644
index 00000000..fcf38910
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs
@@ -0,0 +1,440 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateTagsModule : TemplateModuleParent
+ {
+ private const string CustomTagsStr = "Tags";
+ private const string TagNameStr = "Name";
+ private const string TagValueStr = "Value";
+ private const string QueueIndexStr = "Index";
+ private const string QueueLabelStr = "Queue";
+ private const string RenderTypeLabelStr = "Type";
+ private const string CustomRenderTypeLabelStr = "Custom";
+
+ private const float ShaderKeywordButtonLayoutWidth = 15;
+ private UndoParentNode m_currentOwner;
+
+ private double m_tagNameCheckTimestamp = 0;
+ private bool m_tagNameCheckFlag = true;
+ private int m_tagNameCheckItemId = 0;
+ private const double TagNameCheckMaxInterval = 1.5;
+
+ [SerializeField]
+ private List<CustomTagData> m_availableTags = new List<CustomTagData>();
+
+ private Dictionary<string, CustomTagData> m_availableTagsDict = new Dictionary<string, CustomTagData>();
+
+ public TemplateTagsModule() : base( "Tags" ) { }
+
+ public void CopyFrom( TemplateTagsModule other )
+ {
+ m_availableTags.Clear();
+ m_availableTagsDict.Clear();
+
+ int count = other.AvailableTags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ CustomTagData newData = new CustomTagData( other.AvailableTags[ i ] );
+ m_availableTags.Add( newData );
+ m_availableTagsDict.Add( newData.TagName, newData );
+ }
+ }
+
+ public void ConfigureFromTemplateData( TemplateTagsModuleData tagsData )
+ {
+ bool newValidData = tagsData.DataCheck == TemplateDataCheck.Valid;
+ if( newValidData && newValidData != m_validData )
+ {
+ m_availableTags.Clear();
+ m_availableTagsDict.Clear();
+ int count = tagsData.Tags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ CustomTagData tagData = new CustomTagData( tagsData.Tags[ i ].Name, tagsData.Tags[ i ].Value, i );
+ m_availableTags.Add( tagData );
+ m_availableTagsDict.Add( tagsData.Tags[ i ].Name, tagData );
+ }
+ }
+ m_validData = newValidData;
+ }
+
+ public override void ShowUnreadableDataMessage( ParentNode owner )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags;
+ NodeUtils.DrawPropertyGroup( ref foldout, CustomTagsStr, base.ShowUnreadableDataMessage );
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = foldout;
+ }
+
+ public void OnLogicUpdate()
+ {
+ if( m_tagNameCheckFlag && ( EditorApplication.timeSinceStartup - m_tagNameCheckTimestamp ) > TagNameCheckMaxInterval )
+ {
+ m_tagNameCheckFlag = false;
+ if( m_tagNameCheckItemId < m_availableTags.Count )
+ {
+ if( m_availableTags[ m_tagNameCheckItemId ].TagName.Equals( Constants.RenderQueueHelperStr ) )
+ {
+ m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.Queue;
+ }
+ else if( m_availableTags[ m_tagNameCheckItemId ].TagName.Equals( Constants.RenderTypeHelperStr ) )
+ {
+ m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.RenderType;
+ }
+ else
+ {
+ m_availableTags[ m_tagNameCheckItemId ].SpecialTag = TemplateSpecialTags.None;
+ }
+ }
+ }
+ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ m_currentOwner = owner;
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags;
+ if( style )
+ {
+ NodeUtils.DrawPropertyGroup( ref foldout, CustomTagsStr, DrawMainBody, DrawButtons );
+ }
+ else
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref foldout, CustomTagsStr, DrawMainBody, DrawButtons );
+ }
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedCustomTags = foldout;
+ }
+
+ void DrawButtons()
+ {
+ EditorGUILayout.Separator();
+
+ // Add tag
+ if( GUILayout.Button( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ m_availableTags.Add( new CustomTagData() );
+ EditorGUI.FocusTextInControl( null );
+ }
+
+ //Remove tag
+ if( GUILayout.Button( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ if( m_availableTags.Count > 0 )
+ {
+ m_availableTags.RemoveAt( m_availableTags.Count - 1 );
+ EditorGUI.FocusTextInControl( null );
+ }
+ }
+ }
+
+ void DrawMainBody()
+ {
+ EditorGUI.BeginChangeCheck();
+ {
+ EditorGUILayout.Separator();
+ int itemCount = m_availableTags.Count;
+
+ if( itemCount == 0 )
+ {
+ EditorGUILayout.HelpBox( "Your list is Empty!\nUse the plus button to add one.", MessageType.Info );
+ }
+
+ int markedToDelete = -1;
+ float originalLabelWidth = EditorGUIUtility.labelWidth;
+ for( int i = 0; i < itemCount; i++ )
+ {
+ m_availableTags[ i ].TagFoldout = m_currentOwner.EditorGUILayoutFoldout( m_availableTags[ i ].TagFoldout, string.Format( "[{0}] - {1}", i, m_availableTags[ i ].TagName ) );
+ if( m_availableTags[ i ].TagFoldout )
+ {
+ EditorGUI.indentLevel += 1;
+ EditorGUIUtility.labelWidth = 70;
+ //Tag Name
+ EditorGUI.BeginChangeCheck();
+ m_availableTags[ i ].TagName = m_currentOwner.EditorGUILayoutTextField( TagNameStr, m_availableTags[ i ].TagName );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_availableTags[ i ].TagName = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagName );
+ m_tagNameCheckFlag = true;
+ m_tagNameCheckItemId = i;
+ m_tagNameCheckTimestamp = EditorApplication.timeSinceStartup;
+ }
+
+ //Tag Value
+ switch( m_availableTags[ i ].SpecialTag )
+ {
+ case TemplateSpecialTags.RenderType:
+ {
+ m_availableTags[ i ].RenderType = (RenderType)m_currentOwner.EditorGUILayoutEnumPopup( RenderTypeLabelStr, m_availableTags[ i ].RenderType );
+ if( m_availableTags[ i ].RenderType == RenderType.Custom )
+ {
+ m_availableTags[ i ].TagValue = m_currentOwner.EditorGUILayoutTextField( CustomRenderTypeLabelStr, m_availableTags[ i ].TagValue );
+ }
+ }
+ break;
+ case TemplateSpecialTags.Queue:
+ {
+
+ EditorGUI.BeginChangeCheck();
+ m_availableTags[ i ].RenderQueue = (RenderQueue)m_currentOwner.EditorGUILayoutEnumPopup( QueueLabelStr, m_availableTags[ i ].RenderQueue, GUILayout.MinWidth( 150 ) );
+ m_availableTags[ i ].RenderQueueOffset = m_currentOwner.EditorGUILayoutIntField( QueueIndexStr, m_availableTags[ i ].RenderQueueOffset );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_availableTags[ i ].BuildQueueTagValue();
+ }
+
+ }
+ break;
+ case TemplateSpecialTags.None:
+ {
+ EditorGUI.BeginChangeCheck();
+ m_availableTags[ i ].TagValue = m_currentOwner.EditorGUILayoutTextField( TagValueStr, m_availableTags[ i ].TagValue );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_availableTags[ i ].TagValue = UIUtils.RemoveShaderInvalidCharacters( m_availableTags[ i ].TagValue );
+ }
+ }
+ break;
+
+ }
+
+ EditorGUIUtility.labelWidth = originalLabelWidth;
+
+ EditorGUILayout.BeginHorizontal();
+ {
+ GUILayout.Label( " " );
+ // Add new port
+ if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ m_availableTags.Insert( i + 1, new CustomTagData() );
+ EditorGUI.FocusTextInControl( null );
+ }
+
+ //Remove port
+ if( m_currentOwner.GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( ShaderKeywordButtonLayoutWidth ) ) )
+ {
+ markedToDelete = i;
+ }
+ }
+ EditorGUILayout.EndHorizontal();
+
+ EditorGUI.indentLevel -= 1;
+ }
+
+ }
+ if( markedToDelete > -1 )
+ {
+ if( m_availableTags.Count > markedToDelete )
+ {
+ m_availableTags.RemoveAt( markedToDelete );
+ EditorGUI.FocusTextInControl( null );
+ }
+ }
+ EditorGUILayout.Separator();
+ }
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ }
+
+ //Method used by template options
+ // As such. Render Queue will have value and offset separated by ,
+ public void AddSpecialTag( TemplateSpecialTags tag, TemplateActionItem item )
+ {
+ if( tag == TemplateSpecialTags.None )
+ return;
+
+ int count = m_availableTags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_availableTags[ i ].SpecialTag == tag )
+ {
+ switch( tag )
+ {
+ case TemplateSpecialTags.RenderType:
+ {
+ m_availableTags[ i ].RenderType = TemplateHelperFunctions.StringToRenderType[ item.ActionData ];
+ return;
+ }
+ case TemplateSpecialTags.Queue:
+ {
+
+ m_availableTags[ i ].RenderQueue = TemplateHelperFunctions.StringToRenderQueue[ item.ActionData ];
+ m_availableTags[ i ].RenderQueueOffset = item.ActionDataIdx;
+ m_availableTags[ i ].BuildQueueTagValue();
+ return;
+ }
+ }
+ }
+ }
+
+ CustomTagData data = new CustomTagData();
+ switch( tag )
+ {
+ case TemplateSpecialTags.RenderType:
+ {
+ data.SpecialTag = TemplateSpecialTags.RenderType;
+ data.TagName = "RenderType";
+ data.RenderType = TemplateHelperFunctions.StringToRenderType[ item.ActionData ];
+ }
+ break;
+ case TemplateSpecialTags.Queue:
+ {
+ data.SpecialTag = TemplateSpecialTags.Queue;
+ data.TagName = "Queue";
+ data.RenderQueue = TemplateHelperFunctions.StringToRenderQueue[ item.ActionData ];
+ data.RenderQueueOffset = item.ActionDataIdx;
+ data.BuildQueueTagValue();
+ }
+ break;
+ }
+ m_availableTags.Add( data );
+ }
+
+ void AddTagFromRead( string data )
+ {
+ string[] arr = data.Split( IOUtils.VALUE_SEPARATOR );
+ if( arr.Length > 1 )
+ {
+ string name = arr[ 0 ];
+ string value = arr[ 1 ];
+
+ if( !m_availableTagsDict.ContainsKey( name ) )
+ {
+ CustomTagData tagData = new CustomTagData( data, m_availableTags.Count - 1 );
+ m_availableTags.Add( tagData );
+ m_availableTagsDict.Add( name, tagData );
+ }
+ else
+ {
+ if( m_availableTagsDict[ name ].TagId > -1 &&
+ m_availableTagsDict[ name ].TagId < m_availableTags.Count )
+ {
+ if( arr.Length == 4 )
+ {
+ m_availableTags[ m_availableTagsDict[ name ].TagId ].SetTagValue( value, arr[ 3 ] );
+ }
+ else
+ {
+ m_availableTags[ m_availableTagsDict[ name ].TagId ].SetTagValue( value );
+ }
+
+ }
+ else
+ {
+ int count = m_availableTags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_availableTags[ i ].TagName.Equals( name ) )
+ {
+ m_availableTags[ i ].SetTagValue( value );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validData;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ int count = Convert.ToInt32( nodeParams[ index++ ] );
+ for( int i = 0; i < count; i++ )
+ {
+ AddTagFromRead( nodeParams[ index++ ] );
+ }
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validData );
+ if( m_validData )
+ {
+ int tagsCount = m_availableTags.Count;
+ IOUtils.AddFieldValueToString( ref nodeInfo, tagsCount );
+ for( int i = 0; i < tagsCount; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_availableTags[ i ].ToString() );
+ }
+ }
+ }
+
+ public string GenerateTags()
+ {
+ int tagsCount = m_availableTags.Count;
+ if( tagsCount == 0 )
+ return string.Empty;
+
+ string result = "Tags { ";
+
+ for( int i = 0; i < tagsCount; i++ )
+ {
+ if( m_availableTags[ i ].IsValid )
+ {
+ result += m_availableTags[ i ].GenerateTag();
+ if( i < tagsCount - 1 )
+ {
+ result += " ";
+ }
+ }
+ }
+
+ result += " }";
+
+ return result;
+ }
+
+ public override void Destroy()
+ {
+ m_availableTags.Clear();
+ m_availableTags = null;
+ m_currentOwner = null;
+ m_availableTagsDict.Clear();
+ m_availableTagsDict = null;
+ }
+
+ public List<CustomTagData> AvailableTags { get { return m_availableTags; } }
+
+ public bool HasRenderInfo( ref RenderType renderType, ref RenderQueue renderQueue )
+ {
+ if( !m_validData )
+ return false;
+
+ bool foundRenderType = false;
+ bool foundRenderQueue = false;
+ int count = m_availableTags.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_availableTags[ i ].TagName.Equals( Constants.RenderTypeHelperStr ) )
+ {
+ if( TemplateHelperFunctions.StringToRenderType.ContainsKey( m_availableTags[ i ].TagValue ) )
+ {
+ renderType = TemplateHelperFunctions.StringToRenderType[ m_availableTags[ i ].TagValue ];
+ foundRenderType = true;
+ }
+ }
+ else if( m_availableTags[ i ].TagName.Equals( Constants.RenderQueueHelperStr ) )
+ {
+ string value = m_availableTags[ i ].TagValue.Split( '+' )[ 0 ].Split( '-' )[ 0 ];
+ if( TemplateHelperFunctions.StringToRenderQueue.ContainsKey( value ) )
+ {
+ renderQueue = TemplateHelperFunctions.StringToRenderQueue[ value ];
+ foundRenderQueue = true;
+ }
+ }
+ }
+ return foundRenderType && foundRenderQueue;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta
new file mode 100644
index 00000000..b5888f75
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateTagsModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 905b4a4de4a974a489d7a8aac14e4fcb
+timeCreated: 1516719540
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs
new file mode 100644
index 00000000..3b82e046
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs
@@ -0,0 +1,190 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateVertexData
+ {
+ [SerializeField]
+ private TemplateSemantics m_semantics = TemplateSemantics.NONE;
+ [SerializeField]
+ private WirePortDataType m_dataType = WirePortDataType.OBJECT;
+ [SerializeField]
+ private string m_varName = string.Empty;
+ [SerializeField]
+ private TemplateInfoOnSematics m_dataInfo = TemplateInfoOnSematics.NONE;
+ [SerializeField]
+ private string m_dataSwizzle = string.Empty;
+ [SerializeField]
+ private bool m_available = false;
+ [SerializeField]
+ private string m_varNameWithSwizzle = string.Empty;
+ [SerializeField]
+ private bool m_isSingleComponent = true;
+ [SerializeField]
+ private bool m_excludeStructPrefix = false;
+ [SerializeField]
+ private string[] m_components = { "0", "0", "0", "0" };
+ [SerializeField]
+ private bool[] m_componentUsage = { false, false,false,false };
+
+ public TemplateVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName )
+ {
+ m_semantics = semantics;
+ m_dataType = dataType;
+ m_varName = varName;
+ m_varNameWithSwizzle = varName;
+ }
+
+ public TemplateVertexData( TemplateSemantics semantics, WirePortDataType dataType, string varName, string dataSwizzle )
+ {
+ m_semantics = semantics;
+ m_dataType = dataType;
+ m_varName = varName;
+ m_dataSwizzle = dataSwizzle;
+ m_varNameWithSwizzle = varName + dataSwizzle;
+ }
+
+ public TemplateVertexData( TemplateVertexData other )
+ {
+ m_semantics = other.m_semantics;
+ m_dataType = other.m_dataType;
+ m_varName = other.m_varName;
+ m_dataInfo = other.m_dataInfo;
+ m_dataSwizzle = other.m_dataSwizzle;
+ m_available = other.m_available;
+ m_varNameWithSwizzle = other.m_varNameWithSwizzle;
+ m_isSingleComponent = other.IsSingleComponent;
+ m_excludeStructPrefix = other.ExcludeStructPrefix;
+ for( int i = 0; i < 4; i++ )
+ {
+ m_components[ i ] = other.Components[ i ];
+ }
+ }
+
+ public void RegisterComponent( char channelId, string value )
+ {
+ int channelIdInt = -1;
+ switch( channelId )
+ {
+ case 'r':
+ case 'x': channelIdInt = 0; break;
+ case 'g':
+ case 'y': channelIdInt = 1; break;
+ case 'b':
+ case 'z': channelIdInt = 2; break;
+ case 'a':
+ case 'w': channelIdInt = 3; break;
+ }
+
+ if( channelId < 0 )
+ {
+ Debug.LogWarning( "Attempting to create interpolated data from invalid channel " + channelId );
+ return;
+ }
+
+ RegisterComponent( channelIdInt, value );
+ }
+
+ public void RegisterComponent( int channelId, string value )
+ {
+ channelId = Mathf.Clamp( channelId, 0, 3 );
+ m_components[ channelId ] = value;
+ m_componentUsage[ channelId ] = true;
+ m_isSingleComponent = false;
+ }
+
+ public void BuildVar( PrecisionType precisionType = PrecisionType.Float )
+ {
+ if( m_isSingleComponent )
+ return;
+ WirePortDataType dataType = WirePortDataType.FLOAT;
+ if( m_componentUsage[ 3 ] )
+ {
+ dataType = WirePortDataType.FLOAT4;
+ }
+ else if( m_componentUsage[ 2 ] )
+ {
+ dataType = WirePortDataType.FLOAT3;
+ }
+ else if( m_componentUsage[ 1 ] )
+ {
+ dataType = WirePortDataType.FLOAT2;
+ }
+
+ string newVar = UIUtils.PrecisionWirePortToCgType( precisionType, dataType );
+ newVar += "( ";
+ switch( dataType )
+ {
+ default: newVar += "0"; break;
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ {
+ newVar += "{0}."+Components[ 0 ];
+ }
+ break;
+ case WirePortDataType.FLOAT2:
+ {
+ newVar += "{0}." + Components[ 0 ] + ", " +
+ "{0}." + Components[ 1 ];
+ }
+ break;
+ case WirePortDataType.FLOAT3:
+ {
+ newVar += "{0}." + Components[ 0 ] + ", " +
+ "{0}." + Components[ 1 ] + ", " +
+ "{0}." + Components[ 2 ];
+ }
+ break;
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR:
+ {
+ newVar += "{0}." + Components[ 0 ] + ", " +
+ "{0}." + Components[ 1 ] + ", " +
+ "{0}." + Components[ 2 ] + ", " +
+ "{0}." + Components[ 3 ];
+ }
+ break;
+
+ }
+ newVar += " )";
+ m_varName = newVar;
+ m_varNameWithSwizzle = newVar;
+ }
+
+ public bool ExcludeStructPrefix { get { return m_excludeStructPrefix; } set { m_excludeStructPrefix = value; } }
+ public bool IsSingleComponent { get { return m_isSingleComponent; } }
+ public string[] Components { get { return m_components; } }
+ public TemplateSemantics Semantics { get { return m_semantics; } }
+ public WirePortDataType DataType { get { return m_dataType; } }
+ public string VarName { get { return m_varName; } set { m_varName = value; m_varNameWithSwizzle = value + m_dataSwizzle; } }
+ public string DataSwizzle { get { return m_dataSwizzle; } set { m_dataSwizzle = value; m_varNameWithSwizzle = m_varName + value; } }
+ public TemplateInfoOnSematics DataInfo { get { return m_dataInfo; } set { m_dataInfo = value; } }
+ public bool Available { get { return m_available; } set { m_available = value; } }
+ public string VarNameWithSwizzle { get { return m_varNameWithSwizzle; } }
+ public WirePortDataType SwizzleType
+ {
+ get
+ {
+ if ( string.IsNullOrEmpty( m_dataSwizzle ) )
+ return m_dataType;
+
+ WirePortDataType newType = m_dataType;
+ switch ( m_dataSwizzle.Length )
+ {
+ case 2: newType = WirePortDataType.FLOAT;break;
+ case 3: newType = WirePortDataType.FLOAT2; break;
+ case 4: newType = WirePortDataType.FLOAT3; break;
+ case 5: newType = WirePortDataType.FLOAT4; break;
+ }
+
+ return newType;
+ }
+ }
+
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta
new file mode 100644
index 00000000..d4575340
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexData.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d11e7a9026804bd46962c527fe30d933
+timeCreated: 1496053368
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs
new file mode 100644
index 00000000..65645cc3
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs
@@ -0,0 +1,272 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ [NodeAttributes( "Template Vertex Data", "Vertex Data", "Select and use available vertex data from the template" )]
+ public class TemplateVertexDataNode : TemplateNodeParent
+ {
+ private List<TemplateVertexData> m_interpolatorData = null;
+
+ [SerializeField]
+ private int m_currentDataIdx = -1;
+
+ [SerializeField]
+ private string m_dataName = string.Empty;
+ [SerializeField]
+ private string m_inVarName = string.Empty;
+
+ private string[] m_dataLabels = null;
+
+ private bool m_fetchDataId = false;
+ private UpperLeftWidgetHelper m_upperLeftWidgetHelper = new UpperLeftWidgetHelper();
+
+ void FetchDataId()
+ {
+ if( m_interpolatorData != null )
+ {
+ m_currentDataIdx = 0;
+ int count = m_interpolatorData.Count;
+ m_dataLabels = new string[ count ];
+ for( int i = 0; i < count; i++ )
+ {
+ m_dataLabels[ i ] = m_interpolatorData[ i ].VarName;
+ if( m_interpolatorData[ i ].VarName.Equals( m_dataName ) )
+ {
+ m_currentDataIdx = i;
+ }
+ }
+ UpdateFromId();
+ }
+ else
+ {
+ m_currentDataIdx = -1;
+ }
+ }
+
+ void UpdateFromId()
+ {
+ if( m_interpolatorData != null )
+ {
+ if( m_interpolatorData.Count == 0 )
+ {
+ for( int i = 0; i < 4; i++ )
+ m_containerGraph.DeleteConnection( false, UniqueId, i, false, true );
+
+ m_headerColor = UIUtils.GetColorFromCategory( "Default" );
+ m_content.text = "None";
+ m_additionalContent.text = string.Empty;
+ m_outputPorts[ 0 ].ChangeProperties( "None", WirePortDataType.OBJECT, false );
+ ConfigurePorts();
+ return;
+ }
+
+ bool areCompatible = TemplateHelperFunctions.CheckIfCompatibles( m_outputPorts[ 0 ].DataType, m_interpolatorData[ m_currentDataIdx ].DataType );
+ switch( m_interpolatorData[ m_currentDataIdx ].DataType )
+ {
+ default:
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ m_outputPorts[ 0 ].ChangeProperties( Constants.EmptyPortValue, m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT2:
+ m_outputPorts[ 0 ].ChangeProperties( "XY", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT3:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZ", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.FLOAT4:
+ m_outputPorts[ 0 ].ChangeProperties( "XYZW", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ case WirePortDataType.COLOR:
+ m_outputPorts[ 0 ].ChangeProperties( "RGBA", m_interpolatorData[ m_currentDataIdx ].DataType, false );
+ break;
+ }
+
+ ConfigurePorts();
+
+ if( !areCompatible )
+ {
+ m_containerGraph.DeleteConnection( false, UniqueId, 0, false, true );
+ }
+
+ m_dataName = m_interpolatorData[ m_currentDataIdx ].VarName;
+ m_content.text = m_dataName;
+ m_sizeIsDirty = true;
+ CheckWarningState();
+ }
+ }
+
+ public override void DrawProperties()
+ {
+ base.DrawProperties();
+ if( m_multiPassMode )
+ {
+ DrawMultipassProperties();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = EditorGUILayoutPopup( DataLabelStr, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+ protected override void OnSubShaderChange()
+ {
+ FetchInterpolator();
+ FetchDataId();
+ }
+
+ protected override void OnPassChange()
+ {
+ FetchInterpolator();
+ FetchDataId();
+ }
+
+ void DrawMultipassProperties()
+ {
+ DrawSubShaderUI();
+ DrawPassUI();
+ }
+
+ public override void Draw( DrawInfo drawInfo )
+ {
+ base.Draw( drawInfo );
+ if( m_containerGraph.CurrentCanvasMode != NodeAvailability.TemplateShader )
+ return;
+
+ if( m_interpolatorData == null || m_interpolatorData.Count == 0 )
+ {
+ MasterNode masterNode = m_containerGraph.CurrentMasterNode;
+ FetchInterpolator( masterNode );
+ }
+
+ if( m_fetchDataId )
+ {
+ m_fetchDataId = false;
+ FetchDataId();
+ }
+
+ if( m_currentDataIdx > -1 )
+ {
+ EditorGUI.BeginChangeCheck();
+ m_currentDataIdx = m_upperLeftWidgetHelper.DrawWidget( this, m_currentDataIdx, m_dataLabels );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ UpdateFromId();
+ }
+ }
+ }
+
+ public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( dataCollector.MasterNodeCategory != AvailableShaderTypes.Template )
+ {
+ UIUtils.ShowMessage( UniqueId, "Template Vertex Data node is only intended for templates use only" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( dataCollector.IsFragmentCategory )
+ {
+ UIUtils.ShowMessage( UniqueId, "Template Vertex Data node node is only intended for vertex use use only" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( m_multiPassMode )
+ {
+ if( dataCollector.TemplateDataCollectorInstance.MultipassSubshaderIdx != SubShaderIdx ||
+ dataCollector.TemplateDataCollectorInstance.MultipassPassIdx != PassIdx
+ )
+ {
+ UIUtils.ShowMessage( UniqueId, string.Format( "{0} is only intended for subshader {1} and pass {2}", m_dataLabels[ m_currentDataIdx ], SubShaderIdx, PassIdx ) );
+ return m_outputPorts[ outputId ].ErrorValue;
+ }
+ }
+
+ return GetOutputVectorItem( 0, outputId, m_inVarName + m_dataName );
+ }
+
+ public override void ReadFromString( ref string[] nodeParams )
+ {
+ base.ReadFromString( ref nodeParams );
+ m_dataName = GetCurrentParam( ref nodeParams );
+ m_fetchDataId = true;
+ }
+
+ public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ base.WriteToString( ref nodeInfo, ref connectionsInfo );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_dataName );
+ }
+
+ protected override bool ValidatePass( int passIdx )
+ {
+ return ( m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].VertexFunctionData != null &&
+ m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ passIdx ].VertexDataContainer != null );
+ }
+
+ void FetchInterpolator( MasterNode masterNode = null )
+ {
+ FetchMultiPassTemplate( masterNode );
+ if( m_multiPassMode )
+ {
+ if( m_templateMPData != null )
+ {
+ m_inVarName = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].VertexFunctionData.InVarName + ".";
+ m_interpolatorData = m_templateMPData.SubShaders[ SubShaderIdx ].Passes[ PassIdx ].VertexDataContainer.VertexData;
+ m_fetchDataId = true;
+ }
+ }
+ else
+ {
+ if( masterNode == null )
+ masterNode = m_containerGraph.CurrentMasterNode;
+
+ TemplateData currentTemplate = ( masterNode as TemplateMasterNode ).CurrentTemplate;
+ if( currentTemplate != null )
+ {
+ m_inVarName = currentTemplate.VertexFunctionData.InVarName + ".";
+ m_interpolatorData = currentTemplate.VertexDataList;
+ m_fetchDataId = true;
+ }
+ else
+ {
+ m_interpolatorData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+ }
+
+ public override void OnMasterNodeReplaced( MasterNode newMasterNode )
+ {
+ base.OnMasterNodeReplaced( newMasterNode );
+ if( newMasterNode.CurrentMasterNodeCategory == AvailableShaderTypes.Template )
+ {
+ FetchInterpolator( newMasterNode );
+ }
+ else
+ {
+ m_interpolatorData = null;
+ m_currentDataIdx = -1;
+ }
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_dataLabels = null;
+ m_interpolatorData = null;
+ m_upperLeftWidgetHelper = null;
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta
new file mode 100644
index 00000000..e697d689
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplateVertexDataNode.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5eb32f2452052fb43b6b93c9baa8f02f
+timeCreated: 1506610215
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs
new file mode 100644
index 00000000..93af8a36
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs
@@ -0,0 +1,782 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public sealed class TemplatesBlendModule : TemplateModuleParent
+ {
+ private const string AlphaToMaskStr = "Alpha To Coverage";
+ private const string BlendModeStr = " Blend Mode";
+
+ private const string BlendModesRGBStr = "Blend RGB";
+ private const string BlendModesAlphaStr = "Blend Alpha";
+
+ private const string BlendOpsRGBStr = "Blend Op RGB";
+ private const string BlendOpsAlphaStr = "Blend Op Alpha";
+
+ private const string SourceFactorStr = "Src";
+ private const string DstFactorStr = "Dst";
+
+ private const string AlphaToMaskFormat = "AlphaToMask {0}";
+ private const string BlendFactorOff = "Blend Off";
+ private const string SingleBlendFactorStr = "Blend {0} {1}";
+ private const string SeparateBlendFactorStr = "Blend {0} {1} , {2} {3}";
+
+ private const string SingleBlendOpStr = "BlendOp {0}";
+ private const string SeparateBlendOpStr = "BlendOp {0} , {1}";
+ private const string BlendOpOffStr = "BlendOp Off";
+
+
+ private string[] m_commonBlendTypesArr;
+ private List<CommonBlendTypes> m_commonBlendTypes = new List<CommonBlendTypes>
+ {
+ new CommonBlendTypes("<OFF>", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ),
+ new CommonBlendTypes("Custom", AvailableBlendFactor.Zero, AvailableBlendFactor.Zero ) ,
+ new CommonBlendTypes("Alpha Blend", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.OneMinusSrcAlpha ) ,
+ new CommonBlendTypes("Premultiplied", AvailableBlendFactor.One, AvailableBlendFactor.OneMinusSrcAlpha ),
+ new CommonBlendTypes("Additive", AvailableBlendFactor.One, AvailableBlendFactor.One ),
+ new CommonBlendTypes("Soft Additive", AvailableBlendFactor.OneMinusDstColor, AvailableBlendFactor.One ),
+ new CommonBlendTypes("Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.Zero ),
+ new CommonBlendTypes("2x Multiplicative", AvailableBlendFactor.DstColor, AvailableBlendFactor.SrcColor ),
+ new CommonBlendTypes("Particle Additive", AvailableBlendFactor.SrcAlpha, AvailableBlendFactor.One )
+ };
+
+ [SerializeField]
+ private bool m_validBlendMode = false;
+
+ [SerializeField]
+ private bool m_validBlendOp = false;
+
+ [SerializeField]
+ private bool m_blendModeEnabled = false;
+
+ [SerializeField]
+ private bool m_validAlphaToMask = false;
+
+ [SerializeField]
+ private bool m_alphaToMaskValue = false;
+
+ [SerializeField]
+ private bool m_alphaToMaskIndependent = false;
+
+ // Blend Factor
+ // RGB
+ [SerializeField]
+ private int m_currentRGBIndex = 0;
+
+ [SerializeField]
+ private AvailableBlendFactor m_sourceFactorRGB = AvailableBlendFactor.Zero;
+ [SerializeField]
+ private InlineProperty m_sourceFactorRGBInline = new InlineProperty();
+
+ [SerializeField]
+ private AvailableBlendFactor m_destFactorRGB = AvailableBlendFactor.Zero;
+ [SerializeField]
+ private InlineProperty m_destFactorRGBInline = new InlineProperty();
+
+ //Alpha
+ [SerializeField]
+ private int m_currentAlphaIndex = 0;
+
+ [SerializeField]
+ private AvailableBlendFactor m_sourceFactorAlpha = AvailableBlendFactor.Zero;
+ [SerializeField]
+ private InlineProperty m_sourceFactorAlphaInline = new InlineProperty();
+
+ [SerializeField]
+ private AvailableBlendFactor m_destFactorAlpha = AvailableBlendFactor.Zero;
+ [SerializeField]
+ private InlineProperty m_destFactorAlphaInline = new InlineProperty();
+
+ //Blend Ops
+ [SerializeField]
+ private bool m_blendOpEnabled = false;
+
+ [SerializeField]
+ private AvailableBlendOps m_blendOpRGB = AvailableBlendOps.OFF;
+
+ [SerializeField]
+ private InlineProperty m_blendOpRGBInline = new InlineProperty();
+
+ [SerializeField]
+ private AvailableBlendOps m_blendOpAlpha = AvailableBlendOps.OFF;
+
+ [SerializeField]
+ private InlineProperty m_blendOpAlphaInline = new InlineProperty();
+
+ public TemplatesBlendModule() : base( "Blend Mode and Ops" )
+ {
+ m_commonBlendTypesArr = new string[ m_commonBlendTypes.Count ];
+ for( int i = 0; i < m_commonBlendTypesArr.Length; i++ )
+ {
+ m_commonBlendTypesArr[ i ] = m_commonBlendTypes[ i ].Name;
+ }
+ }
+
+ public void CopyFrom( TemplatesBlendModule other, bool allData )
+ {
+ if( allData )
+ {
+ m_independentModule = other.IndependentModule;
+ m_alphaToMaskIndependent = other.AlphaToMaskIndependent;
+ m_validBlendMode = other.ValidBlendMode;
+ m_validBlendOp = other.ValidBlendOp;
+ m_validAlphaToMask = other.ValidAlphaToMask;
+ }
+ m_alphaToMaskValue = other.AlphaToMaskValue;
+ m_blendModeEnabled = other.BlendModeEnabled;
+ m_currentRGBIndex = other.CurrentRGBIndex;
+ m_sourceFactorRGB = other.SourceFactorRGB;
+ m_destFactorRGB = other.DestFactorRGB;
+ m_currentAlphaIndex = other.CurrentAlphaIndex;
+ m_sourceFactorAlpha = other.SourceFactorAlpha;
+ m_destFactorAlpha = other.DestFactorAlpha;
+ m_blendOpEnabled = other.BlendOpEnabled;
+ m_blendOpRGB = other.BlendOpRGB;
+ m_blendOpAlpha = other.BlendOpAlpha;
+ m_sourceFactorRGBInline = other.SourceFactorRGBInline;
+ m_destFactorRGBInline = other.DestFactorRGBInline;
+ m_sourceFactorAlphaInline = other.SourceFactorAlphaInline;
+ m_destFactorAlphaInline = other.DestFactorAlphaInline;
+ m_blendOpRGBInline = other.BlendOpRGBInline;
+ m_blendOpAlphaInline = other.BlendOpAlphaInline;
+ }
+
+ public void ConfigureFromTemplateData( TemplateBlendData blendData )
+ {
+ if( blendData.ValidAlphaToMask )
+ {
+ if( m_validAlphaToMask != blendData.ValidAlphaToMask )
+ {
+ m_alphaToMaskValue = blendData.AlphaToMaskValue;
+ m_validAlphaToMask = blendData.ValidAlphaToMask;
+ m_alphaToMaskIndependent = blendData.IndependentAlphaToMask;
+ }
+ }
+
+ if( blendData.ValidBlendMode )
+ {
+ if( m_validBlendMode != blendData.ValidBlendMode )
+ {
+ m_blendModeEnabled = true;
+ m_independentModule = blendData.IndependentModule;
+ if( string.IsNullOrEmpty( blendData.SourceFactorRGBInline ) )
+ {
+ m_sourceFactorRGB = blendData.SourceFactorRGB;
+ m_sourceFactorRGBInline.ResetProperty();
+ }
+ else
+ {
+ m_sourceFactorRGBInline.SetInlineByName( blendData.SourceFactorRGBInline );
+ }
+
+ if( string.IsNullOrEmpty( blendData.DestFactorRGBInline ) )
+ {
+ m_destFactorRGB = blendData.DestFactorRGB;
+ m_destFactorRGBInline.ResetProperty();
+ }
+ else
+ {
+ m_destFactorRGBInline.SetInlineByName( blendData.DestFactorRGBInline );
+ }
+
+ if( string.IsNullOrEmpty( blendData.SourceFactorAlphaInline ) )
+ {
+ m_sourceFactorAlpha = blendData.SourceFactorAlpha;
+ m_sourceFactorAlphaInline.ResetProperty();
+ }
+ else
+ {
+ m_sourceFactorAlphaInline.SetInlineByName( blendData.SourceFactorAlphaInline );
+ }
+ if( string.IsNullOrEmpty( blendData.DestFactorAlphaInline ) )
+ {
+ m_destFactorAlpha = blendData.DestFactorAlpha;
+ m_destFactorAlphaInline.ResetProperty();
+ }
+ else
+ {
+ m_destFactorAlphaInline.SetInlineByName( blendData.DestFactorAlphaInline );
+ }
+
+ if( blendData.SeparateBlendFactors )
+ {
+ if( blendData.BlendModeOff )
+ {
+ m_currentRGBIndex = 0;
+ }
+ else
+ {
+ CheckRGBIndex();
+ }
+ CheckAlphaIndex();
+ }
+ else
+ {
+ if( blendData.BlendModeOff )
+ {
+ m_currentRGBIndex = 0;
+ }
+ else
+ {
+ CheckRGBIndex();
+ }
+ m_currentAlphaIndex = 0;
+ }
+ }
+ }
+ else
+ {
+ m_blendModeEnabled = false;
+ }
+
+ if( blendData.ValidBlendOp )
+ {
+ if( m_validBlendOp != blendData.ValidBlendOp )
+ {
+ m_blendOpEnabled = true;
+ if( string.IsNullOrEmpty( blendData.BlendOpRGBInline ) )
+ {
+ m_blendOpRGB = blendData.BlendOpRGB;
+ m_blendOpRGBInline.ResetProperty();
+ }
+ else
+ {
+ m_blendOpRGBInline.SetInlineByName( blendData.BlendOpRGBInline );
+ }
+
+ if( string.IsNullOrEmpty( blendData.BlendOpAlphaInline ) )
+ {
+ m_blendOpAlpha = blendData.BlendOpAlpha;
+ m_blendOpAlphaInline.ResetProperty();
+ }
+ else
+ {
+ m_blendOpAlphaInline.SetInlineByName( blendData.BlendOpAlphaInline );
+ }
+ }
+ }
+ else
+ {
+ m_blendOpEnabled = false;
+ }
+
+ m_validBlendMode = blendData.ValidBlendMode;
+ m_validBlendOp = blendData.ValidBlendOp;
+ m_validData = m_validBlendMode || m_validBlendOp;
+ }
+
+ public override void ShowUnreadableDataMessage( ParentNode owner )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule;
+ NodeUtils.DrawPropertyGroup( ref foldout, BlendModeStr, base.ShowUnreadableDataMessage );
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule = foldout;
+ }
+
+ public override void Draw( UndoParentNode owner, bool style = true )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule;
+ if( style )
+ {
+ NodeUtils.DrawPropertyGroup( ref foldout, BlendModeStr, () =>
+ {
+ DrawBlock( owner, style );
+ } );
+ }
+ else
+ {
+ NodeUtils.DrawNestedPropertyGroup( ref foldout, BlendModeStr, () =>
+ {
+ DrawBlock( owner, style );
+ } );
+ }
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedBlendModeModule = foldout;
+ }
+
+ void DrawBlock( UndoParentNode owner, bool style )
+ {
+ EditorGUI.BeginChangeCheck();
+ {
+ if( m_blendModeEnabled )
+ {
+ // RGB
+ EditorGUI.BeginChangeCheck();
+ m_currentRGBIndex = owner.EditorGUILayoutPopup( BlendModesRGBStr, m_currentRGBIndex, m_commonBlendTypesArr );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ if( m_currentRGBIndex > 1 )
+ {
+ m_sourceFactorRGB = m_commonBlendTypes[ m_currentRGBIndex ].SourceFactor;
+ m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB;
+ m_sourceFactorRGBInline.SetInlineNodeValue();
+
+ m_destFactorRGB = m_commonBlendTypes[ m_currentRGBIndex ].DestFactor;
+ m_destFactorRGBInline.IntValue = (int)m_destFactorRGB;
+ m_destFactorRGBInline.SetInlineNodeValue();
+ }
+ }
+ EditorGUI.BeginDisabledGroup( m_currentRGBIndex == 0 );
+
+ EditorGUI.BeginChangeCheck();
+ float cached = EditorGUIUtility.labelWidth;
+ if( style )
+ {
+ EditorGUIUtility.labelWidth = 40;
+ }
+ else
+ {
+ EditorGUIUtility.labelWidth = 25;
+ }
+
+ EditorGUILayout.BeginHorizontal();
+ //m_sourceFactorRGB = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorRGB );
+ m_sourceFactorRGBInline.CustomDrawer( ref owner, ( x ) => { m_sourceFactorRGB = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorRGB ); }, SourceFactorStr );
+ if( style )
+ {
+ EditorGUI.indentLevel--;
+ EditorGUIUtility.labelWidth = 25;
+ }
+ //m_destFactorRGB = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorRGB );
+ m_destFactorRGBInline.CustomDrawer( ref owner, ( x ) => { m_destFactorRGB = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorRGB ); }, DstFactorStr );
+ if( style )
+ EditorGUI.indentLevel++;
+
+ EditorGUILayout.EndHorizontal();
+
+ EditorGUIUtility.labelWidth = cached;
+ if( EditorGUI.EndChangeCheck() )
+ {
+ CheckRGBIndex();
+ }
+
+ EditorGUI.EndDisabledGroup();
+ // Alpha
+ EditorGUILayout.Separator();
+
+ EditorGUI.BeginChangeCheck();
+ m_currentAlphaIndex = owner.EditorGUILayoutPopup( BlendModesAlphaStr, m_currentAlphaIndex, m_commonBlendTypesArr );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ if( m_currentAlphaIndex > 0 )
+ {
+ m_sourceFactorAlpha = m_commonBlendTypes[ m_currentAlphaIndex ].SourceFactor;
+ m_sourceFactorAlphaInline.IntValue = (int)m_sourceFactorAlpha;
+ m_sourceFactorAlphaInline.SetInlineNodeValue();
+
+ m_destFactorAlpha = m_commonBlendTypes[ m_currentAlphaIndex ].DestFactor;
+ m_destFactorAlphaInline.IntValue = (int)m_destFactorAlpha;
+ m_destFactorAlphaInline.SetInlineNodeValue();
+ }
+ }
+ EditorGUI.BeginDisabledGroup( m_currentAlphaIndex == 0 );
+
+ EditorGUI.BeginChangeCheck();
+ cached = EditorGUIUtility.labelWidth;
+ if( style )
+ {
+ EditorGUIUtility.labelWidth = 40;
+ }
+ else
+ {
+ EditorGUIUtility.labelWidth = 25;
+ }
+ EditorGUILayout.BeginHorizontal();
+ //m_sourceFactorAlpha = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorAlpha );
+ m_sourceFactorAlphaInline.CustomDrawer( ref owner, ( x ) => { m_sourceFactorAlpha = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( SourceFactorStr, m_sourceFactorAlpha ); }, SourceFactorStr );
+ if( style )
+ {
+ EditorGUI.indentLevel--;
+ EditorGUIUtility.labelWidth = 25;
+ }
+ //m_destFactorAlpha = (AvailableBlendFactor)owner.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorAlpha );
+ m_destFactorAlphaInline.CustomDrawer( ref owner, ( x ) => { m_destFactorAlpha = (AvailableBlendFactor)x.EditorGUILayoutEnumPopup( DstFactorStr, m_destFactorAlpha ); }, DstFactorStr );
+ if( style )
+ EditorGUI.indentLevel++;
+ EditorGUILayout.EndHorizontal();
+ EditorGUIUtility.labelWidth = cached;
+
+ if( EditorGUI.EndChangeCheck() )
+ {
+ CheckAlphaIndex();
+ }
+
+ EditorGUI.EndDisabledGroup();
+ EditorGUILayout.Separator();
+ }
+
+ if( m_blendOpEnabled )
+ {
+ // Both these tests should be removed on a later stage
+ // ASE v154dev004 changed AvailableBlendOps.OFF value from -1 to 0
+ // If importing the new package into an already opened ASE window makes
+ // hotcode to preserve the -1 value on these variables
+ if( (int)m_blendOpRGB == -1 )
+ m_blendOpRGB = AvailableBlendOps.OFF;
+
+ if( (int)m_blendOpAlpha == -1 )
+ m_blendOpAlpha = AvailableBlendOps.OFF;
+
+ //m_blendOpRGB = (AvailableBlendOps)owner.EditorGUILayoutEnumPopup( BlendOpsRGBStr, m_blendOpRGB );
+ m_blendOpRGBInline.CustomDrawer( ref owner, ( x ) => { m_blendOpRGB = (AvailableBlendOps)x.EditorGUILayoutPopup( BlendOpsRGBStr, (int)m_blendOpRGB, BlendOpsHelper.BlendOpsLabels ); }, BlendOpsRGBStr );
+ EditorGUILayout.Separator();
+ //m_blendOpAlpha = (AvailableBlendOps)owner.EditorGUILayoutEnumPopup( BlendOpsAlphaStr, m_blendOpAlpha );
+ m_blendOpAlphaInline.CustomDrawer( ref owner, ( x ) => { m_blendOpAlpha = (AvailableBlendOps)x.EditorGUILayoutPopup( BlendOpsAlphaStr, (int)m_blendOpAlpha, BlendOpsHelper.BlendOpsLabels ); }, BlendOpsAlphaStr );
+ }
+
+ if( m_validAlphaToMask )
+ {
+ EditorGUILayout.Space();
+ m_alphaToMaskValue = owner.EditorGUILayoutToggle( AlphaToMaskStr, m_alphaToMaskValue );
+ }
+ }
+
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ }
+
+ void CheckRGBIndex()
+ {
+ int count = m_commonBlendTypes.Count;
+ m_currentRGBIndex = 1;
+ for( int i = 1; i < count; i++ )
+ {
+ if( m_commonBlendTypes[ i ].SourceFactor == m_sourceFactorRGB && m_commonBlendTypes[ i ].DestFactor == m_destFactorRGB )
+ {
+ m_currentRGBIndex = i;
+ return;
+ }
+ }
+
+ }
+
+ void CheckAlphaIndex()
+ {
+ int count = m_commonBlendTypes.Count;
+ m_currentAlphaIndex = 1;
+ for( int i = 1; i < count; i++ )
+ {
+ if( m_commonBlendTypes[ i ].SourceFactor == m_sourceFactorAlpha && m_commonBlendTypes[ i ].DestFactor == m_destFactorAlpha )
+ {
+ m_currentAlphaIndex = i;
+ if( m_currentAlphaIndex > 0 && m_currentRGBIndex == 0 )
+ m_currentRGBIndex = 1;
+ return;
+ }
+ }
+
+ if( m_currentAlphaIndex > 0 && m_currentRGBIndex == 0 )
+ m_currentRGBIndex = 1;
+ }
+
+ public void ReadAlphaToMaskFromString( ref uint index, ref string[] nodeParams )
+ {
+ if( UIUtils.CurrentShaderVersion() > 16102 )
+ {
+ m_validAlphaToMask = Convert.ToBoolean( nodeParams[ index++ ] );
+ if( m_validAlphaToMask )
+ {
+ m_alphaToMaskValue = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+ }
+ }
+
+ public void ReadBlendModeFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validBlendMode;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_currentRGBIndex = Convert.ToInt32( nodeParams[ index++ ] );
+ m_sourceFactorRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] );
+ m_destFactorRGB = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] );
+
+ m_currentAlphaIndex = Convert.ToInt32( nodeParams[ index++ ] );
+ m_sourceFactorAlpha = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] );
+ m_destFactorAlpha = (AvailableBlendFactor)Enum.Parse( typeof( AvailableBlendFactor ), nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_currentRGBIndex = Convert.ToInt32( nodeParams[ index++ ] );
+ m_sourceFactorRGBInline.ReadFromString( ref index, ref nodeParams );
+ m_sourceFactorRGB = (AvailableBlendFactor)m_sourceFactorRGBInline.IntValue;
+ m_destFactorRGBInline.ReadFromString( ref index, ref nodeParams );
+ m_destFactorRGB = (AvailableBlendFactor)m_destFactorRGBInline.IntValue;
+
+ m_currentAlphaIndex = Convert.ToInt32( nodeParams[ index++ ] );
+ m_sourceFactorAlphaInline.ReadFromString( ref index, ref nodeParams );
+ m_sourceFactorAlpha = (AvailableBlendFactor)m_sourceFactorAlphaInline.IntValue;
+ m_destFactorAlphaInline.ReadFromString( ref index, ref nodeParams );
+ m_destFactorAlpha = (AvailableBlendFactor)m_destFactorAlphaInline.IntValue;
+ }
+ }
+ }
+
+ public void ReadBlendOpFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validBlendOp;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_blendOpRGB = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] );
+ m_blendOpAlpha = (AvailableBlendOps)Enum.Parse( typeof( AvailableBlendOps ), nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_blendOpRGBInline.ReadFromString( ref index, ref nodeParams );
+ m_blendOpAlphaInline.ReadFromString( ref index, ref nodeParams );
+
+ if( UIUtils.CurrentShaderVersion() < 15404 )
+ {
+ // Now BlendOps enum starts at 0 and not -1
+ m_blendOpRGBInline.FloatValue += 1;
+ m_blendOpAlphaInline.FloatValue += 1;
+ }
+
+ m_blendOpRGB = (AvailableBlendOps)m_blendOpRGBInline.IntValue;
+ m_blendOpAlpha = (AvailableBlendOps)m_blendOpAlphaInline.IntValue;
+ }
+ //m_blendOpEnabled = ( m_blendOpRGB != AvailableBlendOps.OFF );
+ }
+ }
+ public void WriteAlphaToMaskToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validAlphaToMask );
+ if( m_validAlphaToMask )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_alphaToMaskValue );
+ }
+ }
+
+ public void WriteBlendModeToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validBlendMode );
+ if( m_validBlendMode )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentRGBIndex );
+ if( !m_sourceFactorRGBInline.IsValid ) m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB;
+ m_sourceFactorRGBInline.WriteToString( ref nodeInfo );
+
+ if( !m_destFactorRGBInline.IsValid ) m_destFactorRGBInline.IntValue = (int)m_destFactorRGB;
+ m_destFactorRGBInline.WriteToString( ref nodeInfo );
+
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentAlphaIndex );
+ if( !m_sourceFactorAlphaInline.IsValid ) m_sourceFactorAlphaInline.IntValue = (int)m_sourceFactorAlpha;
+ m_sourceFactorAlphaInline.WriteToString( ref nodeInfo );
+
+ if( !m_destFactorAlphaInline.IsValid ) m_destFactorAlphaInline.IntValue = (int)m_destFactorAlpha;
+ m_destFactorAlphaInline.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public void WriteBlendOpToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validBlendOp );
+ if( m_validBlendOp )
+ {
+ if( !m_blendOpRGBInline.IsValid ) m_blendOpRGBInline.IntValue = (int)m_blendOpRGB;
+ m_blendOpRGBInline.WriteToString( ref nodeInfo );
+
+ if( !m_blendOpAlphaInline.IsValid ) m_blendOpAlphaInline.IntValue = (int)m_blendOpAlpha;
+ m_blendOpAlphaInline.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ ReadBlendModeFromString( ref index, ref nodeParams );
+ ReadBlendOpFromString( ref index, ref nodeParams );
+ ReadAlphaToMaskFromString( ref index, ref nodeParams );
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ WriteBlendModeToString( ref nodeInfo );
+ WriteBlendOpToString( ref nodeInfo );
+ WriteAlphaToMaskToString( ref nodeInfo );
+ }
+
+ public override void Destroy()
+ {
+ base.Destroy();
+ m_sourceFactorRGBInline = null;
+ m_destFactorRGBInline = null;
+ m_sourceFactorAlphaInline = null;
+ m_destFactorAlphaInline = null;
+ m_blendOpRGBInline = null;
+ m_blendOpAlphaInline = null;
+ }
+
+ public string CurrentAlphaToMask
+ {
+ get
+ {
+ return string.Format( AlphaToMaskFormat, m_alphaToMaskValue ? "On" : "Off" );
+ }
+ }
+ public string CurrentBlendFactorSingle
+ {
+ get
+ {
+ return ( m_currentRGBIndex > 0 ) ? string.Format( SingleBlendFactorStr, m_sourceFactorRGBInline.GetValueOrProperty( m_sourceFactorRGB.ToString() ), m_destFactorRGBInline.GetValueOrProperty( m_destFactorRGB.ToString() ) ) : BlendFactorOff;
+ }
+ }
+
+ public string CurrentBlendFactorSeparate
+ {
+ get
+ {
+ return string.Format( SeparateBlendFactorStr,
+ m_sourceFactorRGBInline.GetValueOrProperty( ( m_currentRGBIndex > 0 ? m_sourceFactorRGB.ToString() : AvailableBlendFactor.One.ToString() ) ),
+ m_destFactorRGBInline.GetValueOrProperty( m_currentRGBIndex > 0 ? m_destFactorRGB.ToString() : AvailableBlendFactor.Zero.ToString() ),
+ m_sourceFactorAlphaInline.GetValueOrProperty( m_sourceFactorAlpha.ToString() ),
+ m_destFactorAlphaInline.GetValueOrProperty( m_destFactorAlpha.ToString() ) );
+ }
+ }
+
+ public string CurrentBlendFactor
+ {
+ get
+ {
+ return ( ( m_currentAlphaIndex > 0 ) ? CurrentBlendFactorSeparate : CurrentBlendFactorSingle );
+ }
+ }
+
+
+ public string CurrentBlendOpSingle
+ {
+ get
+ {
+ return ( m_blendOpRGB != AvailableBlendOps.OFF || m_blendOpRGBInline.IsValid ) ? string.Format( SingleBlendOpStr, m_blendOpRGBInline.GetValueOrProperty( m_blendOpRGB.ToString() ) ) : string.Empty;
+ }
+ }
+
+ public string CurrentBlendOpSeparate
+ {
+ get
+ {
+ return string.Format( SeparateBlendOpStr, m_blendOpRGBInline.GetValueOrProperty( ( m_currentRGBIndex > 0 && m_blendOpRGB != AvailableBlendOps.OFF ) ? m_blendOpRGB.ToString() : AvailableBlendOps.Add.ToString() ), m_blendOpAlphaInline.GetValueOrProperty( m_blendOpAlpha.ToString() ) );
+ }
+ }
+
+ public string CurrentBlendOp { get { return ( ( m_blendOpAlpha != AvailableBlendOps.OFF || m_blendOpAlphaInline.IsValid ) ? CurrentBlendOpSeparate : CurrentBlendOpSingle ); } }
+ public bool Active { get { return m_blendModeEnabled && ( m_currentRGBIndex > 0 || m_currentAlphaIndex > 0 ); } }
+ public bool BlendOpActive
+ {
+ get
+ {
+ return m_blendOpEnabled &&
+ (
+ m_blendOpRGBInline.Active ||
+ m_blendOpAlphaInline.Active ||
+ ( !m_blendOpRGBInline.Active && m_blendOpRGB != AvailableBlendOps.OFF ) ||
+ ( !m_blendOpAlphaInline.Active && m_blendOpAlpha != AvailableBlendOps.OFF ) );
+ }
+ }
+
+ public bool ValidBlendMode { get { return m_validBlendMode; } }
+ public bool ValidBlendOp { get { return m_validBlendOp; } }
+ public int CurrentRGBIndex { get { return m_currentRGBIndex; } }
+
+ public AvailableBlendFactor SourceFactorRGB
+ {
+ get { return m_sourceFactorRGB; }
+ set
+ {
+ m_sourceFactorRGB = value;
+ m_sourceFactorRGBInline.IntValue = (int)m_sourceFactorRGB;
+ m_sourceFactorRGBInline.Active = false;
+ }
+
+ }
+ public AvailableBlendFactor DestFactorRGB
+ {
+ get { return m_destFactorRGB; }
+ set
+ {
+ m_destFactorRGB = value;
+ m_destFactorRGBInline.IntValue = (int)value;
+ }
+ }
+
+ public int CurrentAlphaIndex { get { return m_currentAlphaIndex; } set { m_currentAlphaIndex = value; } }
+
+ public AvailableBlendFactor SourceFactorAlpha
+ {
+ get { return m_sourceFactorAlpha; }
+ set
+ {
+ m_sourceFactorAlpha = value;
+ m_sourceFactorAlphaInline.IntValue = (int)value;
+ m_sourceFactorAlphaInline.Active = false;
+ }
+ }
+
+ public AvailableBlendFactor DestFactorAlpha
+ {
+ get { return m_destFactorAlpha; }
+ set
+ {
+ m_destFactorAlpha = value;
+ m_destFactorAlphaInline.IntValue = (int)value;
+ m_destFactorAlphaInline.Active = false;
+
+ }
+ }
+
+ public bool BlendModeEnabled { get { return m_blendModeEnabled; } }
+ public bool BlendOpEnabled { get { return m_blendOpEnabled; } }
+ public AvailableBlendOps BlendOpRGB
+ {
+ get { return m_blendOpRGB; }
+ set
+ {
+ m_blendOpRGB = value;
+ m_blendOpRGBInline.IntValue = (int)value;
+ m_blendOpRGBInline.Active = false;
+ }
+ }
+
+ public AvailableBlendOps BlendOpAlpha
+ {
+ get { return m_blendOpAlpha; }
+ set
+ {
+ m_blendOpAlpha = value;
+ m_blendOpAlphaInline.IntValue = (int)value;
+ m_blendOpAlphaInline.Active = false;
+ }
+ }
+
+ public InlineProperty SourceFactorRGBInline { get { return m_sourceFactorRGBInline; } }
+ public InlineProperty DestFactorRGBInline { get { return m_destFactorRGBInline; } }
+ public InlineProperty SourceFactorAlphaInline { get { return m_sourceFactorAlphaInline; } }
+ public InlineProperty DestFactorAlphaInline { get { return m_destFactorAlphaInline; } }
+ public InlineProperty BlendOpRGBInline { get { return m_blendOpRGBInline; } }
+ public InlineProperty BlendOpAlphaInline { get { return m_blendOpAlphaInline; } }
+ public bool IsAdditiveRGB { get { return m_validBlendMode && m_blendModeEnabled && ( m_currentRGBIndex > 0 ) && ( m_sourceFactorRGB == AvailableBlendFactor.One ) && ( m_destFactorRGB == AvailableBlendFactor.One ); } }
+ public bool IsAlphaBlendRGB { get { return m_validBlendMode && m_blendModeEnabled && ( m_currentRGBIndex > 0 ) && ( m_sourceFactorRGB == AvailableBlendFactor.SrcAlpha ) && ( m_destFactorRGB == AvailableBlendFactor.OneMinusSrcAlpha ); } }
+ public bool ValidAlphaToMask { get { return m_validAlphaToMask; } }
+ public bool AlphaToMaskValue { get { return m_alphaToMaskValue; } }
+ public bool AlphaToMaskIndependent { get { return m_alphaToMaskIndependent; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta
new file mode 100644
index 00000000..b4eeb76e
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesBlendModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7c88941c5badfb7428059cc3ff0c0df9
+timeCreated: 1510933946
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs
new file mode 100644
index 00000000..456cc4df
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs
@@ -0,0 +1,904 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using UnityEditor;
+using System.Collections.Generic;
+using UnityEngine;
+using System.Text.RegularExpressions;
+
+namespace AmplifyShaderEditor
+{
+ [Serializable]
+ public class TemplateInputData
+ {
+ public string PortName;
+ public WirePortDataType DataType;
+ public MasterNodePortCategory PortCategory;
+ public int PortUniqueId;
+ public int OrderId;
+ public int TagGlobalStartIdx;
+ public int TagLocalStartIdx;
+ public string TagId;
+ public string DefaultValue;
+ public string LinkId;
+
+ public TemplateInputData( int tagLocalStartIdx, int tagGlobalStartIdx, string tagId, string portName, string defaultValue, WirePortDataType dataType, MasterNodePortCategory portCategory, int portUniqueId, int orderId, string linkId )
+ {
+ DefaultValue = defaultValue;
+ PortName = portName;
+ DataType = dataType;
+ PortCategory = portCategory;
+ PortUniqueId = portUniqueId;
+ OrderId = orderId;
+ TagId = tagId;
+ TagGlobalStartIdx = tagGlobalStartIdx;
+ TagLocalStartIdx = tagLocalStartIdx;
+ LinkId = linkId;
+ }
+
+ public TemplateInputData( TemplateInputData other )
+ {
+ DefaultValue = other.DefaultValue;
+ PortName = other.PortName;
+ DataType = other.DataType;
+ PortCategory = other.PortCategory;
+ PortUniqueId = other.PortUniqueId;
+ OrderId = other.OrderId;
+ TagId = other.TagId;
+ TagGlobalStartIdx = other.TagGlobalStartIdx;
+ LinkId = other.LinkId;
+ }
+ }
+
+
+
+ [Serializable]
+ public class TemplatePropertyContainer
+ {
+ [SerializeField]
+ private List<TemplateProperty> m_propertyList = new List<TemplateProperty>();
+ private Dictionary<string, TemplateProperty> m_propertyDict = new Dictionary<string, TemplateProperty>();
+
+
+ public void AddId( TemplateProperty templateProperty )
+ {
+ BuildInfo();
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+
+ public void AddId( string body, string ID, bool searchIndentation = true )
+ {
+ AddId( body, ID, searchIndentation, string.Empty );
+ }
+
+ public void AddId( string body, string ID, bool searchIndentation, string customIndentation )
+ {
+ BuildInfo();
+
+ int propertyIndex = body.IndexOf( ID );
+ if( propertyIndex > -1 )
+ {
+ if( searchIndentation )
+ {
+ int identationIndex = -1;
+ for( int i = propertyIndex; i >= 0; i-- )
+ {
+ if( body[ i ] == TemplatesManager.TemplateNewLine )
+ {
+ identationIndex = i + 1;
+ break;
+ }
+
+ if( i == 0 )
+ {
+ identationIndex = 0;
+ }
+ }
+ if( identationIndex > -1 )
+ {
+ int length = propertyIndex - identationIndex;
+ string indentation = ( length > 0 ) ? body.Substring( identationIndex, length ) : string.Empty;
+ TemplateProperty templateProperty = new TemplateProperty( ID, indentation, false );
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+ else
+ {
+ TemplateProperty templateProperty = new TemplateProperty( ID, string.Empty, false );
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+ }
+ else
+ {
+ TemplateProperty templateProperty = new TemplateProperty( ID, customIndentation, true );
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+ }
+ }
+
+
+ public void AddId( string body, string ID, int propertyIndex, bool searchIndentation )
+ {
+ AddId( body, ID, propertyIndex, searchIndentation, string.Empty );
+ }
+
+ public void AddId( string body, string ID, int propertyIndex, bool searchIndentation, string customIndentation )
+ {
+ if( body == null || string.IsNullOrEmpty( body ) )
+ return;
+
+ BuildInfo();
+ if( searchIndentation && propertyIndex > -1 && propertyIndex < body.Length )
+ {
+ int indentationIndex = -1;
+ for( int i = propertyIndex; i > 0; i-- )
+ {
+ if( body[ i ] == TemplatesManager.TemplateNewLine )
+ {
+ indentationIndex = i + 1;
+ break;
+ }
+ }
+
+ if( indentationIndex > -1 )
+ {
+ int length = propertyIndex - indentationIndex;
+ string indentation = ( length > 0 ) ? body.Substring( indentationIndex, length ) : string.Empty;
+ TemplateProperty templateProperty = new TemplateProperty( ID, indentation, false );
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+ }
+ else
+ {
+ TemplateProperty templateProperty = new TemplateProperty( ID, customIndentation, true );
+ m_propertyList.Add( templateProperty );
+ m_propertyDict.Add( templateProperty.Id, templateProperty );
+ }
+
+ }
+ public void BuildInfo()
+ {
+ if( m_propertyDict == null )
+ {
+ m_propertyDict = new Dictionary<string, TemplateProperty>();
+ }
+
+ if( m_propertyList.Count != m_propertyDict.Count )
+ {
+ m_propertyDict.Clear();
+ for( int i = 0; i < m_propertyList.Count; i++ )
+ {
+ m_propertyDict.Add( m_propertyList[ i ].Id, m_propertyList[ i ] );
+ }
+ }
+ }
+
+ public void ResetTemplateUsageData()
+ {
+ BuildInfo();
+ for( int i = 0; i < m_propertyList.Count; i++ )
+ {
+ m_propertyList[ i ].Used = false;
+ }
+ }
+
+ public void Reset()
+ {
+ m_propertyList.Clear();
+ m_propertyDict.Clear();
+ }
+
+ public void Destroy()
+ {
+ m_propertyList.Clear();
+ m_propertyList = null;
+ m_propertyDict.Clear();
+ m_propertyDict = null;
+ }
+
+
+ public Dictionary<string, TemplateProperty> PropertyDict
+ {
+ get
+ {
+ BuildInfo();
+ return m_propertyDict;
+ }
+ }
+ public List<TemplateProperty> PropertyList { get { return m_propertyList; } }
+ }
+
+ [Serializable]
+ public class TemplateProperty
+ {
+ public bool UseIndentationAtStart = false;
+ public string Indentation;
+ public bool UseCustomIndentation;
+ public string Id;
+ public bool AutoLineFeed;
+ public bool Used;
+
+ public TemplateProperty( string id, string indentation, bool useCustomIndentation )
+ {
+ Id = id;
+ Indentation = indentation;
+ UseCustomIndentation = useCustomIndentation;
+ AutoLineFeed = !string.IsNullOrEmpty( indentation );
+ Used = false;
+ }
+ }
+
+ [Serializable]
+ public class TemplateTessVControlTag
+ {
+ public string Id;
+ public int StartIdx;
+
+ public TemplateTessVControlTag()
+ {
+ StartIdx = -1;
+ }
+
+ public bool IsValid { get { return StartIdx >= 0; } }
+ }
+
+ [Serializable]
+ public class TemplateTessControlData
+ {
+ public string Id;
+ public int StartIdx;
+ public string InVarType;
+ public string InVarName;
+ public string OutVarType;
+ public string OutVarName;
+
+ public bool IsValid { get { return StartIdx >= 0; } }
+
+ public TemplateTessControlData()
+ {
+ StartIdx = -1;
+ }
+
+ public TemplateTessControlData( int startIdx, string id, string inVarInfo, string outVarInfo )
+ {
+ StartIdx = startIdx;
+ Id = id;
+ string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( inVarInfoArr.Length > 1 )
+ {
+ InVarType = inVarInfoArr[ 1 ];
+ InVarName = inVarInfoArr[ 0 ];
+ }
+
+ string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( outVarInfoArr.Length > 1 )
+ {
+ OutVarType = outVarInfoArr[ 1 ];
+ OutVarName = outVarInfoArr[ 0 ];
+ }
+ }
+
+ public string[] GenerateControl( Dictionary<TemplateSemantics, TemplateVertexData> vertexData, List<string> inputList )
+ {
+ List<string> value = new List<string>();
+ if( vertexData != null && vertexData.Count > 0 )
+ {
+ foreach( var item in vertexData )
+ {
+ if( inputList.FindIndex( x => { return x.Contains( item.Value.VarName ); } ) > -1 )
+ value.Add( string.Format( "{0}.{1} = {2}.{1};", OutVarName, item.Value.VarName, InVarName ) );
+ }
+ }
+ return value.ToArray();
+ }
+ }
+
+ [Serializable]
+ public class TemplateTessDomainData
+ {
+ public string Id;
+ public int StartIdx;
+ public string InVarType;
+ public string InVarName;
+ public string OutVarType;
+ public string OutVarName;
+ public string BaryVarType;
+ public string BaryVarName;
+
+ public bool IsValid { get { return StartIdx >= 0; } }
+
+ public TemplateTessDomainData()
+ {
+ StartIdx = -1;
+ }
+
+ public TemplateTessDomainData( int startIdx, string id, string inVarInfo, string outVarInfo, string baryVarInfo )
+ {
+ StartIdx = startIdx;
+ Id = id;
+ string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( inVarInfoArr.Length > 1 )
+ {
+ InVarType = inVarInfoArr[ 1 ];
+ InVarName = inVarInfoArr[ 0 ];
+ }
+
+ string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( outVarInfoArr.Length > 1 )
+ {
+ OutVarType = outVarInfoArr[ 1 ];
+ OutVarName = outVarInfoArr[ 0 ];
+ }
+
+ string[] baryVarInfoArr = baryVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( baryVarInfoArr.Length > 1 )
+ {
+ BaryVarType = baryVarInfoArr[ 1 ];
+ BaryVarName = baryVarInfoArr[ 0 ];
+ }
+ }
+
+ public string[] GenerateDomain( Dictionary<TemplateSemantics, TemplateVertexData> vertexData, List<string> inputList )
+ {
+ List<string> value = new List<string>();
+ if( vertexData != null && vertexData.Count > 0 )
+ {
+ foreach( var item in vertexData )
+ {
+ //o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z;
+ if( inputList.FindIndex( x => { return x.Contains( item.Value.VarName ); } ) > -1 )
+ value.Add( string.Format( "{0}.{1} = {2}[0].{1} * {3}.x + {2}[1].{1} * {3}.y + {2}[2].{1} * {3}.z;", OutVarName, item.Value.VarName, InVarName, BaryVarName ) );
+ }
+ }
+ return value.ToArray();
+ }
+ }
+
+ [Serializable]
+ public class TemplateFunctionData
+ {
+ public int MainBodyLocalIdx;
+ public string MainBodyName;
+
+ public string Id;
+ public int Position;
+ public string InVarType;
+ public string InVarName;
+ public string OutVarType;
+ public string OutVarName;
+ public MasterNodePortCategory Category;
+ public TemplateFunctionData( int mainBodyLocalIdx, string mainBodyName, string id, int position, string inVarInfo, string outVarInfo, MasterNodePortCategory category )
+ {
+ MainBodyLocalIdx = mainBodyLocalIdx;
+ MainBodyName = mainBodyName;
+ Id = id;
+ Position = position;
+ {
+ string[] inVarInfoArr = inVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( inVarInfoArr.Length > 1 )
+ {
+ InVarType = inVarInfoArr[ 1 ];
+ InVarName = inVarInfoArr[ 0 ];
+ }
+ }
+ {
+ string[] outVarInfoArr = outVarInfo.Split( IOUtils.VALUE_SEPARATOR );
+ if( outVarInfoArr.Length > 1 )
+ {
+ OutVarType = outVarInfoArr[ 1 ];
+ OutVarName = outVarInfoArr[ 0 ];
+ }
+ }
+ Category = category;
+ }
+ }
+
+ [Serializable]
+ public class TemplateTagData
+ {
+ public int StartIdx = -1;
+ public string Id;
+ public bool SearchIndentation;
+ public string CustomIndentation;
+
+
+ public TemplateTagData( int startIdx, string id, bool searchIndentation )
+ {
+ StartIdx = startIdx;
+ Id = id;
+ SearchIndentation = searchIndentation;
+ CustomIndentation = string.Empty;
+ }
+
+ public TemplateTagData( string id, bool searchIndentation )
+ {
+ Id = id;
+ SearchIndentation = searchIndentation;
+ CustomIndentation = string.Empty;
+ }
+
+ public TemplateTagData( string id, bool searchIndentation, string customIndentation )
+ {
+ Id = id;
+ SearchIndentation = searchIndentation;
+ CustomIndentation = customIndentation;
+ }
+
+ public bool IsValid { get { return StartIdx >= 0; } }
+ }
+
+ public enum TemplatePortIds
+ {
+ Name = 0,
+ DataType,
+ UniqueId,
+ OrderId,
+ Link
+ }
+
+ public enum TemplateCommonTagId
+ {
+ Property = 0,
+ Global = 1,
+ Function = 2,
+ Tag = 3,
+ Pragmas = 4,
+ Pass = 5,
+ Params_Vert = 6,
+ Params_Frag = 7
+ //CullMode = 8,
+ //BlendMode = 9,
+ //BlendOp = 10,
+ //ColorMask = 11,
+ //StencilOp = 12
+ }
+
+ [Serializable]
+ public class TemplatesManager : ScriptableObject
+ {
+ public static int MPShaderVersion = 14503;
+
+ public static readonly string TemplateShaderNameBeginTag = "/*ase_name*/";
+ public static readonly string TemplateStencilTag = "/*ase_stencil*/\n";
+ public static readonly string TemplateAllModulesTag = "/*ase_all_modules*/\n";
+ public static readonly string TemplateMPSubShaderTag = "\\bSubShader\\b\\s*{";
+ //public static readonly string TemplateMPPassTag = "^\\s*Pass\b\\s*{";//"\\bPass\\b\\s*{";
+ public static readonly string TemplateMPPassTag = "\\bPass\\b\\s*{";
+ public static readonly string TemplateLocalVarTag = "/*ase_local_var*/";
+ public static readonly string TemplateDependenciesListTag = "/*ase_dependencies_list*/";
+ public static readonly string TemplatePragmaBeforeTag = "/*ase_pragma_before*/";
+ public static readonly string TemplatePragmaTag = "/*ase_pragma*/";
+ public static readonly string TemplatePassTag = "/*ase_pass*/";
+ public static readonly string TemplatePassesEndTag = "/*ase_pass_end*/";
+ public static readonly string TemplateLODsTag = "/*ase_lod*/";
+ //public static readonly string TemplatePassTagPattern = @"\s\/\*ase_pass\*\/";
+ public static readonly string TemplatePassTagPattern = @"\s\/\*ase_pass[:\*]+";
+ public static readonly string TemplatePropertyTag = "/*ase_props*/";
+ public static readonly string TemplateGlobalsTag = "/*ase_globals*/";
+ public static readonly string TemplateSRPBatcherTag = "/*ase_srp_batcher*/\n";
+ public static readonly string TemplateInterpolatorBeginTag = "/*ase_interp(";
+ public static readonly string TemplateVertexDataTag = "/*ase_vdata:";
+
+ public static readonly string TemplateTessVControlTag = "/*ase_vcontrol*/";
+ public static readonly string TemplateTessControlCodeArea = "/*ase_control_code:";
+ public static readonly string TemplateTessDomainCodeArea = "/*ase_domain_code:";
+
+ //public static readonly string TemplateExcludeFromGraphTag = "/*ase_hide_pass*/";
+ public static readonly string TemplateMainPassTag = "/*ase_main_pass*/";
+
+ public static readonly string TemplateFunctionsTag = "/*ase_funcs*/\n";
+ //public static readonly string TemplateTagsTag = "/*ase_tags*/";
+
+ //public static readonly string TemplateCullModeTag = "/*ase_cull_mode*/";
+ //public static readonly string TemplateBlendModeTag = "/*ase_blend_mode*/";
+ //public static readonly string TemplateBlendOpTag = "/*ase_blend_op*/";
+ //public static readonly string TemplateColorMaskTag = "/*ase_color_mask*/";
+ //public static readonly string TemplateStencilOpTag = "/*ase_stencil*/";
+
+ public static readonly string TemplateCodeSnippetAttribBegin = "#CODE_SNIPPET_ATTRIBS_BEGIN#";
+ public static readonly string TemplateCodeSnippetAttribEnd = "#CODE_SNIPPET_ATTRIBS_END#\n";
+ public static readonly string TemplateCodeSnippetEnd = "#CODE_SNIPPET_END#\n";
+
+ public static readonly char TemplateNewLine = '\n';
+
+ // INPUTS AREA
+ public static readonly string TemplateInputsVertBeginTag = "/*ase_vert_out:";
+ public static readonly string TemplateInputsFragBeginTag = "/*ase_frag_out:";
+ public static readonly string TemplateInputsVertParamsTag = "/*ase_vert_input*/";
+ public static readonly string TemplateInputsFragParamsTag = "/*ase_frag_input*/";
+
+
+ // CODE AREA
+ public static readonly string TemplateVertexCodeBeginArea = "/*ase_vert_code:";
+ public static readonly string TemplateFragmentCodeBeginArea = "/*ase_frag_code:";
+
+
+ public static readonly string TemplateEndOfLine = "*/\n";
+ public static readonly string TemplateEndSectionTag = "*/";
+ public static readonly string TemplateFullEndTag = "/*end*/";
+
+ public static readonly string NameFormatter = "\"{0}\"";
+
+ public static readonly TemplateTagData[] CommonTags = { new TemplateTagData( TemplatePropertyTag,true),
+ new TemplateTagData( TemplateGlobalsTag,true),
+ new TemplateTagData( TemplateSRPBatcherTag,true),
+ new TemplateTagData( TemplateFunctionsTag,true),
+ //new TemplateTagData( TemplateTagsTag,false," "),
+ new TemplateTagData( TemplatePragmaBeforeTag,true),
+ new TemplateTagData( TemplatePragmaTag,true),
+ new TemplateTagData( TemplatePassTag,true),
+ new TemplateTagData( TemplateInputsVertParamsTag,false),
+ new TemplateTagData( TemplateInputsFragParamsTag,false),
+ new TemplateTagData( TemplateLODsTag,true)
+ //new TemplateTagData( TemplateCullModeTag,false),
+ //new TemplateTagData( TemplateBlendModeTag,false),
+ //new TemplateTagData( TemplateBlendOpTag,false),
+ //new TemplateTagData( TemplateColorMaskTag,false),
+ //new TemplateTagData( TemplateStencilOpTag,true),
+ };
+ public static string LightweigthPBRGUID = "1976390536c6c564abb90fe41f6ee334";
+ public static string LightweigthUnlitGUID = "e2514bdcf5e5399499a9eb24d175b9db";
+ public static string UniversalPBRGUID = "94348b07e5e8bab40bd6c8a1e3df54cd";
+ public static string UniversalUnlitGUID = "2992e84f91cbeb14eab234972e07ea9d";
+
+ public static string HDNewLitGUID = "53b46d85872c5b24c8f4f0a1c3fe4c87";
+ public static string HDNewPBRGUID = "41e04be03f2c20941bc749271be1c937";
+ public static string HDNewUnlitGUID = "7f5cb9c3ea6481f469fdd856555439ef";
+ public static string HDLitGUID = "091c43ba8bd92c9459798d59b089ce4e";
+ public static string HDPBRGUID = "bb308bce79762c34e823049efce65141";
+ public static string HDUnlitGUID = "dfe2f27ac20b08c469b2f95c236be0c3";
+
+ public static Dictionary<string, string> OfficialTemplates = new Dictionary<string, string>()
+ {
+ { "0770190933193b94aaa3065e307002fa","Legacy/Unlit"},
+ { "32139be9c1eb75640a847f011acf3bcf","Legacy/Post-Processing Stack"},
+ { "6ce779933eb99f049b78d6163735e06f","Legacy/Custom RT Init"},
+ { "32120270d1b3a8746af2aca8bc749736","Legacy/Custom RT Update"},
+ { LightweigthPBRGUID,"LW/PBR"},
+ { LightweigthUnlitGUID,"LW/Unlit"},
+ { UniversalPBRGUID,"Universal/PBR"},
+ { UniversalUnlitGUID,"Universal/Unlit"},
+ { "53b46d85872c5b24c8f4f0a1c3fe4c87","HD/Lit"},
+ { HDLitGUID,"Deprecated/HD/Lit"},
+ { HDPBRGUID,"Deprecated/HD/PBR"},
+ { HDUnlitGUID,"Deprecated/HD/Unlit"},
+ { "c71b220b631b6344493ea3cf87110c93","Legacy/Post Process" },
+ { "6e114a916ca3e4b4bb51972669d463bf","Deprecated/Legacy/Default Unlit" },
+ { "5056123faa0c79b47ab6ad7e8bf059a4","Legacy/Default UI" },
+ { "899e609c083c74c4ca567477c39edef0","Legacy/Unlit Lightmap" },
+ { "0f8ba0101102bb14ebf021ddadce9b49","Legacy/Default Sprites" },
+ { "0b6a9f8b4f707c74ca64c0be8e590de0","Legacy/Particles Alpha Blended" },
+ { "e1de45c0d41f68c41b2cc20c8b9c05ef","Legacy/Multi Pass Unlit" }
+ };
+
+ public static readonly string TemplateMenuItemsFileGUID = "da0b931bd234a1e43b65f684d4b59bfb";
+
+ private Dictionary<string, TemplateDataParent> m_availableTemplates = new Dictionary<string, TemplateDataParent>();
+
+ [SerializeField]
+ private List<TemplateDataParent> m_sortedTemplates = new List<TemplateDataParent>();
+
+ [SerializeField]
+ public string[] AvailableTemplateNames;
+
+ [SerializeField]
+ public bool Initialized = false;
+
+ private Dictionary<string, bool> m_optionsInitialSetup = new Dictionary<string, bool>();
+
+ public static string CurrTemplateGUIDLoaded = string.Empty;
+
+ public static bool IsTestTemplate { get { return CurrTemplateGUIDLoaded.Equals( "a95a019bbc760714bb8228af04c291d1" ); } }
+ public static bool ShowDebugMessages = false;
+ public void RefreshAvailableTemplates()
+ {
+ if( m_availableTemplates.Count != m_sortedTemplates.Count )
+ {
+ m_availableTemplates.Clear();
+ int count = m_sortedTemplates.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] );
+ }
+ }
+ }
+
+ public void Init()
+ {
+ if( !Initialized )
+ {
+ if( ShowDebugMessages )
+ Debug.Log( "Initialize" );
+
+ string templateMenuItems = IOUtils.LoadTextFileFromDisk( AssetDatabase.GUIDToAssetPath( TemplateMenuItemsFileGUID ) );
+ bool refreshTemplateMenuItems = false;
+
+ foreach( KeyValuePair<string, string> kvp in OfficialTemplates )
+ {
+ if( !string.IsNullOrEmpty( AssetDatabase.GUIDToAssetPath( kvp.Key ) ) )
+ {
+ TemplateMultiPass template = ScriptableObject.CreateInstance<TemplateMultiPass>();
+ template.Init( kvp.Value, kvp.Key, false );
+ AddTemplate( template );
+ if( !refreshTemplateMenuItems && templateMenuItems.IndexOf( kvp.Value ) < 0 )
+ refreshTemplateMenuItems = true;
+ }
+ }
+
+ // Search for other possible templates on the project
+ string[] allShaders = AssetDatabase.FindAssets( "t:shader" );
+ for( int i = 0; i < allShaders.Length; i++ )
+ {
+ if( !m_availableTemplates.ContainsKey( allShaders[ i ] ) )
+ {
+ CheckAndLoadTemplate( allShaders[ i ] );
+ }
+ }
+
+ // TODO: Sort list alphabeticaly
+ AvailableTemplateNames = new string[ m_sortedTemplates.Count + 1 ];
+ AvailableTemplateNames[ 0 ] = "Custom";
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ m_sortedTemplates[ i ].OrderId = i;
+ AvailableTemplateNames[ i + 1 ] = m_sortedTemplates[ i ].Name;
+ }
+
+ if( refreshTemplateMenuItems )
+ CreateTemplateMenuItems();
+
+ Initialized = true;
+ }
+ }
+
+ //[MenuItem( "Window/Amplify Shader Editor/Create Menu Items", false, 1000 )]
+ //public static void ForceCreateTemplateMenuItems()
+ //{
+ // UIUtils.CurrentWindow.TemplatesManagerInstance.CreateTemplateMenuItems();
+ //}
+
+ public void CreateTemplateMenuItems()
+ {
+ if( m_sortedTemplates == null || m_sortedTemplates.Count == 0 )
+ return;
+
+ // change names for duplicates
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ for( int j = 0; j < i; j++ )
+ {
+ if( m_sortedTemplates[ i ].Name == m_sortedTemplates[ j ].Name )
+ {
+ var match = Regex.Match( m_sortedTemplates[ i ].Name, @".+(\d+)" );
+ if( match.Success )
+ {
+ string strNumber = match.Groups[ 1 ].Value;
+ int number = int.Parse( strNumber ) + 1;
+ string firstPart = m_sortedTemplates[ i ].Name.Substring( 0, match.Groups[ 1 ].Index );
+ string secondPart = m_sortedTemplates[ i ].Name.Substring( match.Groups[ 1 ].Index + strNumber.Length );
+ m_sortedTemplates[ i ].Name = firstPart + number + secondPart;
+ }
+ else
+ {
+ m_sortedTemplates[ i ].Name += " 1";
+ }
+ }
+ }
+ }
+
+ System.Text.StringBuilder fileContents = new System.Text.StringBuilder();
+ fileContents.Append( "// Amplify Shader Editor - Visual Shader Editing Tool\n" );
+ fileContents.Append( "// Copyright (c) Amplify Creations, Lda <info@amplify.pt>\n" );
+ fileContents.Append( "using UnityEditor;\n" );
+ fileContents.Append( "\n" );
+ fileContents.Append( "namespace AmplifyShaderEditor\n" );
+ fileContents.Append( "{\n" );
+ fileContents.Append( "\tpublic class TemplateMenuItems\n" );
+ fileContents.Append( "\t{\n" );
+ int fixedPriority = 85;
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ fileContents.AppendFormat( "\t\t[MenuItem( \"Assets/Create/Amplify Shader/{0}\", false, {1} )]\n", m_sortedTemplates[ i ].Name, fixedPriority );
+ string itemName = UIUtils.RemoveInvalidCharacters( m_sortedTemplates[ i ].Name );
+ fileContents.AppendFormat( "\t\tpublic static void ApplyTemplate{0}()\n", itemName/*i*/ );
+ fileContents.Append( "\t\t{\n" );
+ //fileContents.AppendFormat( "\t\t\tAmplifyShaderEditorWindow.CreateNewTemplateShader( \"{0}\" );\n", m_sortedTemplates[ i ].GUID );
+ fileContents.AppendFormat( "\t\t\tAmplifyShaderEditorWindow.CreateConfirmationTemplateShader( \"{0}\" );\n", m_sortedTemplates[ i ].GUID );
+ fileContents.Append( "\t\t}\n" );
+ }
+ fileContents.Append( "\t}\n" );
+ fileContents.Append( "}\n" );
+ string filePath = AssetDatabase.GUIDToAssetPath( TemplateMenuItemsFileGUID );
+ IOUtils.SaveTextfileToDisk( fileContents.ToString(), filePath, false );
+ AssetDatabase.ImportAsset( filePath );
+ }
+
+ public int GetIdForTemplate( TemplateData templateData )
+ {
+ if( templateData == null )
+ return -1;
+
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ if( m_sortedTemplates[ i ].GUID.Equals( templateData.GUID ) )
+ return m_sortedTemplates[ i ].OrderId;
+ }
+ return -1;
+ }
+
+
+
+ public void AddTemplate( TemplateDataParent templateData )
+ {
+ if( templateData == null || !templateData.IsValid )
+ return;
+ RefreshAvailableTemplates();
+ if( !m_availableTemplates.ContainsKey( templateData.GUID ) )
+ {
+ m_sortedTemplates.Add( templateData );
+ m_availableTemplates.Add( templateData.GUID, templateData );
+ }
+ }
+
+ public void RemoveTemplate( string guid )
+ {
+ TemplateDataParent templateData = GetTemplate( guid );
+ if( templateData != null )
+ {
+ RemoveTemplate( templateData );
+ }
+ }
+
+ public void RemoveTemplate( TemplateDataParent templateData )
+ {
+ RefreshAvailableTemplates();
+
+ if( m_availableTemplates != null )
+ m_availableTemplates.Remove( templateData.GUID );
+
+ m_sortedTemplates.Remove( templateData );
+ templateData.Destroy();
+ }
+
+ public void Destroy()
+ {
+ if( TemplatesManager.ShowDebugMessages )
+ Debug.Log( "Destroy Manager" );
+ if( m_availableTemplates != null )
+ {
+ foreach( KeyValuePair<string, TemplateDataParent> kvp in m_availableTemplates )
+ {
+ kvp.Value.Destroy();
+ }
+ m_availableTemplates.Clear();
+ m_availableTemplates = null;
+ }
+ int count = m_sortedTemplates.Count;
+
+ for( int i = 0; i < count; i++ )
+ {
+ ScriptableObject.DestroyImmediate( m_sortedTemplates[ i ] );
+ }
+
+ m_sortedTemplates.Clear();
+ m_sortedTemplates = null;
+
+ AvailableTemplateNames = null;
+ Initialized = false;
+ }
+
+ public TemplateDataParent GetTemplate( int id )
+ {
+ if( id < m_sortedTemplates.Count )
+ return m_sortedTemplates[ id ];
+
+ return null;
+ }
+
+ public TemplateDataParent GetTemplate( string guid )
+ {
+ RefreshAvailableTemplates();
+ if( m_availableTemplates == null && m_sortedTemplates != null )
+ {
+ m_availableTemplates = new Dictionary<string, TemplateDataParent>();
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] );
+ }
+ }
+
+ if( m_availableTemplates.ContainsKey( guid ) )
+ return m_availableTemplates[ guid ];
+
+ return null;
+ }
+
+
+ public TemplateDataParent GetTemplateByName( string name )
+ {
+ RefreshAvailableTemplates();
+ if( m_availableTemplates == null && m_sortedTemplates != null )
+ {
+ m_availableTemplates = new Dictionary<string, TemplateDataParent>();
+ for( int i = 0; i < m_sortedTemplates.Count; i++ )
+ {
+ m_availableTemplates.Add( m_sortedTemplates[ i ].GUID, m_sortedTemplates[ i ] );
+ }
+ }
+
+ foreach( KeyValuePair<string, TemplateDataParent> kvp in m_availableTemplates )
+ {
+ if( kvp.Value.DefaultShaderName.Equals( name ) )
+ {
+ return kvp.Value;
+ }
+ }
+ return null;
+ }
+
+ public TemplateDataParent CheckAndLoadTemplate( string guid )
+ {
+ TemplateDataParent templateData = GetTemplate( guid );
+ if( templateData == null )
+ {
+ string datapath = AssetDatabase.GUIDToAssetPath( guid );
+ string body = IOUtils.LoadTextFileFromDisk( datapath );
+
+ if( body.IndexOf( TemplatesManager.TemplateShaderNameBeginTag ) > -1 )
+ {
+ templateData = ScriptableObject.CreateInstance<TemplateMultiPass>();
+ templateData.Init( string.Empty, guid, true );
+ if( templateData.IsValid )
+ {
+ AddTemplate( templateData );
+ return templateData;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private void OnEnable()
+ {
+ if( !Initialized )
+ {
+ Init();
+ }
+ else
+ {
+ RefreshAvailableTemplates();
+ }
+ hideFlags = HideFlags.HideAndDontSave;
+ if( ShowDebugMessages )
+ Debug.Log( "On Enable Manager: " + this.GetInstanceID() );
+ }
+
+ public void ResetOptionsSetupData()
+ {
+ if( ShowDebugMessages )
+ Debug.Log( "Reseting options setup data" );
+ m_optionsInitialSetup.Clear();
+ }
+
+ public bool SetOptionsValue( string optionId, bool value )
+ {
+ if( m_optionsInitialSetup.ContainsKey( optionId ) )
+ {
+ m_optionsInitialSetup[ optionId ] = m_optionsInitialSetup[ optionId ] || value;
+ }
+ else
+ {
+ m_optionsInitialSetup.Add( optionId, value );
+ }
+ return m_optionsInitialSetup[ optionId ];
+ }
+
+ public int TemplateCount { get { return m_sortedTemplates.Count; } }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta
new file mode 100644
index 00000000..b49d0694
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesManager.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9f0aacdb47cf3b94ebbe9e72af9d3cf1
+timeCreated: 1481126958
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs
new file mode 100644
index 00000000..6be80ea4
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs
@@ -0,0 +1,662 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace AmplifyShaderEditor
+{
+
+ [Serializable]
+ public sealed class TemplatesStencilBufferModule : TemplateModuleParent
+ {
+ private const string FoldoutLabelStr = " Stencil Buffer";
+ private GUIContent ReferenceValueContent = new GUIContent( "Reference", "The value to be compared against (if Comparison is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace)" );
+ private GUIContent ReadMaskContent = new GUIContent( "Read Mask", "An 8 bit mask as an 0-255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)" );
+ private GUIContent WriteMaskContent = new GUIContent( "Write Mask", "An 8 bit mask as an 0-255 integer, used when writing to the buffer" );
+ private const string ComparisonStr = "Comparison";
+ private const string PassStr = "Pass";
+ private const string FailStr = "Fail";
+ private const string ZFailStr = "ZFail";
+
+ private const string ComparisonFrontStr = "Comp. Front";
+ private const string PassFrontStr = "Pass Front";
+ private const string FailFrontStr = "Fail Front";
+ private const string ZFailFrontStr = "ZFail Front";
+
+ private const string ComparisonBackStr = "Comp. Back";
+ private const string PassBackStr = "Pass Back";
+ private const string FailBackStr = "Fail Back";
+ private const string ZFailBackStr = "ZFail Back";
+
+ private Dictionary<string, int> m_comparisonDict = new Dictionary<string, int>();
+ private Dictionary<string, int> m_stencilOpsDict = new Dictionary<string, int>();
+
+ [SerializeField]
+ private bool m_active = true;
+
+ [SerializeField]
+ private InlineProperty m_reference = new InlineProperty();
+
+ // Read Mask
+ private const int ReadMaskDefaultValue = 255;
+ [SerializeField]
+ private InlineProperty m_readMask = new InlineProperty( ReadMaskDefaultValue );
+
+ //Write Mask
+ private const int WriteMaskDefaultValue = 255;
+ [SerializeField]
+ private InlineProperty m_writeMask = new InlineProperty( WriteMaskDefaultValue );
+
+ //Comparison Function
+ private const int ComparisonDefaultValue = 0;
+ [SerializeField]
+ private InlineProperty m_comparisonFunctionFrontIdx = new InlineProperty( ComparisonDefaultValue );
+
+ [SerializeField]
+ private InlineProperty m_comparisonFunctionBackIdx = new InlineProperty( ComparisonDefaultValue );
+
+ //Pass Stencil Op
+ private const int PassStencilOpDefaultValue = 0;
+ [SerializeField]
+ private InlineProperty m_passStencilOpFrontIdx = new InlineProperty( PassStencilOpDefaultValue );
+
+ [SerializeField]
+ private InlineProperty m_passStencilOpBackIdx = new InlineProperty( PassStencilOpDefaultValue );
+
+ //Fail Stencil Op
+ private const int FailStencilOpDefaultValue = 0;
+
+ [SerializeField]
+ private InlineProperty m_failStencilOpFrontIdx = new InlineProperty( FailStencilOpDefaultValue );
+
+ [SerializeField]
+ private InlineProperty m_failStencilOpBackIdx = new InlineProperty( FailStencilOpDefaultValue );
+
+ //ZFail Stencil Op
+ private const int ZFailStencilOpDefaultValue = 0;
+ [SerializeField]
+ private InlineProperty m_zFailStencilOpFrontIdx = new InlineProperty( ZFailStencilOpDefaultValue );
+
+ [SerializeField]
+ private InlineProperty m_zFailStencilOpBackIdx = new InlineProperty( ZFailStencilOpDefaultValue );
+
+ public TemplatesStencilBufferModule() : base("Stencil Buffer")
+ {
+ for( int i = 0; i < StencilBufferOpHelper.StencilComparisonValues.Length; i++ )
+ {
+ m_comparisonDict.Add( StencilBufferOpHelper.StencilComparisonValues[ i ].ToLower(), i );
+ }
+
+ for( int i = 0; i < StencilBufferOpHelper.StencilOpsValues.Length; i++ )
+ {
+ m_stencilOpsDict.Add( StencilBufferOpHelper.StencilOpsValues[ i ].ToLower(), i );
+ }
+ }
+
+ public void CopyFrom( TemplatesStencilBufferModule other , bool allData )
+ {
+ if( allData )
+ m_independentModule = other.IndependentModule;
+
+ m_active = other.Active;
+ m_reference.CopyFrom( other.Reference );
+ m_readMask.CopyFrom( other.ReadMask );
+ m_writeMask.CopyFrom( other.WriteMask );
+ m_comparisonFunctionFrontIdx.CopyFrom( other.ComparisonFunctionIdx );
+ m_comparisonFunctionBackIdx.CopyFrom( other.ComparisonFunctionBackIdx );
+ m_passStencilOpFrontIdx.CopyFrom( other.PassStencilOpIdx );
+ m_passStencilOpBackIdx.CopyFrom( other.PassStencilOpBackIdx );
+ m_failStencilOpFrontIdx.CopyFrom( other.FailStencilOpIdx );
+ m_failStencilOpBackIdx.CopyFrom( other.FailStencilOpBackIdx );
+ m_zFailStencilOpFrontIdx.CopyFrom( other.ZFailStencilOpIdx );
+ m_zFailStencilOpBackIdx.CopyFrom( other.ZFailStencilOpBackIdx );
+ }
+
+ public void ConfigureFromTemplateData( TemplateStencilData stencilData )
+ {
+ bool newValidData = ( stencilData.DataCheck == TemplateDataCheck.Valid );
+ if( newValidData && m_validData != newValidData )
+ {
+ m_active = stencilData.Active;
+ m_independentModule = stencilData.IndependentModule;
+ if( string.IsNullOrEmpty( stencilData.ReferenceInline ) )
+ {
+ m_reference.IntValue = stencilData.Reference;
+ m_reference.ResetProperty();
+ }
+ else
+ {
+ m_reference.SetInlineByName( stencilData.ReferenceInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.ReadMaskInline ) )
+ {
+ m_readMask.IntValue = stencilData.ReadMask;
+ m_readMask.ResetProperty();
+ }
+ else
+ {
+ m_readMask.SetInlineByName( stencilData.ReadMaskInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.WriteMaskInline ) )
+ {
+ m_writeMask.IntValue = stencilData.WriteMask;
+ m_writeMask.ResetProperty();
+ }
+ else
+ {
+ m_writeMask.SetInlineByName( stencilData.WriteMaskInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.ComparisonFrontInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.ComparisonFront ) )
+ {
+ m_comparisonFunctionFrontIdx.IntValue = m_comparisonDict[ stencilData.ComparisonFront.ToLower() ];
+ }
+ else
+ {
+ m_comparisonFunctionFrontIdx.IntValue = m_comparisonDict[ "always" ];
+ }
+ m_comparisonFunctionFrontIdx.ResetProperty();
+ }
+ else
+ {
+ m_comparisonFunctionFrontIdx.SetInlineByName( stencilData.ComparisonFrontInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.PassFrontInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.PassFront ) )
+ {
+ m_passStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.PassFront.ToLower() ];
+ }
+ else
+ {
+ m_passStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_passStencilOpFrontIdx.ResetProperty();
+ }
+ else
+ {
+ m_passStencilOpFrontIdx.SetInlineByName( stencilData.PassFrontInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.FailFrontInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.FailFront ) )
+ {
+ m_failStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.FailFront.ToLower() ];
+ }
+ else
+ {
+ m_failStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_failStencilOpFrontIdx.ResetProperty();
+ }
+ else
+ {
+ m_failStencilOpFrontIdx.SetInlineByName( stencilData.FailFrontInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.ZFailFrontInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.ZFailFront ) )
+ {
+ m_zFailStencilOpFrontIdx.IntValue = m_stencilOpsDict[ stencilData.ZFailFront.ToLower() ];
+ }
+ else
+ {
+ m_zFailStencilOpFrontIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_zFailStencilOpFrontIdx.ResetProperty();
+ }
+ else
+ {
+ m_zFailStencilOpFrontIdx.SetInlineByName( stencilData.ZFailFrontInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.ComparisonBackInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.ComparisonBack ) )
+ {
+ m_comparisonFunctionBackIdx.IntValue = m_comparisonDict[ stencilData.ComparisonBack.ToLower() ];
+ }
+ else
+ {
+ m_comparisonFunctionBackIdx.IntValue = m_comparisonDict[ "always" ];
+ }
+ m_comparisonFunctionBackIdx.ResetProperty();
+ }
+ else
+ {
+ m_comparisonFunctionBackIdx.SetInlineByName( stencilData.ComparisonBackInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.PassBackInline ) )
+ {
+
+ if( !string.IsNullOrEmpty( stencilData.PassBack ) )
+ {
+ m_passStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.PassBack.ToLower() ];
+ }
+ else
+ {
+ m_passStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_passStencilOpBackIdx.ResetProperty();
+ }
+ else
+ {
+ m_passStencilOpBackIdx.SetInlineByName( stencilData.PassBackInline );
+ }
+
+ if( string.IsNullOrEmpty( stencilData.FailBackInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.FailBack ) )
+ {
+ m_failStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.FailBack.ToLower() ];
+ }
+ else
+ {
+ m_failStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_failStencilOpBackIdx.ResetProperty();
+ }
+ else
+ {
+ m_failStencilOpBackIdx.SetInlineByName( stencilData.FailBackInline );
+ }
+
+
+ if( string.IsNullOrEmpty( stencilData.ZFailBackInline ) )
+ {
+ if( !string.IsNullOrEmpty( stencilData.ZFailBack ) )
+ {
+ m_zFailStencilOpBackIdx.IntValue = m_stencilOpsDict[ stencilData.ZFailBack.ToLower() ];
+ }
+ else
+ {
+ m_zFailStencilOpBackIdx.IntValue = m_stencilOpsDict[ "keep" ];
+ }
+ m_zFailStencilOpBackIdx.ResetProperty();
+ }
+ else
+ {
+ m_zFailStencilOpBackIdx.SetInlineByName( stencilData.ZFailBackInline );
+ }
+ }
+ m_validData = newValidData;
+ }
+
+ public string CreateStencilOp( CullMode cullMode )
+ {
+ if( !m_active )
+ return string.Empty;
+
+ string result = "Stencil\n{\n";
+ result += string.Format( "\tRef {0}\n", m_reference.GetValueOrProperty() );
+ if( m_readMask.IsValid || m_readMask.IntValue != ReadMaskDefaultValue )
+ {
+ result += string.Format( "\tReadMask {0}\n", m_readMask.GetValueOrProperty() );
+ }
+
+ if( m_writeMask.IsValid || m_writeMask.IntValue != WriteMaskDefaultValue )
+ {
+ result += string.Format( "\tWriteMask {0}\n", m_writeMask.GetValueOrProperty() );
+ }
+
+ if( cullMode == CullMode.Off &&
+ ( m_comparisonFunctionBackIdx.IsValid || m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue ||
+ m_passStencilOpBackIdx.IsValid || m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue ||
+ m_failStencilOpBackIdx.IsValid || m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue ||
+ m_zFailStencilOpBackIdx.IsValid || m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue ) )
+ {
+ if( m_comparisonFunctionFrontIdx.IsValid || m_comparisonFunctionFrontIdx.IntValue != ComparisonDefaultValue )
+ result += string.Format( "\tCompFront {0}\n", m_comparisonFunctionFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionFrontIdx.IntValue ] ) );
+
+ if( m_passStencilOpFrontIdx.IsValid || m_passStencilOpFrontIdx.IntValue != PassStencilOpDefaultValue )
+ result += string.Format( "\tPassFront {0}\n", m_passStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpFrontIdx.IntValue ] ) );
+
+ if( m_failStencilOpFrontIdx.IsValid || m_failStencilOpFrontIdx.IntValue != FailStencilOpDefaultValue )
+ result += string.Format( "\tFailFront {0}\n", m_failStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpFrontIdx.IntValue ] ) );
+
+ if( m_zFailStencilOpFrontIdx.IsValid || m_zFailStencilOpFrontIdx.IntValue != ZFailStencilOpDefaultValue )
+ result += string.Format( "\tZFailFront {0}\n", m_zFailStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpFrontIdx.IntValue ] ) );
+
+ if( m_comparisonFunctionBackIdx.IsValid || m_comparisonFunctionBackIdx.IntValue != ComparisonDefaultValue )
+ result += string.Format( "\tCompBack {0}\n", m_comparisonFunctionBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionBackIdx.IntValue ] ) );
+
+ if( m_passStencilOpBackIdx.IsValid || m_passStencilOpBackIdx.IntValue != PassStencilOpDefaultValue )
+ result += string.Format( "\tPassBack {0}\n", m_passStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpBackIdx.IntValue ] ) );
+
+ if( m_failStencilOpBackIdx.IsValid || m_failStencilOpBackIdx.IntValue != FailStencilOpDefaultValue )
+ result += string.Format( "\tFailBack {0}\n", m_failStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpBackIdx.IntValue ] ));
+
+ if( m_zFailStencilOpBackIdx.IsValid || m_zFailStencilOpBackIdx.IntValue != ZFailStencilOpDefaultValue )
+ result += string.Format( "\tZFailBack {0}\n", m_zFailStencilOpBackIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpBackIdx.IntValue ] ));
+ }
+ else
+ {
+ if( m_comparisonFunctionFrontIdx.IsValid || m_comparisonFunctionFrontIdx.IntValue != ComparisonDefaultValue )
+ result += string.Format( "\tComp {0}\n", m_comparisonFunctionFrontIdx.GetValueOrProperty(StencilBufferOpHelper.StencilComparisonValues[ m_comparisonFunctionFrontIdx.IntValue ] ));
+ if( m_passStencilOpFrontIdx.IsValid || m_passStencilOpFrontIdx.IntValue != PassStencilOpDefaultValue )
+ result += string.Format( "\tPass {0}\n", m_passStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_passStencilOpFrontIdx.IntValue ] ));
+ if( m_failStencilOpFrontIdx.IsValid || m_failStencilOpFrontIdx.IntValue != FailStencilOpDefaultValue )
+ result += string.Format( "\tFail {0}\n", m_failStencilOpFrontIdx.GetValueOrProperty( StencilBufferOpHelper.StencilOpsValues[ m_failStencilOpFrontIdx.IntValue ] ));
+ if( m_zFailStencilOpFrontIdx.IsValid || m_zFailStencilOpFrontIdx.IntValue != ZFailStencilOpDefaultValue )
+ result += string.Format( "\tZFail {0}\n", m_zFailStencilOpFrontIdx.GetValueOrProperty(StencilBufferOpHelper.StencilOpsValues[ m_zFailStencilOpFrontIdx.IntValue ] ));
+ }
+
+ result += "}";
+ return result;
+ }
+
+ public override void ShowUnreadableDataMessage( ParentNode owner )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions;
+ NodeUtils.DrawPropertyGroup( ref foldout, FoldoutLabelStr, base.ShowUnreadableDataMessage );
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldout;
+ }
+
+ public void Draw( UndoParentNode owner, CullMode cullMode , bool style = true )
+ {
+ bool foldout = owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions;
+ if( style )
+ {
+ NodeUtils.DrawPropertyGroup( ref foldout, FoldoutLabelStr, () =>
+ {
+ DrawBlock( owner, cullMode );
+ } );
+ }
+ else
+ {
+ NodeUtils.DrawNestedPropertyGroup( owner, ref foldout, ref m_active, FoldoutLabelStr, () =>
+ {
+ DrawBlock( owner, cullMode );
+ } );
+ }
+ owner.ContainerGraph.ParentWindow.InnerWindowVariables.ExpandedStencilOptions = foldout;
+ }
+
+ void DrawBlock( UndoParentNode owner, CullMode cullMode )
+ {
+ bool guiEnabled = GUI.enabled;
+ GUI.enabled = m_active;
+ EditorGUI.BeginChangeCheck();
+ {
+ m_reference.IntSlider( ref owner, ReferenceValueContent, 0, 255 );
+ m_readMask.IntSlider( ref owner, ReadMaskContent, 0, 255 );
+ m_writeMask.IntSlider( ref owner, WriteMaskContent, 0, 255 );
+ if( cullMode == CullMode.Off )
+ {
+ m_comparisonFunctionFrontIdx.EnumTypePopup( ref owner, ComparisonFrontStr, StencilBufferOpHelper.StencilComparisonLabels );
+ m_passStencilOpFrontIdx.EnumTypePopup( ref owner, PassFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_failStencilOpFrontIdx.EnumTypePopup( ref owner, FailFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_zFailStencilOpFrontIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ EditorGUILayout.Separator();
+ m_comparisonFunctionBackIdx.EnumTypePopup( ref owner, ComparisonBackStr, StencilBufferOpHelper.StencilComparisonLabels );
+ m_passStencilOpBackIdx.EnumTypePopup( ref owner, PassBackStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_failStencilOpBackIdx.EnumTypePopup( ref owner, FailBackStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_zFailStencilOpBackIdx.EnumTypePopup( ref owner, ZFailBackStr, StencilBufferOpHelper.StencilOpsLabels );
+ }
+ else
+ {
+ m_comparisonFunctionFrontIdx.EnumTypePopup( ref owner, ComparisonStr, StencilBufferOpHelper.StencilComparisonLabels );
+ m_passStencilOpFrontIdx.EnumTypePopup( ref owner, PassFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_failStencilOpFrontIdx.EnumTypePopup( ref owner, FailFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ m_zFailStencilOpFrontIdx.EnumTypePopup( ref owner, ZFailFrontStr, StencilBufferOpHelper.StencilOpsLabels );
+ }
+ }
+ if( EditorGUI.EndChangeCheck() )
+ {
+ m_isDirty = true;
+ }
+ GUI.enabled = guiEnabled;
+ }
+
+ public override void ReadFromString( ref uint index, ref string[] nodeParams )
+ {
+ bool validDataOnMeta = m_validData;
+ if( UIUtils.CurrentShaderVersion() > TemplatesManager.MPShaderVersion )
+ {
+ validDataOnMeta = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( validDataOnMeta )
+ {
+ if( UIUtils.CurrentShaderVersion() > 15307 )
+ {
+ m_active = Convert.ToBoolean( nodeParams[ index++ ] );
+ }
+
+ if( UIUtils.CurrentShaderVersion() < 15304 )
+ {
+ m_reference.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_readMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_writeMask.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_comparisonFunctionFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_passStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_failStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_zFailStencilOpFrontIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_comparisonFunctionBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_passStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_failStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ m_zFailStencilOpBackIdx.IntValue = Convert.ToInt32( nodeParams[ index++ ] );
+ }
+ else
+ {
+ m_reference.ReadFromString( ref index, ref nodeParams );
+ m_readMask.ReadFromString( ref index, ref nodeParams );
+ m_writeMask.ReadFromString( ref index, ref nodeParams );
+ m_comparisonFunctionFrontIdx.ReadFromString( ref index, ref nodeParams );
+ m_passStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams );
+ m_failStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams );
+ m_zFailStencilOpFrontIdx.ReadFromString( ref index, ref nodeParams );
+ m_comparisonFunctionBackIdx.ReadFromString( ref index, ref nodeParams );
+ m_passStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
+ m_failStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
+ m_zFailStencilOpBackIdx.ReadFromString( ref index, ref nodeParams );
+ }
+
+ }
+ }
+
+ public override void WriteToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_validData );
+ if( m_validData )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_active );
+ m_reference.WriteToString( ref nodeInfo );
+ m_readMask.WriteToString( ref nodeInfo );
+ m_writeMask.WriteToString( ref nodeInfo );
+ m_comparisonFunctionFrontIdx.WriteToString( ref nodeInfo );
+ m_passStencilOpFrontIdx.WriteToString( ref nodeInfo );
+ m_failStencilOpFrontIdx.WriteToString( ref nodeInfo );
+ m_zFailStencilOpFrontIdx.WriteToString( ref nodeInfo );
+ m_comparisonFunctionBackIdx.WriteToString( ref nodeInfo );
+ m_passStencilOpBackIdx.WriteToString( ref nodeInfo );
+ m_failStencilOpBackIdx.WriteToString( ref nodeInfo );
+ m_zFailStencilOpBackIdx.WriteToString( ref nodeInfo );
+ }
+ }
+
+ public override void Destroy()
+ {
+ m_comparisonDict.Clear();
+ m_comparisonDict = null;
+
+ m_stencilOpsDict.Clear();
+ m_stencilOpsDict = null;
+
+ m_reference = null;
+ m_readMask = null;
+ m_writeMask = null;
+ m_comparisonFunctionFrontIdx = null;
+ m_passStencilOpFrontIdx = null;
+ m_failStencilOpFrontIdx = null;
+ m_zFailStencilOpFrontIdx = null;
+ m_comparisonFunctionBackIdx = null;
+ m_passStencilOpBackIdx = null;
+ m_failStencilOpBackIdx = null;
+ m_zFailStencilOpBackIdx = null;
+ }
+ public bool Active { get { return m_active; } }
+ public InlineProperty Reference { get { return m_reference; } }
+ public InlineProperty ReadMask { get { return m_readMask; } }
+ public InlineProperty WriteMask { get { return m_writeMask; } }
+ public InlineProperty ComparisonFunctionIdx { get { return m_comparisonFunctionFrontIdx; } }
+ public InlineProperty ComparisonFunctionBackIdx { get { return m_comparisonFunctionBackIdx; } }
+ public InlineProperty PassStencilOpIdx { get { return m_passStencilOpFrontIdx; } }
+ public InlineProperty PassStencilOpBackIdx { get { return m_passStencilOpBackIdx; } }
+ public InlineProperty FailStencilOpIdx { get { return m_failStencilOpFrontIdx; } }
+ public InlineProperty FailStencilOpBackIdx { get { return m_failStencilOpBackIdx; } }
+ public InlineProperty ZFailStencilOpIdx { get { return m_zFailStencilOpFrontIdx; } }
+ public InlineProperty ZFailStencilOpBackIdx { get { return m_zFailStencilOpBackIdx; } }
+
+
+ public int ReferenceValue
+ {
+ set
+ {
+ m_reference.IntValue = value;
+ m_reference.Active = false;
+ }
+ get
+ {
+ return m_reference.IntValue;
+ }
+ }
+
+ public int ReadMaskValue
+ {
+ set
+ {
+ m_readMask.IntValue = value;
+ m_reference.Active = false;
+ }
+ get
+ {
+ return m_readMask.IntValue;
+ }
+ }
+
+ public int WriteMaskValue
+ {
+ set
+ {
+ m_writeMask.IntValue = value;
+ m_writeMask.Active = false;
+ }
+ get
+ {
+ return m_writeMask.IntValue;
+ }
+ }
+
+ public int ComparisonFunctionIdxValue
+ {
+ set
+ {
+ m_comparisonFunctionFrontIdx.IntValue = value;
+ m_comparisonFunctionFrontIdx.Active = false;
+ }
+ get
+ {
+ return m_comparisonFunctionFrontIdx.IntValue;
+ }
+ }
+
+ public int ComparisonFunctionBackIdxValue
+ {
+ set
+ {
+ m_comparisonFunctionBackIdx.IntValue = value;
+ m_comparisonFunctionBackIdx.Active = false;
+ }
+ get
+ {
+ return m_comparisonFunctionBackIdx.IntValue;
+ }
+ }
+
+ public int PassStencilOpIdxValue
+ {
+ set
+ {
+ m_passStencilOpFrontIdx.IntValue = value;
+ m_passStencilOpFrontIdx.Active = false;
+ }
+ get
+ {
+ return m_passStencilOpFrontIdx.IntValue;
+ }
+ }
+
+ public int PassStencilOpBackIdxValue
+ {
+ set
+ {
+ m_passStencilOpBackIdx.IntValue = value;
+ m_passStencilOpBackIdx.Active = false;
+ }
+ get
+ {
+ return m_passStencilOpBackIdx.IntValue;
+ }
+ }
+
+ public int FailStencilOpIdxValue
+ {
+ set
+ {
+ m_failStencilOpFrontIdx.IntValue = value;
+ m_failStencilOpFrontIdx.Active = false;
+ }
+ get
+ {
+ return m_failStencilOpFrontIdx.IntValue;
+ }
+ }
+ public int FailStencilOpBackIdxValue
+ {
+ set
+ {
+ m_failStencilOpBackIdx.IntValue = value;
+ m_failStencilOpBackIdx.Active = false;
+ }
+ get
+ {
+ return m_failStencilOpBackIdx.IntValue;
+ }
+ }
+
+ public int ZFailStencilOpIdxValue
+ {
+ set
+ {
+ m_zFailStencilOpFrontIdx.IntValue = value;
+ m_zFailStencilOpFrontIdx.Active = false;
+ }
+ get
+ {
+ return m_zFailStencilOpFrontIdx.IntValue;
+ }
+ }
+
+ public int ZFailStencilOpBackIdxValue
+ {
+ set
+ {
+ m_zFailStencilOpBackIdx.IntValue = value;
+ m_zFailStencilOpBackIdx.Active = false;
+ }
+ get
+ {
+ return m_zFailStencilOpBackIdx.IntValue;
+ }
+ }
+ }
+}
diff --git a/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta
new file mode 100644
index 00000000..552dbaf7
--- /dev/null
+++ b/Assets/AmplifyShaderEditor/Plugins/Editor/Templates/TemplatesStencilBufferModule.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fa41b984209fa624aa1fdea5949d9d59
+timeCreated: 1511548974
+licenseType: Store
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: