|
|
- // 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 DynamicTypeNode : ParentNode
- {
- protected string m_inputA = string.Empty;
- protected string m_inputB = string.Empty;
- protected List<string> m_extensibleInputResults;
- protected bool m_dynamicOutputType = true;
-
- protected bool m_extensibleInputPorts = false;
- protected bool m_allowMatrixCheck = false;
- protected bool m_vectorMatrixOps = false;
- //[SerializeField]
- private int m_inputCount = 2;
-
- //[SerializeField]
- private int m_lastInputCount = 2;
-
- private bool m_previouslyDragging = false;
- private int m_beforePreviewCount = 0;
-
- [UnityEngine.SerializeField]
- protected WirePortDataType m_mainDataType = WirePortDataType.FLOAT;
-
- protected WirePortDataType[] m_dynamicRestrictions =
- {
- WirePortDataType.OBJECT,
- WirePortDataType.FLOAT,
- WirePortDataType.FLOAT2,
- WirePortDataType.FLOAT3,
- WirePortDataType.FLOAT4,
- WirePortDataType.COLOR,
- WirePortDataType.INT
- };
-
- protected override void CommonInit( int uniqueId )
- {
- base.CommonInit( uniqueId );
- m_useInternalPortData = true;
- m_textLabelWidth = 35;
- AddPorts();
- }
-
- protected virtual void AddPorts()
- {
- AddInputPort( WirePortDataType.FLOAT, false, "A" );
- AddInputPort( WirePortDataType.FLOAT, false, "B" );
- AddOutputPort( WirePortDataType.FLOAT, Constants.EmptyPortValue );
- m_inputPorts[ 0 ].CreatePortRestrictions( m_dynamicRestrictions );
- m_inputPorts[ 1 ].CreatePortRestrictions( m_dynamicRestrictions );
- }
-
- public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type )
- {
- UpdateConnection( inputPortId );
- }
-
- public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
- {
- base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode );
- UpdateConnection( portId );
- }
-
- public override void OnInputPortDisconnected( int portId )
- {
- base.OnInputPortDisconnected( portId );
- UpdateDisconnectedConnection( portId );
- UpdateConnection( portId );
- UpdateEmptyInputPorts( true );
- }
-
- void UpdateDisconnectedConnection( int portId )
- {
- if( m_extensibleInputPorts || m_allowMatrixCheck )
- {
- int higher = 0;
- int groupOneType = 0;
- int groupTwoType = 0;
- for( int i = 0; i < m_inputPorts.Count; i++ )
- {
- if( m_inputPorts[ i ].IsConnected )
- {
- int currentPriority = UIUtils.GetPriority( m_inputPorts[ i ].DataType );
- if( !m_vectorMatrixOps && currentPriority < 3 )
- currentPriority += 7;
- if( currentPriority > higher && currentPriority > 2 )
- {
- higher = currentPriority;
- m_mainDataType = m_inputPorts[ i ].DataType;
- }
- switch( m_inputPorts[ i ].DataType )
- {
- case WirePortDataType.FLOAT2:
- case WirePortDataType.FLOAT3:
- case WirePortDataType.FLOAT4:
- case WirePortDataType.COLOR:
- {
- groupOneType++;
- groupTwoType++;
- }
- break;
- case WirePortDataType.FLOAT3x3:
- {
- groupOneType++;
- }
- break;
- case WirePortDataType.FLOAT4x4:
- {
- groupTwoType++;
- }
- break;
- }
- }
- }
-
- for( int i = 0; i < m_inputPorts.Count; i++ )
- {
- if( !m_inputPorts[ i ].IsConnected )
- {
- m_inputPorts[ i ].ChangeType( m_mainDataType, false );
- }
- }
-
- if( groupOneType > 0 && m_mainDataType == WirePortDataType.FLOAT4x4 )
- {
- m_errorMessageTooltip = "Doing this operation with FLOAT4x4 value only works against other FLOAT4x4 or FLOAT values";
- m_showErrorMessage = true;
- }
- else if( groupTwoType > 0 && m_mainDataType == WirePortDataType.FLOAT3x3 )
- {
- m_errorMessageTooltip = "Doing this operation with FLOAT3x3 value only works against other FLOAT3x3 or FLOAT values";
- m_showErrorMessage = true;
- }
- else
- {
- m_showErrorMessage = false;
- }
-
- if( m_dynamicOutputType )
- m_outputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
- else
-
- if( m_inputPorts[ 0 ].DataType != m_inputPorts[ 1 ].DataType )
- {
- int otherPortId = ( portId + 1 ) % 2;
- if( m_inputPorts[ otherPortId ].IsConnected )
- {
- m_mainDataType = m_inputPorts[ otherPortId ].DataType;
- m_inputPorts[ portId ].ChangeType( m_mainDataType, false );
- if( m_dynamicOutputType )
- m_outputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
- else
- {
- if( UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) )
- {
- m_mainDataType = m_inputPorts[ 0 ].DataType;
- m_inputPorts[ 1 ].ChangeType( m_mainDataType, false );
- }
- else
- {
- m_mainDataType = m_inputPorts[ 1 ].DataType;
- m_inputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
-
- if( m_dynamicOutputType )
- {
- if( m_mainDataType != m_outputPorts[ 0 ].DataType )
- {
- m_outputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
- }
- }
- }
- }
-
- void UpdateConnection( int portId )
- {
- if( m_extensibleInputPorts || m_allowMatrixCheck )
- {
- m_inputPorts[ portId ].MatchPortToConnection();
-
- int higher = 0;
- int groupOneType = 0;
- int groupTwoType = 0;
- for( int i = 0; i < m_inputPorts.Count; i++ )
- {
- if( m_inputPorts[ i ].IsConnected )
- {
- int currentPriority = UIUtils.GetPriority( m_inputPorts[ i ].DataType );
- if( !m_vectorMatrixOps && currentPriority < 3 )
- currentPriority += 7;
- if( currentPriority > higher )
- {
- higher = currentPriority;
- m_mainDataType = m_inputPorts[ i ].DataType;
- }
- switch( m_inputPorts[ i ].DataType )
- {
- case WirePortDataType.FLOAT2:
- case WirePortDataType.FLOAT3:
- case WirePortDataType.FLOAT4:
- case WirePortDataType.COLOR:
- {
- groupOneType++;
- groupTwoType++;
- }
- break;
- case WirePortDataType.FLOAT3x3:
- {
- groupOneType++;
- }
- break;
- case WirePortDataType.FLOAT4x4:
- {
- groupTwoType++;
- }
- break;
- }
- }
- }
-
- for( int i = 0; i < m_inputPorts.Count; i++ )
- {
- if( !m_inputPorts[ i ].IsConnected )
- {
- m_inputPorts[ i ].ChangeType( m_mainDataType, false );
- }
- }
- if( groupOneType > 0 && m_mainDataType == WirePortDataType.FLOAT4x4 )
- {
- m_errorMessageTooltip = "Doing this operation with FLOAT4x4 value only works against other FLOAT4x4 or FLOAT values";
- m_showErrorMessage = true;
- }
- else if( groupTwoType > 0 && m_mainDataType == WirePortDataType.FLOAT3x3 )
- {
- m_errorMessageTooltip = "Doing this operation with FLOAT3x3 value only works against other FLOAT3x3 or FLOAT values";
- m_showErrorMessage = true;
- }
- else
- {
- m_showErrorMessage = false;
- }
-
- if( m_dynamicOutputType )
- m_outputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
-
- else
- {
- m_inputPorts[ portId ].MatchPortToConnection();
- int otherPortId = ( portId + 1 ) % 2;
- if( !m_inputPorts[ otherPortId ].IsConnected )
- {
- m_inputPorts[ otherPortId ].ChangeType( m_inputPorts[ portId ].DataType, false );
- }
-
- if( m_inputPorts[ 0 ].DataType == m_inputPorts[ 1 ].DataType )
- {
- m_mainDataType = m_inputPorts[ 0 ].DataType;
- if( m_dynamicOutputType )
- m_outputPorts[ 0 ].ChangeType( InputPorts[ 0 ].DataType, false );
- }
- else
- {
- if( UIUtils.GetPriority( m_inputPorts[ 0 ].DataType ) > UIUtils.GetPriority( m_inputPorts[ 1 ].DataType ) )
- {
- m_mainDataType = m_inputPorts[ 0 ].DataType;
- }
- else
- {
- m_mainDataType = m_inputPorts[ 1 ].DataType;
- }
-
- if( m_dynamicOutputType )
- {
- if( m_mainDataType != m_outputPorts[ 0 ].DataType )
- {
- m_outputPorts[ 0 ].ChangeType( m_mainDataType, false );
- }
- }
- }
- }
- }
-
- public override void OnNodeLayout( DrawInfo drawInfo )
- {
- base.OnNodeLayout( drawInfo );
-
- if( !m_extensibleInputPorts )
- return;
-
- if( m_previouslyDragging != m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid && m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.NodeId != UniqueId )
- {
- if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid )
- {
- m_beforePreviewCount = 2;
- for( int i = 2; i < m_inputPorts.Count; i++ )
- {
- if( m_inputPorts[ i ].IsConnected )
- {
- m_beforePreviewCount++;
- }
- }
-
- m_inputCount = m_beforePreviewCount + 1;
- if( m_inputCount <= 10 )
- {
- if( m_inputCount > m_lastInputCount )
- {
- Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoCreateDynamicPortId );
- RecordObject( Constants.UndoCreateDynamicPortId );
-
- AddInputPort( m_mainDataType, false, ( ( char ) ( 'A' + m_inputCount - 1 ) ).ToString() );
- m_inputPorts[ m_inputCount - 1 ].CreatePortRestrictions( m_dynamicRestrictions );
- if( Selected && ContainerGraph.ParentWindow.ParametersWindow.IsMaximized )
- Event.current.type = EventType.Used;
- }
-
- m_lastInputCount = m_inputCount;
- m_sizeIsDirty = true;
- m_isDirty = true;
- SetSaveIsDirty();
- }
- }
- else
- {
- bool hasEmpty = CheckValidConnections();
- if( hasEmpty )
- UpdateEmptyInputPorts( false );
- }
-
- m_previouslyDragging = m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid;
- }
-
- UpdateEmptyInputPorts( false );
- }
-
- private bool CheckValidConnections()
- {
- if( !m_extensibleInputPorts )
- return false;
-
- bool hasEmptyConnections = false;
-
- bool hasMatrix = m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4x4 || m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ 1 ].DataType == WirePortDataType.FLOAT4x4;
-
- if( m_inputPorts.Count != m_beforePreviewCount )
- {
- if( hasMatrix )
- {
- bool showError = false;
- for( int i = m_inputPorts.Count - 1; i >= 2; i-- )
- {
- if( m_inputPorts[ i ].IsConnected )
- {
- showError = true;
- m_inputPorts[ i ].FullDeleteConnections();
- }
-
- hasEmptyConnections = true;
- }
- if( showError )
- m_containerGraph.ParentWindow.ShowMessage( "Matrix operations are only valid for the first two inputs to prevent errors" );
- }
- else
- {
- for( int i = m_inputPorts.Count - 1; i >= 2; i-- )
- {
- if( m_inputPorts[ i ].DataType == WirePortDataType.FLOAT3x3 || m_inputPorts[ i ].DataType == WirePortDataType.FLOAT4x4 )
- {
- m_containerGraph.ParentWindow.ShowMessage( "Matrix operations are only valid for the first two inputs to prevent errors" );
- m_inputPorts[ i ].FullDeleteConnections();
- hasEmptyConnections = true;
- }
- else if( !m_inputPorts[ i ].IsConnected )
- {
- hasEmptyConnections = true;
- }
- }
- }
- }
-
- return hasEmptyConnections;
- }
-
- private void UpdateEmptyInputPorts( bool recordUndo )
- {
- if( !m_extensibleInputPorts )
- return;
-
- if( !m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid )
- {
- if( recordUndo )
- {
- Undo.RegisterCompleteObjectUndo( m_containerGraph.ParentWindow, Constants.UndoDeleteDynamicPortId );
- RecordObject( Constants.UndoDeleteDynamicPortId );
- }
-
- bool hasDeleted = false;
- m_inputCount = 2;
- for( int i = m_inputPorts.Count - 1; i >= 2; i-- )
- {
- if( !m_inputPorts[ i ].IsConnected )
- {
- hasDeleted = true;
- DeleteInputPortByArrayIdx( i );
- }
- else
- {
- m_inputCount++;
- }
- }
-
- if( hasDeleted || m_inputCount != m_lastInputCount )
- {
- for( int i = 2; i < m_inputPorts.Count; i++ )
- {
- m_inputPorts[ i ].Name = ( ( char ) ( 'A' + i ) ).ToString();
- }
-
- m_beforePreviewCount = m_inputPorts.Count;
- m_inputCount = m_beforePreviewCount;
- m_lastInputCount = m_inputCount;
- m_sizeIsDirty = true;
- m_isDirty = true;
- SetSaveIsDirty();
- }
- }
-
- m_inputCount = Mathf.Clamp( m_inputCount, 2, 10 );
- }
-
- public virtual string BuildResults( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
- {
- if( !m_extensibleInputPorts )
- SetInputData( outputId, ref dataCollector, ignoreLocalvar );
- else
- SetExtensibleInputData( outputId, ref dataCollector, ignoreLocalvar );
- return string.Empty;
- }
-
- public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
- {
- string result = BuildResults( outputId, ref dataCollector, ignoreLocalvar );
- return CreateOutputLocalVariable( 0, result, ref dataCollector );
- }
-
- protected void SetInputData( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
- {
- m_inputA = m_inputPorts[ 0 ].GeneratePortInstructions( ref dataCollector );
- if( m_inputPorts[ 0 ].DataType != m_mainDataType )
- {
- m_inputA = UIUtils.CastPortType( ref dataCollector, m_currentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputA, m_inputPorts[ 0 ].DataType, m_mainDataType, m_inputA );
- }
- m_inputB = m_inputPorts[ 1 ].GeneratePortInstructions( ref dataCollector );
- if( m_inputPorts[ 1 ].DataType != m_mainDataType )
- {
- m_inputB = UIUtils.CastPortType( ref dataCollector, m_currentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_inputB, m_inputPorts[ 1 ].DataType, m_mainDataType, m_inputB );
- }
- }
-
- protected void SetExtensibleInputData( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
- {
- m_extensibleInputResults = new List<string>();
- for( int i = 0; i < m_inputPorts.Count; i++ )
- {
- m_extensibleInputResults.Add( m_inputPorts[ i ].GeneratePortInstructions( ref dataCollector ) );
- if( m_inputPorts[ i ].DataType != m_mainDataType && m_inputPorts[ i ].DataType != WirePortDataType.FLOAT && m_inputPorts[ i ].DataType != WirePortDataType.INT )
- {
- m_extensibleInputResults[ i ] = UIUtils.CastPortType( ref dataCollector, m_currentPrecisionType, new NodeCastInfo( UniqueId, outputId ), m_extensibleInputResults[ i ], m_inputPorts[ i ].DataType, m_mainDataType, m_extensibleInputResults[ i ] );
- }
- }
- }
-
- void UpdatePorts()
- {
- m_lastInputCount = Mathf.Clamp( m_inputCount, 2, 10 );
-
- for( int i = 2; i < m_inputCount; i++ )
- {
- AddInputPort( m_mainDataType, false, ( ( char ) ( 'A' + i ) ).ToString() );
- m_inputPorts[ i ].CreatePortRestrictions( m_dynamicRestrictions );
- }
-
- m_sizeIsDirty = true;
- SetSaveIsDirty();
- }
-
- public override void ReadFromString( ref string[] nodeParams )
- {
- base.ReadFromString( ref nodeParams );
- if( m_extensibleInputPorts && UIUtils.CurrentShaderVersion() > 10005 )
- {
- m_inputCount = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
- UpdatePorts();
- }
- }
-
- public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
- {
- base.WriteToString( ref nodeInfo, ref connectionsInfo );
- if( m_extensibleInputPorts )
- IOUtils.AddFieldValueToString( ref nodeInfo, m_inputCount );
- }
- }
- }
|