| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 | // Amplify Shader Editor - Visual Shader Editing Tool// Copyright (c) Amplify Creations, Lda <info@amplify.pt>//// Custom Node Global Array// Donated by Johann van Berkelusing System;using UnityEngine;using UnityEditor;namespace AmplifyShaderEditor{	[Serializable]	[NodeAttributes( "Global Array" , "Constants And Properties" , "The node returns a value from a global array, which you can configure by entering the name of the array in the node's settings." , null , KeyCode.None , true , false , null , null , "Johann van Berkel" )]	public sealed class GlobalArrayNode : ParentNode	{		private const string DefaultArrayName = "MyGlobalArray";		private const string TypeStr = "Type";		private const string AutoRangeCheckStr = "Range Check";		private const string ArrayFormatStr = "{0}[{1}]";		private const string JaggedArrayFormatStr = "{0}[{1}][{2}]";		private const string IsJaggedStr = "Is Jagged";		private const string AutoRegisterStr = "Auto-Register";		private readonly string[] AvailableTypesLabel = { "Float" , "Color" , "Vector4" , "Matrix4x4" };		private readonly WirePortDataType[] AvailableTypesValues = { WirePortDataType.FLOAT , WirePortDataType.COLOR , WirePortDataType.FLOAT4 , WirePortDataType.FLOAT4x4 };		[SerializeField]		private string m_name = DefaultArrayName;		[SerializeField]		private int m_indexX = 0;		[SerializeField]		private int m_indexY = 0;		[SerializeField]		private int m_arrayLengthX = 1;		[SerializeField]		private int m_arrayLengthY = 1;		[SerializeField]		private int m_type = 0;		[SerializeField]		private bool m_autoRangeCheck = false;		[SerializeField]		private bool m_isJagged = false;		[SerializeField]		private bool m_autoRegister = false;		//////////////////////////////////////////////////////////////////		private readonly Color ReferenceHeaderColor = new Color( 0.6f , 3.0f , 1.25f , 1.0f );		[SerializeField]		private TexReferenceType m_referenceType = TexReferenceType.Object;		[SerializeField]		private int m_referenceArrayId = -1;		[SerializeField]		private int m_referenceNodeId = -1;		private GlobalArrayNode m_referenceNode = null;		private bool m_updated = false;		protected override void CommonInit( int uniqueId )		{			base.CommonInit( uniqueId );			AddInputPort( WirePortDataType.INT , false , "Index" , -1 , MasterNodePortCategory.Fragment , 0 );			AddInputPort( WirePortDataType.INT , false , "Index Y" , -1 , MasterNodePortCategory.Fragment , 2 );			AddInputPort( WirePortDataType.INT , false , "Array Length" , -1 , MasterNodePortCategory.Fragment , 1 );			AddInputPort( WirePortDataType.INT , false , "Array Length Y" , -1 , MasterNodePortCategory.Fragment , 3 );			AddOutputPort( WirePortDataType.FLOAT , "Out" );			m_textLabelWidth = 95;			m_autoWrapProperties = true;			SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) );			UpdatePorts();		}		protected override void OnUniqueIDAssigned()		{			base.OnUniqueIDAssigned();			UIUtils.CurrentWindow.OutsideGraph.GlobalArrayNodes.AddNode( this );		}		public override void Destroy()		{			base.Destroy();			UIUtils.CurrentWindow.OutsideGraph.GlobalArrayNodes.RemoveNode( this );		}		void UpdatePorts()		{			InputPort indexXPort = GetInputPortByUniqueId( 0 );			InputPort arrayLengthPortX = GetInputPortByUniqueId( 1 );			InputPort indexYPort = GetInputPortByUniqueId( 2 );			InputPort arrayLengthPortY = GetInputPortByUniqueId( 3 );			if( m_referenceType == TexReferenceType.Object )			{				m_headerColorModifier = Color.white;				SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) );				arrayLengthPortX.Visible = true;				if( m_isJagged )				{					indexXPort.Name = "Index X";					arrayLengthPortX.Name = "Array Length X";					indexYPort.Visible = true;					arrayLengthPortY.Visible = true;				}				else				{					indexXPort.Name = "Index";					arrayLengthPortX.Name = "Array Length";					indexYPort.Visible = false;					arrayLengthPortY.Visible = false;				}			}			else if( m_referenceNodeId > -1 )			{				m_headerColorModifier = ReferenceHeaderColor;				if( m_referenceNode == null )					m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode;				if( m_referenceNode != null )				{					SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_referenceNode.DataToArray ) );					arrayLengthPortX.Visible = false;					arrayLengthPortY.Visible = false;					if( m_referenceNode.IsJagged )					{						indexXPort.Name = "Index X";						indexYPort.Visible = true;					}					else					{						indexXPort.Name = "Index";						indexYPort.Visible = false;					}				}			}			m_sizeIsDirty = true;		}		void DrawObjectProperties()		{			EditorGUI.BeginChangeCheck();			m_name = EditorGUILayoutStringField( "Name" , m_name );			if( EditorGUI.EndChangeCheck() )			{				m_updated = true;				m_name = UIUtils.RemoveInvalidCharacters( m_name );				if( string.IsNullOrEmpty( m_name ) )					m_name = DefaultArrayName;				UIUtils.UpdateGlobalArrayDataNode( UniqueId , m_name );				SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) );			}			m_autoRegister = EditorGUILayoutToggle( AutoRegisterStr , m_autoRegister );			EditorGUI.BeginChangeCheck();			m_isJagged = EditorGUILayoutToggle( IsJaggedStr , m_isJagged );			if( EditorGUI.EndChangeCheck() )			{				m_updated = true;				UpdatePorts();			}			InputPort indexXPort = GetInputPortByUniqueId( 0 );			if( !indexXPort.IsConnected )			{				EditorGUI.BeginChangeCheck();				m_indexX = EditorGUILayoutIntField( indexXPort.Name , m_indexX );				if( EditorGUI.EndChangeCheck() )				{					m_indexX = Mathf.Clamp( m_indexX , 0 , ( ArrayLengthX - 1 ) );				}			}			if( m_isJagged )			{				InputPort indexYPort = GetInputPortByUniqueId( 2 );				if( !indexYPort.IsConnected )				{					EditorGUI.BeginChangeCheck();					m_indexY = EditorGUILayoutIntField( indexYPort.Name , m_indexY );					if( EditorGUI.EndChangeCheck() )					{						m_indexY = Mathf.Clamp( m_indexY , 0 , ( ArrayLengthY - 1 ) );					}				}			}			InputPort arrayLengthXPort = GetInputPortByUniqueId( 1 );			if( !arrayLengthXPort.IsConnected )			{				EditorGUI.BeginChangeCheck();				m_arrayLengthX = EditorGUILayoutIntField( arrayLengthXPort.Name , m_arrayLengthX );				if( EditorGUI.EndChangeCheck() )				{					m_arrayLengthX = Mathf.Max( 1 , m_arrayLengthX );				}			}			if( m_isJagged )			{				InputPort arrayLengthYPort = GetInputPortByUniqueId( 3 );				if( !arrayLengthYPort.IsConnected )				{					EditorGUI.BeginChangeCheck();					m_arrayLengthY = EditorGUILayoutIntField( arrayLengthYPort.Name , m_arrayLengthY );					if( EditorGUI.EndChangeCheck() )					{						m_arrayLengthY = Mathf.Max( 1 , m_arrayLengthY );					}				}			}			EditorGUI.BeginChangeCheck();			m_type = EditorGUILayoutPopup( TypeStr , m_type , AvailableTypesLabel );			if( EditorGUI.EndChangeCheck() )			{				m_outputPorts[ 0 ].ChangeType( (WirePortDataType)AvailableTypesValues[ m_type ] , false );			}			m_autoRangeCheck = EditorGUILayoutToggle( AutoRangeCheckStr , m_autoRangeCheck );		}		public override void OnNodeLayout( DrawInfo drawInfo )		{			base.OnNodeLayout( drawInfo );			m_updated = false;			if( m_referenceType == TexReferenceType.Instance )			{				if( m_referenceNodeId > -1 && m_referenceNode == null )				{					m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode;					if( m_referenceNode == null )					{						m_referenceNodeId = -1;					}				}				if( m_referenceNode != null && m_referenceNode.Updated )				{					UpdatePorts();				}			}		}		void DrawInstancedProperties()		{			string[] arr = UIUtils.GlobalArrayNodeArr();			bool guiEnabledBuffer = GUI.enabled;			if( arr != null && arr.Length > 0 )			{				GUI.enabled = true;			}			else			{				m_referenceArrayId = -1;				m_referenceNodeId = -1;				m_referenceNode = null;				GUI.enabled = false;			}			EditorGUI.BeginChangeCheck();			m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr , m_referenceArrayId , arr );			if( EditorGUI.EndChangeCheck() )			{				m_referenceNode = UIUtils.GetGlobalArrayNode( m_referenceArrayId );				if( m_referenceNode != null )				{					m_referenceNodeId = m_referenceNode.UniqueId;				}				UpdatePorts();			}			GUI.enabled = guiEnabledBuffer;			InputPort indexXPort = GetInputPortByUniqueId( 0 );			if( !indexXPort.IsConnected )			{				EditorGUI.BeginChangeCheck();				m_indexX = EditorGUILayoutIntField( indexXPort.Name , m_indexX );				if( EditorGUI.EndChangeCheck() )				{					m_indexX = Mathf.Clamp( m_indexX , 0 , ( ArrayLengthX - 1 ) );				}			}			if( m_isJagged )			{				InputPort indexYPort = GetInputPortByUniqueId( 2 );				if( !indexYPort.IsConnected )				{					EditorGUI.BeginChangeCheck();					m_indexY = EditorGUILayoutIntField( indexYPort.Name , m_indexY );					if( EditorGUI.EndChangeCheck() )					{						m_indexY = Mathf.Clamp( m_indexY , 0 , ( ArrayLengthY - 1 ) );					}				}			}		}		public override void DrawProperties()		{			EditorGUI.BeginChangeCheck();			m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr , (int)m_referenceType , Constants.ReferenceArrayLabels );			if( EditorGUI.EndChangeCheck() )			{				UpdatePorts();			}			if( m_referenceType == TexReferenceType.Object )				DrawObjectProperties();			else				DrawInstancedProperties();		}		public string GetArrayValue( string indexX , string indexY = null )		{			if( m_isJagged )				return string.Format( JaggedArrayFormatStr , m_name , indexX , indexY );			return string.Format( ArrayFormatStr , m_name , indexX );		}		public string GenerateInstancedShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar )		{			string result = string.Empty;			if( m_referenceNode != null )			{				InputPort indexXPort = GetInputPortByUniqueId( 0 );				if( m_referenceNode.IsJagged )				{					InputPort indexYPort = GetInputPortByUniqueId( 2 );					string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString();					string arrayIndexY = indexYPort.IsConnected ? indexYPort.GeneratePortInstructions( ref dataCollector ) : m_indexY.ToString();					result = m_referenceNode.GetArrayValue( arrayIndexX , arrayIndexY );				}				else				{					string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString();					result = m_referenceNode.GetArrayValue( arrayIndexX );				}			}			m_outputPorts[ 0 ].SetLocalValue( result , dataCollector.PortCategory );			return result;		}		public override string GenerateShaderForOutput( int outputId , ref MasterNodeDataCollector dataCollector , bool ignoreLocalvar )		{			if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) )				return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory );			if( m_referenceType == TexReferenceType.Instance )				return GenerateInstancedShaderForOutput( outputId , ref dataCollector , ignoreLocalvar );			string dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType , AvailableTypesValues[ m_type ] );			InputPort indexXPort = GetInputPortByUniqueId( 0 );			InputPort arrayLengthXPort = GetInputPortByUniqueId( 1 );			string result = string.Empty;			if( m_isJagged )			{				InputPort indexYPort = GetInputPortByUniqueId( 2 );				InputPort arrayLengthYPort = GetInputPortByUniqueId( 3 );				string arrayIndexX = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString();				string arrayLengthX = arrayLengthXPort.IsConnected ? arrayLengthXPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthX.ToString();				string arrayIndexY = indexYPort.IsConnected ? indexYPort.GeneratePortInstructions( ref dataCollector ) : m_indexY.ToString();				string arrayLengthY = arrayLengthYPort.IsConnected ? arrayLengthYPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthY.ToString();				dataCollector.AddToUniforms( UniqueId , dataType , string.Format( JaggedArrayFormatStr , m_name , arrayLengthX , arrayLengthY ) );				if( m_autoRangeCheck )				{					arrayIndexX = string.Format( "clamp({0},0,({1} - 1))" , arrayIndexX , arrayLengthX );					arrayIndexY = string.Format( "clamp({0},0,({1} - 1))" , arrayIndexY , arrayLengthY );				}				result = string.Format( JaggedArrayFormatStr , m_name , arrayIndexX , arrayIndexY );			}			else			{				string arrayIndex = indexXPort.IsConnected ? indexXPort.GeneratePortInstructions( ref dataCollector ) : m_indexX.ToString();				string arrayLength = arrayLengthXPort.IsConnected ? arrayLengthXPort.GeneratePortInstructions( ref dataCollector ) : ArrayLengthX.ToString();				dataCollector.AddToUniforms( UniqueId , dataType , string.Format( ArrayFormatStr , m_name , arrayLength ) );				if( m_autoRangeCheck )					arrayIndex = string.Format( "clamp({0},0,({1} - 1))" , arrayIndex , arrayLength );				result = string.Format( ArrayFormatStr , m_name , arrayIndex );			}			m_outputPorts[ 0 ].SetLocalValue( result , dataCollector.PortCategory );			return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory );		}		public void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector )		{			if( m_referenceType == TexReferenceType.Object && m_autoRegister && m_connStatus != NodeConnectionStatus.Connected )			{				string dataType = UIUtils.PrecisionWirePortToCgType( CurrentPrecisionType , AvailableTypesValues[ m_type ] );				if( m_isJagged )				{					dataCollector.AddToUniforms( UniqueId , dataType , string.Format( JaggedArrayFormatStr , m_name , ArrayLengthX , ArrayLengthY ) );				}				else				{					dataCollector.AddToUniforms( UniqueId , dataType , string.Format( ArrayFormatStr , m_name , ArrayLengthX ) );				}			}		}		public override void WriteToString( ref string nodeInfo , ref string connectionsInfo )		{			base.WriteToString( ref nodeInfo , ref connectionsInfo );			IOUtils.AddFieldValueToString( ref nodeInfo , m_name );			IOUtils.AddFieldValueToString( ref nodeInfo , m_indexX );			IOUtils.AddFieldValueToString( ref nodeInfo , m_arrayLengthX );			IOUtils.AddFieldValueToString( ref nodeInfo , m_type );			IOUtils.AddFieldValueToString( ref nodeInfo , m_autoRangeCheck );			IOUtils.AddFieldValueToString( ref nodeInfo , m_isJagged );			IOUtils.AddFieldValueToString( ref nodeInfo , m_indexY );			IOUtils.AddFieldValueToString( ref nodeInfo , m_arrayLengthY );			IOUtils.AddFieldValueToString( ref nodeInfo , m_autoRegister );			IOUtils.AddFieldValueToString( ref nodeInfo , m_referenceType );			IOUtils.AddFieldValueToString( ref nodeInfo , m_referenceNodeId );		}		public override void ReadFromString( ref string[] nodeParams )		{			base.ReadFromString( ref nodeParams );			m_name = GetCurrentParam( ref nodeParams );			m_indexX = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			m_arrayLengthX = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			m_type = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			m_autoRangeCheck = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );			if( UIUtils.CurrentShaderVersion() > 15801 )			{				m_isJagged = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );				m_indexY = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );				m_arrayLengthY = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );				m_autoRegister = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );				m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ) , GetCurrentParam( ref nodeParams ) );				m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );			}			SetAdditonalTitleText( string.Format( Constants.SubTitleValueFormatStr , m_name ) );			UpdatePorts();		}		public override void RefreshExternalReferences()		{			base.RefreshExternalReferences();			if( m_referenceType == TexReferenceType.Instance && m_referenceNodeId > -1 )			{				m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as GlobalArrayNode;				if( m_referenceNode != null )				{					m_referenceArrayId = UIUtils.GetGlobalArrayNodeRegisterId( m_referenceNodeId );					UpdatePorts();				}				else				{					m_referenceNodeId = -1;				}			}		}		public int ArrayLengthX { get { return ( m_referenceNode != null ) ? m_referenceNode.ArrayLengthX : m_arrayLengthX; } }		public int ArrayLengthY { get { return ( m_referenceNode != null ) ? m_referenceNode.ArrayLengthY : m_arrayLengthY; } }		public bool AutoRegister { get { return m_autoRegister; } }		public bool IsJagged { get { return m_isJagged; } }		public bool Updated { get { return m_updated; } }		public override string DataToArray { get { return m_name; } }	}}
 |