| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990 | // Amplify Shader Editor - Visual Shader Editing Tool// Copyright (c) Amplify Creations, Lda <info@amplify.pt>using UnityEngine;using UnityEditor;using System;namespace AmplifyShaderEditor{	[Serializable]	//[NodeAttributes( "Texture Array", "Textures", "Texture Array fetches a texture from a texture2DArray asset file given a index value", KeyCode.None, true, 0, int.MaxValue, typeof( Texture2DArray ) )]	[NodeAttributes( "[Old]Texture Array", "Textures", "Texture Array fetches a texture from a texture2DArray asset file given a index value", null, KeyCode.None, true, true, "SamplerNode", typeof( SamplerNode ) )]	public class TextureArrayNode : PropertyNode	{		[SerializeField]		private Texture2DArray m_defaultTextureArray;		[SerializeField]		private Texture2DArray m_materialTextureArray;		[SerializeField]		private TexReferenceType m_referenceType = TexReferenceType.Object;		[SerializeField]		private int m_uvSet = 0;		[SerializeField]		private MipType m_mipMode = MipType.Auto;		private readonly string[] m_mipOptions = { "Auto", "Mip Level", "Derivative" };		private TextureArrayNode m_referenceSampler = null;		[SerializeField]		private int m_referenceArrayId = -1;		[SerializeField]		private int m_referenceNodeId = -1;		[SerializeField]		private bool m_autoUnpackNormals = false;		private InputPort m_texPort;		private InputPort m_uvPort;		private InputPort m_indexPort;		private InputPort m_lodPort;		private InputPort m_normalPort;		private InputPort m_ddxPort;		private InputPort m_ddyPort;		private OutputPort m_colorPort;		private const string AutoUnpackNormalsStr = "Normal";		private const string NormalScaleStr = "Scale";		private string m_labelText = "None (Texture2DArray)";		private readonly Color ReferenceHeaderColor = new Color( 2.66f, 1.02f, 0.6f, 1.0f );		private int m_cachedUvsId = -1;		private int m_cachedSamplerId = -1;		private int m_texConnectedId = -1;		private int m_cachedUnpackId = -1;		private int m_cachedLodId = -1;		private Rect m_iconPos;		private bool m_isEditingPicker;		private bool m_linearTexture;		protected bool m_drawPicker;		private ReferenceState m_state = ReferenceState.Self;		private ParentNode m_previewTextProp = null;		protected override void CommonInit( int uniqueId )		{			base.CommonInit( uniqueId );			AddOutputColorPorts( "RGBA" );			m_colorPort = m_outputPorts[ 0 ];			AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex", -1, MasterNodePortCategory.Fragment, 6 );			AddInputPort( WirePortDataType.FLOAT2, false, "UV", -1, MasterNodePortCategory.Fragment, 0 );			AddInputPort( WirePortDataType.FLOAT, false, "Index", -1, MasterNodePortCategory.Fragment, 1 );			AddInputPort( WirePortDataType.FLOAT, false, "Level", -1, MasterNodePortCategory.Fragment, 2 );			AddInputPort( WirePortDataType.FLOAT, false, NormalScaleStr, -1, MasterNodePortCategory.Fragment, 3 );			AddInputPort( WirePortDataType.FLOAT2, false, "DDX", -1, MasterNodePortCategory.Fragment, 4 );			AddInputPort( WirePortDataType.FLOAT2, false, "DDY", -1, MasterNodePortCategory.Fragment, 5 );			m_inputPorts[ 2 ].AutoDrawInternalData = true;			m_texPort = m_inputPorts[ 0 ];			m_uvPort = m_inputPorts[ 1 ];			m_indexPort = m_inputPorts[ 2 ];			m_lodPort = m_inputPorts[ 3 ];			m_lodPort.Visible = false;			m_normalPort = m_inputPorts[ 4 ];			m_normalPort.Visible = m_autoUnpackNormals;			m_normalPort.FloatInternalData = 1.0f;			m_ddxPort = m_inputPorts[ 5 ];			m_ddxPort.Visible = false;			m_ddyPort = m_inputPorts[ 6 ];			m_ddyPort.Visible = false;			m_insideSize.Set( 128, 128 + 5 );			m_drawPrecisionUI = false;			m_currentParameterType = PropertyType.Property;			m_availableAttribs.Add( new PropertyAttributes( "No Scale Offset", "[NoScaleOffset]" ) );			m_freeType = false;			m_showPreview = true;			m_drawPreviewExpander = false;			m_drawPreview = false;			m_drawPicker = true;			m_customPrefix = "Texture Array ";			m_selectedLocation = PreviewLocation.TopCenter;			m_previewShaderGUID = "2e6d093df2d289f47b827b36efb31a81";			m_showAutoRegisterUI = false;		}		public override void SetPreviewInputs()		{			base.SetPreviewInputs();			if( m_cachedUvsId == -1 )				m_cachedUvsId = Shader.PropertyToID( "_CustomUVs" );			if( m_cachedSamplerId == -1 )				m_cachedSamplerId = Shader.PropertyToID( "_Sampler" );			if( m_texConnectedId == -1 )				m_texConnectedId = Shader.PropertyToID( "_TexConnected" );			if( m_cachedUnpackId == -1 )				m_cachedUnpackId = Shader.PropertyToID( "_Unpack" );			if( m_cachedLodId == -1 )				m_cachedLodId = Shader.PropertyToID( "_LodType" );			PreviewMaterial.SetFloat( m_cachedLodId, ( m_mipMode == MipType.MipLevel ? 1 : 0 ) );			PreviewMaterial.SetFloat( m_cachedUnpackId, m_autoUnpackNormals ? 1 : 0 );			if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null )			{				if( (ParentNode)m_referenceSampler != m_referenceSampler.PreviewTextProp )				{					PreviewMaterial.SetInt( m_texConnectedId, 1 );					PreviewMaterial.SetTexture( "_G", m_referenceSampler.PreviewTextProp.PreviewTexture );				}				else				{					PreviewMaterial.SetInt( m_texConnectedId, 0 );					PreviewMaterial.SetTexture( m_cachedSamplerId, m_referenceSampler.TextureArray );				}			}			else if( m_texPort.IsConnected )			{				PreviewMaterial.SetInt( m_texConnectedId, 1 );			}			else			{				PreviewMaterial.SetInt( m_texConnectedId, 0 );				PreviewMaterial.SetTexture( m_cachedSamplerId, TextureArray );			}			PreviewMaterial.SetFloat( m_cachedUvsId, ( m_uvPort.IsConnected ? 1 : 0 ) );		}		protected override void OnUniqueIDAssigned()		{			base.OnUniqueIDAssigned();			if( m_referenceType == TexReferenceType.Object )			{				UIUtils.RegisterTextureArrayNode( this );				UIUtils.RegisterPropertyNode( this );			}			if( UniqueId > -1 )				ContainerGraph.TextureArrayNodes.OnReorderEventComplete += OnReorderEventComplete;		}		private void OnReorderEventComplete()		{			if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null )			{				m_referenceArrayId = ContainerGraph.TextureArrayNodes.GetNodeRegisterIdx( m_referenceSampler.UniqueId );			}		}		new void ShowDefaults()		{			m_uvSet = EditorGUILayoutIntPopup( Constants.AvailableUVSetsLabel, m_uvSet, Constants.AvailableUVSetsStr, Constants.AvailableUVSets );			MipType newMipMode = (MipType)EditorGUILayoutPopup( "Mip Mode", (int)m_mipMode, m_mipOptions );			if( newMipMode != m_mipMode )			{				m_mipMode = newMipMode;			}			switch( m_mipMode )			{				case MipType.Auto:				m_lodPort.Visible = false;				m_ddxPort.Visible = false;				m_ddyPort.Visible = false;				break;				case MipType.MipLevel:				m_lodPort.Visible = true;				m_ddxPort.Visible = false;				m_ddyPort.Visible = false;				break;				case MipType.MipBias:				case MipType.Derivative:				m_ddxPort.Visible = true;				m_ddyPort.Visible = true;				m_lodPort.Visible = false;				break;			}			if( m_ddxPort.Visible )			{				EditorGUILayout.HelpBox( "Warning: Derivative Mip Mode only works on some platforms (D3D11 XBOXONE GLES3 GLCORE)", MessageType.Warning );			}			if( !m_lodPort.IsConnected && m_lodPort.Visible )			{				m_lodPort.FloatInternalData = EditorGUILayoutFloatField( "Mip Level", m_lodPort.FloatInternalData );			}			if( !m_indexPort.IsConnected )			{				m_indexPort.FloatInternalData = EditorGUILayoutFloatField( "Index", m_indexPort.FloatInternalData );			}		}		public override void DrawMainPropertyBlock()		{			EditorGUI.BeginChangeCheck();			m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels );			if( EditorGUI.EndChangeCheck() )			{				if( m_referenceType == TexReferenceType.Object )				{					UIUtils.RegisterTextureArrayNode( this );					UIUtils.RegisterPropertyNode( this );					SetTitleText( m_propertyInspectorName );					SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) );					m_referenceArrayId = -1;					m_referenceNodeId = -1;					m_referenceSampler = null;				}				else				{					UIUtils.UnregisterTextureArrayNode( this );					UIUtils.UnregisterPropertyNode( this );				}				UpdateHeaderColor();			}			if( m_referenceType == TexReferenceType.Object )			{				EditorGUI.BeginChangeCheck();				base.DrawMainPropertyBlock();				if( EditorGUI.EndChangeCheck() )				{					OnPropertyNameChanged();				}			}			else			{				string[] arr = UIUtils.TextureArrayNodeArr();				bool guiEnabledBuffer = GUI.enabled;				if( arr != null && arr.Length > 0 )				{					GUI.enabled = true;				}				else				{					m_referenceArrayId = -1;					GUI.enabled = false;				}				m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr );				GUI.enabled = guiEnabledBuffer;				ShowDefaults();				DrawSamplerOptions();			}		}		public override void OnPropertyNameChanged()		{			base.OnPropertyNameChanged();			UIUtils.UpdateTextureArrayDataNode( UniqueId, PropertyInspectorName );		}		public override void DrawSubProperties()		{			ShowDefaults();			DrawSamplerOptions();			EditorGUI.BeginChangeCheck();			m_defaultTextureArray = EditorGUILayoutObjectField( Constants.DefaultValueLabel, m_defaultTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray;			if( EditorGUI.EndChangeCheck() )			{				CheckTextureImporter( true );				SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) );			}		}		public override void DrawMaterialProperties()		{			ShowDefaults();			DrawSamplerOptions();			EditorGUI.BeginChangeCheck();			m_materialTextureArray = EditorGUILayoutObjectField( Constants.MaterialValueLabel, m_materialTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray;			if( EditorGUI.EndChangeCheck() )			{				CheckTextureImporter( true );				SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) );				m_requireMaterialUpdate = true;			}		}		public void DrawSamplerOptions()		{			EditorGUI.BeginChangeCheck();			bool autoUnpackNormals = EditorGUILayoutToggle( "Normal Map", m_autoUnpackNormals );			if( EditorGUI.EndChangeCheck() )			{				if( m_autoUnpackNormals != autoUnpackNormals )				{					AutoUnpackNormals = autoUnpackNormals;					ConfigureInputPorts();					ConfigureOutputPorts();				}			}			if( m_autoUnpackNormals && !m_normalPort.IsConnected )			{				m_normalPort.FloatInternalData = EditorGUILayoutFloatField( NormalScaleStr, m_normalPort.FloatInternalData );			}		}		public void ConfigureInputPorts()		{			m_normalPort.Visible = AutoUnpackNormals;			m_sizeIsDirty = true;		}		public void ConfigureOutputPorts()		{			m_outputPorts[ m_colorPort.PortId + 4 ].Visible = !AutoUnpackNormals;			if( !AutoUnpackNormals )			{				m_colorPort.ChangeProperties( "RGBA", WirePortDataType.FLOAT4, false );				m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "R", WirePortDataType.FLOAT, false );				m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "G", WirePortDataType.FLOAT, false );				m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "B", WirePortDataType.FLOAT, false );				m_outputPorts[ m_colorPort.PortId + 4 ].ChangeProperties( "A", WirePortDataType.FLOAT, false );			}			else			{				m_colorPort.ChangeProperties( "XYZ", WirePortDataType.FLOAT3, false );				m_outputPorts[ m_colorPort.PortId + 1 ].ChangeProperties( "X", WirePortDataType.FLOAT, false );				m_outputPorts[ m_colorPort.PortId + 2 ].ChangeProperties( "Y", WirePortDataType.FLOAT, false );				m_outputPorts[ m_colorPort.PortId + 3 ].ChangeProperties( "Z", WirePortDataType.FLOAT, false );			}			m_sizeIsDirty = true;		}		public virtual void CheckTextureImporter( bool additionalCheck )		{			m_requireMaterialUpdate = true;			Texture2DArray texture = m_materialMode ? m_materialTextureArray : m_defaultTextureArray;			UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath( AssetDatabase.GetAssetPath( texture ), typeof( UnityEngine.Object ) );			if( obj != null )			{				SerializedObject serializedObject = new UnityEditor.SerializedObject( obj );				if( serializedObject != null )				{					SerializedProperty colorSpace = serializedObject.FindProperty( "m_ColorSpace" );					m_linearTexture = ( colorSpace.intValue == 0 );				}			}		}		void UpdateHeaderColor()		{			m_headerColorModifier = ( m_referenceType == TexReferenceType.Object ) ? Color.white : ReferenceHeaderColor;		}		public override void DrawGUIControls( DrawInfo drawInfo )		{			base.DrawGUIControls( drawInfo );			if( !( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp || drawInfo.CurrentEventType == EventType.ExecuteCommand || drawInfo.CurrentEventType == EventType.DragPerform ) )				return;			bool insideBox = m_previewRect.Contains( drawInfo.MousePosition );			if( insideBox )			{				m_isEditingPicker = true;			}			else if( m_isEditingPicker && !insideBox && drawInfo.CurrentEventType != EventType.ExecuteCommand )			{				GUI.FocusControl( null );				m_isEditingPicker = false;			}			if( m_state != ReferenceState.Self && drawInfo.CurrentEventType == EventType.MouseDown && m_previewRect.Contains( drawInfo.MousePosition ) )			{				UIUtils.FocusOnNode( m_previewTextProp, 1, true );				Event.current.Use();			}		}		public override void OnNodeLayout( DrawInfo drawInfo )		{			base.OnNodeLayout( drawInfo );			if( m_drawPreview )			{				m_iconPos = m_globalPosition;				m_iconPos.width = 19 * drawInfo.InvertedZoom;				m_iconPos.height = 19 * drawInfo.InvertedZoom;				m_iconPos.y += 10 * drawInfo.InvertedZoom;				m_iconPos.x += m_globalPosition.width - m_iconPos.width - 5 * drawInfo.InvertedZoom;			}			bool instanced = CheckReference();			if( instanced )			{				m_state = ReferenceState.Instance;				m_previewTextProp = m_referenceSampler;			}			else if( m_texPort.IsConnected )			{				m_state = ReferenceState.Connected;				m_previewTextProp = m_texPort.GetOutputNode( 0 ) as ParentNode;			}			else			{				m_state = ReferenceState.Self;				m_previewTextProp = this;			}			if( m_previewTextProp == null )				m_previewTextProp = this;		}		public override void Draw( DrawInfo drawInfo )		{			base.Draw( drawInfo );			if( m_isEditingPicker && m_drawPicker )			{				Rect hitRect = m_previewRect;				hitRect.height = 14 * drawInfo.InvertedZoom;				hitRect.y = m_previewRect.yMax - hitRect.height;				hitRect.width = 4 * 14 * drawInfo.InvertedZoom;				bool restoreMouse = false;				if( Event.current.type == EventType.MouseDown && hitRect.Contains( drawInfo.MousePosition ) )				{					restoreMouse = true;					Event.current.type = EventType.Ignore;				}				EditorGUI.BeginChangeCheck();				m_colorBuffer = GUI.color;				GUI.color = Color.clear;				if( m_materialMode )					m_materialTextureArray = EditorGUIObjectField( m_previewRect, m_materialTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray;				else					m_defaultTextureArray = EditorGUIObjectField( m_previewRect, m_defaultTextureArray, typeof( Texture2DArray ), false ) as Texture2DArray;				GUI.color = m_colorBuffer;				if( EditorGUI.EndChangeCheck() )				{					PreviewIsDirty = true;					CheckTextureImporter( true );					SetTitleText( PropertyInspectorName );					SetAdditonalTitleText( string.Format( Constants.PropertyValueLabel, GetPropertyValStr() ) );					ConfigureInputPorts();					ConfigureOutputPorts();					BeginDelayedDirtyProperty();					m_requireMaterialUpdate = true;				}				if( restoreMouse )				{					Event.current.type = EventType.MouseDown;				}				if( ( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp ) )					DrawPreviewMaskButtonsLayout( drawInfo, m_previewRect );			}			if( drawInfo.CurrentEventType != EventType.Repaint )				return;			switch( m_state )			{				default:				case ReferenceState.Self:				if( drawInfo.CurrentEventType == EventType.Repaint )				{					m_drawPreview = false;					m_drawPicker = true;					DrawTexturePicker( drawInfo );				}				break;				case ReferenceState.Connected:				if( drawInfo.CurrentEventType == EventType.Repaint )				{					m_drawPreview = true;					m_drawPicker = false;					if( m_previewTextProp != null )					{						SetTitleTextOnCallback( m_previewTextProp.TitleContent.text, ( instance, newTitle ) => instance.TitleContent.text = newTitle + " (Input)" );						SetAdditonalTitleText( m_previewTextProp.AdditonalTitleContent.text );					}					// Draw chain lock					GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) );					// Draw frame around preview					GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) );				}				break;				case ReferenceState.Instance:				{					m_drawPreview = true;					m_drawPicker = false;					if( m_referenceSampler != null )					{						SetTitleTextOnCallback( m_referenceSampler.PreviewTextProp.TitleContent.text, ( instance, newTitle ) => instance.TitleContent.text = newTitle + Constants.InstancePostfixStr );						SetAdditonalTitleText( m_referenceSampler.PreviewTextProp.AdditonalTitleContent.text );					}					// Draw chain lock					GUI.Label( m_iconPos, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon ) );					// Draw frame around preview					GUI.Label( m_previewRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) );				}				break;			}		}		protected void DrawTexturePicker( DrawInfo drawInfo )		{			Rect newRect = m_previewRect;			Texture2DArray currentValue = m_materialMode ? m_materialTextureArray : m_defaultTextureArray;			if( currentValue == null )				GUI.Label( newRect, string.Empty, UIUtils.ObjectFieldThumb );			else				DrawPreview( drawInfo, m_previewRect );			if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 )			{				Rect butRect = m_previewRect;				butRect.y -= 1;				butRect.x += 1;				Rect smallButton = newRect;				smallButton.height = 14 * drawInfo.InvertedZoom;				smallButton.y = newRect.yMax - smallButton.height - 2;				smallButton.width = 40 * drawInfo.InvertedZoom;				smallButton.x = newRect.xMax - smallButton.width - 2;				if( currentValue == null )				{					GUI.Label( newRect, m_labelText, UIUtils.ObjectFieldThumbOverlay );				}				else				{					DrawPreviewMaskButtonsRepaint( drawInfo, butRect );				}				GUI.Label( smallButton, "Select", UIUtils.GetCustomStyle( CustomStyle.SamplerButton ) );			}			GUI.Label( newRect, string.Empty, UIUtils.GetCustomStyle( CustomStyle.SamplerFrame ) );		}		public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )		{			if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) )				return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) );			OnPropertyNameChanged();			if( CheckReference() )			{				OrderIndex = m_referenceSampler.RawOrderIndex;				OrderIndexOffset = m_referenceSampler.OrderIndexOffset;			}			bool isVertex = ( dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation );			bool instanced = false;			if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null )				instanced = true;			if( instanced )			{				if( !m_referenceSampler.TexPort.IsConnected )					base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );			}			else if( !m_texPort.IsConnected )				base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );			string level = string.Empty;			if( m_lodPort.Visible )			{				level = m_lodPort.GeneratePortInstructions( ref dataCollector );			}			if( isVertex && !m_lodPort.Visible )				level = "0";			string propertyName = string.Empty;			if( instanced )			{				if( m_referenceSampler.TexPort.IsConnected )					propertyName = m_referenceSampler.TexPort.GeneratePortInstructions( ref dataCollector );				else					propertyName = m_referenceSampler.PropertyName;			}			else if( m_texPort.IsConnected )				propertyName = m_texPort.GeneratePortInstructions( ref dataCollector );			else				propertyName = PropertyName;			string uvs = string.Empty;			if( m_uvPort.IsConnected )			{				uvs = m_uvPort.GeneratePortInstructions( ref dataCollector );			}			else			{				if( dataCollector.IsTemplate )				{					uvs = dataCollector.TemplateDataCollectorInstance.GetTextureCoord( m_uvSet, propertyName/*( instanced ? m_referenceSampler.PropertyName : PropertyName )*/, UniqueId, CurrentPrecisionType );				}				else				{					if( isVertex )						uvs = TexCoordVertexDataNode.GenerateVertexUVs( ref dataCollector, UniqueId, m_uvSet, propertyName );					else						uvs = TexCoordVertexDataNode.GenerateFragUVs( ref dataCollector, UniqueId, m_uvSet, propertyName );				}			}			string index = m_indexPort.GeneratePortInstructions( ref dataCollector );			string result = string.Empty;			if( dataCollector.IsTemplate && dataCollector.IsSRP )			{				//CAREFUL mipbias here means derivative (this needs index changes)				//TODO: unity now supports bias as well				if( m_mipMode == MipType.MipBias )				{					GeneratorUtils.AddCustomArraySamplingMacros( ref dataCollector );					result = propertyName + ".SampleGrad(sampler" + propertyName + ", float3(" + uvs + ", " + index + "), " + m_ddxPort.GeneratePortInstructions( ref dataCollector ) + ", " + m_ddyPort.GeneratePortInstructions( ref dataCollector ) + ");";				}				else if( m_lodPort.Visible || isVertex )				{					result = "SAMPLE_TEXTURE2D_ARRAY_LOD(" + propertyName + ", sampler" + propertyName + ", " + uvs + ", " + index + ", " + level + " )";				}				else				{					result = "SAMPLE_TEXTURE2D_ARRAY(" + propertyName + ", sampler" + propertyName + ", " + uvs + ", " + index + " )";				}			}			else			{				//CAREFUL mipbias here means derivative (this needs index changes)				if( m_mipMode == MipType.MipBias )				{					GeneratorUtils.AddCustomArraySamplingMacros( ref dataCollector );					result = "ASE_SAMPLE_TEX2DARRAY_GRAD(" + propertyName + ", float3(" + uvs + ", " + index + "), " + m_ddxPort.GeneratePortInstructions( ref dataCollector ) + ", " + m_ddyPort.GeneratePortInstructions( ref dataCollector ) + " )";				}				else if( m_lodPort.Visible || isVertex )				{					result = "UNITY_SAMPLE_TEX2DARRAY_LOD(" + propertyName + ", float3(" + uvs + ", " + index + "), " + level + " )";				}				else				{					result = "UNITY_SAMPLE_TEX2DARRAY" + ( m_lodPort.Visible || isVertex ? "_LOD" : "" ) + "(" + propertyName + ", float3(" + uvs + ", " + index + ") " + ( m_lodPort.Visible || isVertex ? ", " + level : "" ) + " )";				}			}			if( m_autoUnpackNormals )			{				bool isScaledNormal = false;				if( m_normalPort.IsConnected )				{					isScaledNormal = true;				}				else				{					if( m_normalPort.FloatInternalData != 1 )					{						isScaledNormal = true;					}				}				string scaleValue = isScaledNormal ? m_normalPort.GeneratePortInstructions( ref dataCollector ) : "1.0";				result = GeneratorUtils.GenerateUnpackNormalStr( ref dataCollector, CurrentPrecisionType, UniqueId, OutputId, result, isScaledNormal, scaleValue, UnpackInputMode.Tangent );				if( isScaledNormal && ( !dataCollector.IsTemplate || !dataCollector.IsSRP ) )				{					dataCollector.AddToIncludes( UniqueId, Constants.UnityStandardUtilsLibFuncs );				}			}			RegisterLocalVariable( 0, result, ref dataCollector, "texArray" + OutputId );			return GetOutputVectorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) );		}		public override string PropertyName		{			get			{				if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null )					return m_referenceSampler.PropertyName;				else					return base.PropertyName;			}		}		public override string PropertyInspectorName		{			get			{				if( m_referenceType == TexReferenceType.Instance && m_referenceSampler != null )					return m_referenceSampler.PropertyInspectorName;				else					return base.PropertyInspectorName;			}		}		public override string GetPropertyValue()		{			return PropertyAttributes + PropertyName + "(\"" + PropertyInspectorName + "\", 2DArray ) = \"\" {}";		}		public override bool GetUniformData( out string dataType, out string dataName, ref bool fullValue )		{			MasterNode currMasterNode = ( m_containerGraph.CurrentMasterNode != null ) ? m_containerGraph.CurrentMasterNode : m_containerGraph.ParentWindow.OutsideGraph.CurrentMasterNode;			if( currMasterNode != null && currMasterNode.CurrentDataCollector.IsTemplate && currMasterNode.CurrentDataCollector.IsSRP )			{				dataType = "TEXTURE2D_ARRAY( " + PropertyName + "";				dataName = ");\nuniform SAMPLER( sampler" + PropertyName + " )";				return true;			}			dataType = "UNITY_DECLARE_TEX2DARRAY(";			dataName = PropertyName + " )";			return true;		}		public override void ReadFromString( ref string[] nodeParams )		{			base.ReadFromString( ref nodeParams );			string textureName = GetCurrentParam( ref nodeParams );			m_defaultTextureArray = AssetDatabase.LoadAssetAtPath<Texture2DArray>( textureName );			m_uvSet = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) );			m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			if( UIUtils.CurrentShaderVersion() > 3202 )				m_mipMode = (MipType)Enum.Parse( typeof( MipType ), GetCurrentParam( ref nodeParams ) );			if( UIUtils.CurrentShaderVersion() > 5105 )				m_autoUnpackNormals = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );			if( m_referenceType == TexReferenceType.Instance )			{				UIUtils.UnregisterTextureArrayNode( this );				UIUtils.UnregisterPropertyNode( this );			}			ConfigureInputPorts();			ConfigureOutputPorts();			m_lodPort.Visible = ( m_mipMode == MipType.MipLevel );			m_ddxPort.Visible = ( m_mipMode == MipType.MipBias ); //not really bias, it's derivative			m_ddyPort.Visible = ( m_mipMode == MipType.MipBias ); //not really bias, it's derivative			UpdateHeaderColor();			if( m_defaultTextureArray )			{				m_materialTextureArray = m_defaultTextureArray;			}			if( !m_isNodeBeingCopied && m_referenceType == TexReferenceType.Object )			{				ContainerGraph.TextureArrayNodes.UpdateDataOnNode( UniqueId, DataToArray );			}		}		public override void RefreshExternalReferences()		{			base.RefreshExternalReferences();			m_referenceSampler = UIUtils.GetNode( m_referenceNodeId ) as TextureArrayNode;			m_referenceArrayId = UIUtils.GetTextureArrayNodeRegisterId( m_referenceNodeId );			OnPropertyNameChanged();		}		public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )		{			base.WriteToString( ref nodeInfo, ref connectionsInfo );			IOUtils.AddFieldValueToString( ref nodeInfo, ( m_defaultTextureArray != null ) ? AssetDatabase.GetAssetPath( m_defaultTextureArray ) : Constants.NoStringValue );			IOUtils.AddFieldValueToString( ref nodeInfo, m_uvSet.ToString() );			IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType );			IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceSampler != null ) ? m_referenceSampler.UniqueId : -1 ) );			IOUtils.AddFieldValueToString( ref nodeInfo, m_mipMode );			IOUtils.AddFieldValueToString( ref nodeInfo, m_autoUnpackNormals );		}		public override void ReadAdditionalClipboardData( ref string[] nodeParams )		{			base.ReadAdditionalClipboardData( ref nodeParams );			string textureName = GetCurrentParam( ref nodeParams );			m_materialTextureArray = AssetDatabase.LoadAssetAtPath<Texture2DArray>( textureName );		}		public override void WriteAdditionalClipboardData( ref string nodeInfo )		{			base.WriteAdditionalClipboardData( ref nodeInfo );			IOUtils.AddFieldValueToString( ref nodeInfo, ( m_materialTextureArray != null ) ? AssetDatabase.GetAssetPath( m_materialTextureArray ) : Constants.NoStringValue );		}		public override void UpdateMaterial( Material mat )		{			base.UpdateMaterial( mat );			if( UIUtils.IsProperty( m_currentParameterType ) && !InsideShaderFunction && m_referenceType == TexReferenceType.Object )			{				OnPropertyNameChanged();				if( mat.HasProperty( PropertyName ) )				{					mat.SetTexture( PropertyName, m_materialTextureArray );				}			}		}		public override void SetMaterialMode( Material mat, bool fetchMaterialValues )		{			base.SetMaterialMode( mat, fetchMaterialValues );			if( fetchMaterialValues && m_materialMode && UIUtils.IsProperty( m_currentParameterType ) )			{				if( mat.HasProperty( PropertyName ) )				{					m_materialTextureArray = (Texture2DArray)mat.GetTexture( PropertyName );					if( m_materialTextureArray == null )						m_materialTextureArray = m_defaultTextureArray;				}			}		}		public override void ForceUpdateFromMaterial( Material material )		{			if( UIUtils.IsProperty( m_currentParameterType ) && material.HasProperty( PropertyName ) )			{				m_materialTextureArray = (Texture2DArray)material.GetTexture( PropertyName );				if( m_materialTextureArray == null )					m_materialTextureArray = m_defaultTextureArray;				PreviewIsDirty = true;			}		}		public override bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol )		{			if( m_defaultTextureArray != null )			{				defaultCol.AddValue( PropertyName, m_defaultTextureArray );			}			return true;		}		public override string GetPropertyValStr()		{			return m_materialMode ? ( m_materialTextureArray != null ? m_materialTextureArray.name : IOUtils.NO_TEXTURES ) : ( m_defaultTextureArray != null ? m_defaultTextureArray.name : IOUtils.NO_TEXTURES );		}		public bool CheckReference()		{			if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 )			{				m_referenceSampler = UIUtils.GetTextureArrayNode( m_referenceArrayId );				if( m_referenceSampler == null )				{					m_texPort.Locked = false;					m_referenceArrayId = -1;				}				else					m_texPort.Locked = true;			}			else			{				m_texPort.Locked = false;			}			return m_referenceSampler != null;		}		public override void SetupFromCastObject( UnityEngine.Object obj )		{			base.SetupFromCastObject( obj );			SetupFromObject( obj );		}		public override void OnObjectDropped( UnityEngine.Object obj )		{			SetupFromObject( obj );		}		private void SetupFromObject( UnityEngine.Object obj )		{			if( m_materialMode )				m_materialTextureArray = obj as Texture2DArray;			else				m_defaultTextureArray = obj as Texture2DArray;		}		public Texture2DArray TextureArray { get { return ( m_materialMode ? m_materialTextureArray : m_defaultTextureArray ); } }		public bool IsLinearTexture { get { return m_linearTexture; } }		public bool AutoUnpackNormals		{			get { return m_autoUnpackNormals; }			set { m_autoUnpackNormals = value; }		}		public override string DataToArray { get { return PropertyInspectorName; } }		public override void Destroy()		{			base.Destroy();			m_defaultTextureArray = null;			m_materialTextureArray = null;			m_texPort = null;			m_uvPort = null;			m_indexPort = null;			m_lodPort = null;			m_normalPort = null;			m_ddxPort = null;			m_ddyPort = null;			if( m_referenceType == TexReferenceType.Object )			{				UIUtils.UnregisterTextureArrayNode( this );				UIUtils.UnregisterPropertyNode( this );			}			if( UniqueId > -1 )				ContainerGraph.TextureArrayNodes.OnReorderEventComplete -= OnReorderEventComplete;		}		public ParentNode PreviewTextProp { get { return m_previewTextProp; } }		public InputPort TexPort { get { return m_texPort; } }	}}
 |