diff options
author | chai <chaifix@163.com> | 2020-10-23 13:08:43 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2020-10-23 13:08:43 +0800 |
commit | b82da95b5181ac8bbae38efb13e950d5e88a4caa (patch) | |
tree | 48a6f3269276484bbc7cfc95f0651f40a2176aa1 /Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs | |
parent | 917e9e0b320775634dc2e710f7deac74fd0822f0 (diff) |
*移动amplify shader editor到third party目录
Diffstat (limited to 'Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs')
-rw-r--r-- | Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs | 1236 |
1 files changed, 1236 insertions, 0 deletions
diff --git a/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs new file mode 100644 index 00000000..de297c2e --- /dev/null +++ b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/Master/FunctionNode.cs @@ -0,0 +1,1236 @@ +// Amplify Shader Editor - Visual Shader Editing Tool +// Copyright (c) Amplify Creations, Lda <info@amplify.pt> + +//#define ADD_SHADER_FUNCTION_HEADERS + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System; +namespace AmplifyShaderEditor +{ + [Serializable] + [NodeAttributes( "Function Node", "Functions", "Function Node", KeyCode.None, false, 0, int.MaxValue, typeof( AmplifyShaderFunction ) )] + public class FunctionNode : ParentNode + { + [SerializeField] + private AmplifyShaderFunction m_function; + + [SerializeField] + private ParentGraph m_functionGraph; + + [SerializeField] + private int m_functionGraphId = -1; + + [SerializeField] + private List<FunctionInput> m_allFunctionInputs; + private Dictionary<int, FunctionInput> m_allFunctionInputsDict = new Dictionary<int, FunctionInput>(); + + [SerializeField] + private List<FunctionOutput> m_allFunctionOutputs; + private Dictionary<int, FunctionOutput> m_allFunctionOutputsDict = new Dictionary<int, FunctionOutput>(); + + [SerializeField] + private List<FunctionSwitch> m_allFunctionSwitches; + private Dictionary<int, FunctionSwitch> m_allFunctionSwitchesDict = new Dictionary<int, FunctionSwitch>(); + + [SerializeField] + private ReordenatorNode m_reordenator; + + [SerializeField] + private string m_filename; + + [SerializeField] + private string m_headerTitle = string.Empty; + + [SerializeField] + private int m_orderIndex; + + [SerializeField] + private string m_functionCheckSum; + + [SerializeField] + private string m_functionGUID = string.Empty; + + //[SerializeField] + //private List<string> m_includes = new List<string>(); + + //[SerializeField] + //private List<string> m_pragmas = new List<string>(); + + [SerializeField] + private List<AdditionalDirectiveContainer> m_directives = new List<AdditionalDirectiveContainer>(); + + private bool m_parametersFoldout = true; + [SerializeField] + private ParentGraph m_outsideGraph = null; + + [SerializeField] + private FunctionOutput m_mainPreviewNode; + + bool m_portsChanged = false; + //[SerializeField] + bool m_initialGraphDraw = false; + + private bool m_refreshIdsRequired = false; + + public string[] ReadOptionsHelper = new string[] { }; + + private bool m_lateRefresh = false; + + private Dictionary<int, bool> m_duplicatesBuffer = new Dictionary<int, bool>(); + string LastLine( string text ) + { + string[] lines = text.Replace( "\r", "" ).Split( '\n' ); + return lines[ lines.Length - 1 ]; + } + + public void CommonInit( AmplifyShaderFunction function, int uniqueId ) + { + SetBaseUniqueId( uniqueId ); + + if( function == null ) + return; + + m_refreshIdsRequired = UIUtils.IsLoading && ( UIUtils.CurrentShaderVersion() < 14004 ); + + m_function = function; + + if( Function.FunctionName.Length > 1 ) + { + SetTitleText( GraphContextMenu.AddSpacesToSentence( Function.FunctionName ) ); + } + else + { + SetTitleText( Function.FunctionName ); + } + m_tooltipText = Function.Description; + m_hasTooltipLink = false; + if( m_functionGraph == null ) + { + //m_functionGraph = new ParentGraph(); + m_functionGraph = CreateInstance<ParentGraph>(); + m_functionGraph.Init(); + m_functionGraph.ParentWindow = ContainerGraph.ParentWindow; + } + + if( string.IsNullOrEmpty( m_functionGUID ) ) + { + m_functionGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath( m_function ) ); + } + + m_functionGraphId = Mathf.Max( m_functionGraphId, ContainerGraph.ParentWindow.GraphCount ); + ContainerGraph.ParentWindow.GraphCount = m_functionGraphId + 1; + m_functionGraph.SetGraphId( m_functionGraphId ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + AmplifyShaderEditorWindow.LoadFromMeta( ref m_functionGraph, ContainerGraph.ParentWindow.ContextMenuInstance, Function.FunctionInfo ); + //m_functionCheckSum = LastLine( m_function.FunctionInfo ); + m_functionCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString(); + List<PropertyNode> propertyList = UIUtils.PropertyNodesList(); + m_allFunctionInputs = UIUtils.FunctionInputList(); + m_allFunctionOutputs = UIUtils.FunctionOutputList(); + m_allFunctionSwitches = UIUtils.FunctionSwitchList(); + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_allFunctionInputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + m_allFunctionOutputs.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + m_allFunctionSwitches.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); + + int inputCount = m_allFunctionInputs.Count; + for( int i = 0; i < inputCount; i++ ) + { + if( m_refreshIdsRequired ) + { + AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName ); + } + else + { + AddInputPort( m_allFunctionInputs[ i ].SelectedInputType, false, m_allFunctionInputs[ i ].InputName, -1, MasterNodePortCategory.Fragment, m_allFunctionInputs[ i ].UniqueId ); + } + InputPortSwitchRestriction( m_inputPorts[ i ] ); + + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected ) + { + m_inputPorts[ i ].AutoDrawInternalData = true; + m_inputPorts[ i ].InternalData = m_allFunctionInputs[ i ].InputPorts[ 0 ].InternalData; + } + m_allFunctionInputs[ i ].Fnode = this; + } + + int outputCount = m_allFunctionOutputs.Count; + FunctionOutput first = null; + for( int i = 0; i < outputCount; i++ ) + { + if( i == 0 ) + first = m_allFunctionOutputs[ i ]; + + if( m_allFunctionOutputs[ i ].PreviewNode ) + { + m_mainPreviewNode = m_allFunctionOutputs[ i ]; + } + + if( m_refreshIdsRequired ) + { + AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName ); + } + else + { + AddOutputPort( m_allFunctionOutputs[ i ].AutoOutputType, m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].UniqueId ); + } + OutputPortSwitchRestriction( m_outputPorts[ i ] ); + } + + // make sure to hide the ports properly + CheckPortVisibility(); + + if( m_mainPreviewNode == null ) + m_mainPreviewNode = first; + + //create reordenator to main graph + bool inside = false; + if( ContainerGraph.ParentWindow.CustomGraph != null ) + inside = true; + + if( /*hasConnectedProperties*/propertyList.Count > 0 ) + { + m_reordenator = ScriptableObject.CreateInstance<ReordenatorNode>(); + m_reordenator.Init( "_" + Function.FunctionName, Function.FunctionName, propertyList, false ); + m_reordenator.OrderIndex = m_orderIndex; + m_reordenator.HeaderTitle = Function.FunctionName; + m_reordenator.IsInside = inside; + } + + if( m_reordenator != null ) + { + cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + UIUtils.RegisterPropertyNode( m_reordenator ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + if( inside ) + { + UIUtils.RegisterPropertyNode( m_reordenator ); + } + } + + m_textLabelWidth = 120; + + UIUtils.RegisterFunctionNode( this ); + + m_previewShaderGUID = "aca70c900c50c004e8ef0b47c4fac4d4"; + m_useInternalPortData = false; + m_selectedLocation = function.PreviewPosition; + UIUtils.CurrentWindow.OutsideGraph.OnLODMasterNodesAddedEvent += OnLODMasterNodesAddedEvent; + } + + public InputPort GetInput( FunctionInput input ) + { + int index = m_allFunctionInputs.FindIndex( ( x ) => { return x.Equals( input ); } ); + if( index >= 0 ) + return InputPorts[ index ]; + else + return null; + } + + private void OnLODMasterNodesAddedEvent( int lod ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + + public void SetPreviewInput( InputPort input ) + { + if( !HasPreviewShader || !m_initialized ) + return; + + if( input.IsConnected && input.InputNodeHasPreview( ContainerGraph ) ) + { + input.SetPreviewInputTexture( ContainerGraph ); + } + else + { + input.SetPreviewInputValue( ContainerGraph ); + } + } + + public override bool RecursivePreviewUpdate( Dictionary<string, bool> duplicatesDict = null ) + { + if( duplicatesDict == null ) + { + duplicatesDict = ContainerGraph.ParentWindow.VisitedChanged; + } + + if( m_allFunctionOutputs == null || m_allFunctionOutputs.Count == 0 ) + return false; + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + ParentNode outNode = m_allFunctionOutputs[ i ]; + if( outNode != null ) + { + if( !duplicatesDict.ContainsKey( outNode.OutputId ) ) + { + bool result = outNode.RecursivePreviewUpdate(); + if( result ) + PreviewIsDirty = true; + } + else if( duplicatesDict[ outNode.OutputId ] ) + { + PreviewIsDirty = true; + } + } + } + + bool needsUpdate = PreviewIsDirty; + RenderNodePreview(); + if( !duplicatesDict.ContainsKey( OutputId ) ) + duplicatesDict.Add( OutputId, needsUpdate ); + return needsUpdate; + } + + public override void RenderNodePreview() + { + if( m_outputPorts == null ) + return; + + if( !PreviewIsDirty && !m_continuousPreviewRefresh ) + return; + + // this is in the wrong place?? + if( m_drawPreviewAsSphere != m_mainPreviewNode.SpherePreview ) + { + m_drawPreviewAsSphere = m_mainPreviewNode.SpherePreview; + OnNodeChange(); + } + + int count = m_outputPorts.Count; + for( int i = 0; i < count; i++ ) + { + m_outputPorts[ i ].OutputPreviewTexture = m_allFunctionOutputs[ i ].PreviewTexture; + } + + if( PreviewIsDirty ) + FinishPreviewRender = true; + + PreviewIsDirty = false; + } + + public override RenderTexture PreviewTexture + { + get + { + if( m_mainPreviewNode != null ) + return m_mainPreviewNode.PreviewTexture; + else + return base.PreviewTexture; + } + } + + private void AddShaderFunctionDirectivesInternal( int lod ) + { + List<TemplateMultiPassMasterNode> nodes = ContainerGraph.ParentWindow.OutsideGraph.GetMultiPassMasterNodes( lod ); + int count = nodes.Count; + for( int i = 0; i < count; i++ ) + { + nodes[ i ].PassModule.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + } + + public override void RefreshExternalReferences() + { + base.RefreshExternalReferences(); + if( Function == null ) + return; + + //Debug.Log( "RefreshExternalReferences " + m_function.FunctionName + " " + UIUtils.CurrentWindow.IsShaderFunctionWindow ); + + Function.UpdateDirectivesList(); + + MasterNode masterNode = UIUtils.CurrentWindow.OutsideGraph.CurrentMasterNode; + StandardSurfaceOutputNode surface = masterNode as StandardSurfaceOutputNode; + + + + if( surface != null ) + { + //for( int i = 0; i < Function.AdditionalIncludes.IncludeList.Count; i++ ) + //{ + // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Add( Function.AdditionalIncludes.IncludeList[ i ] ); + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem( AdditionalLineType.Include, Function.AdditionalIncludes.IncludeList[ i ] ); + // m_includes.Add( Function.AdditionalIncludes.IncludeList[ i ] ); + //} + + //for( int i = 0; i < Function.AdditionalPragmas.PragmaList.Count; i++ ) + //{ + // //ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Add( Function.AdditionalPragmas.PragmaList[ i ] ); + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.AddShaderFunctionItem(AdditionalLineType.Pragma, Function.AdditionalPragmas.PragmaList[ i ] ); + // m_pragmas.Add( Function.AdditionalPragmas.PragmaList[ i ] ); + //} + surface.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + } + else + { + // Assuring that we're not editing a Shader Function, as directives setup is not needed there + if( !UIUtils.CurrentWindow.IsShaderFunctionWindow ) + { + // This function is nested inside a shader function itself and this method + // was called before the main output node was created. + // This is possible since all nodes RefreshExternalReferences(...) are called at the end + // of a LoadFromMeta + // Need to delay this setup to after all nodes are loaded to then setup the directives + m_lateRefresh = true; + return; + } + } + + } + m_directives.AddRange( Function.AdditionalDirectives.DirectivesList ); + + if( m_refreshIdsRequired ) + { + m_refreshIdsRequired = false; + int inputCount = m_inputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + m_inputPorts[ i ].ChangePortId( m_allFunctionInputs[ i ].UniqueId ); + } + + int outputCount = m_outputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + m_outputPorts[ i ].ChangePortId( m_allFunctionOutputs[ i ].UniqueId ); + } + } + + if( ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph ) + ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount += m_functionGraph.InstancePropertyCount; + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( ReadOptionsHelper.Length > 2 ) + { + for( int i = 1; i < ReadOptionsHelper.Length; i += 2 ) + { + int optionId = Convert.ToInt32( ReadOptionsHelper[ i ] ); + int optionValue = Convert.ToInt32( ReadOptionsHelper[ i + 1 ] ); + for( int j = 0; j < m_allFunctionSwitches.Count; j++ ) + { + if( m_allFunctionSwitches[ j ].UniqueId == optionId ) + { + m_allFunctionSwitches[ j ].SetCurrentSelectedInput( optionValue, m_allFunctionSwitches[ j ].GetCurrentSelectedInput() ); + break; + } + } + } + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_portsChanged = true; + } + + void InputPortSwitchRestriction( WirePort port ) + { + switch( port.DataType ) + { + case WirePortDataType.OBJECT: + break; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + { + port.CreatePortRestrictions( WirePortDataType.FLOAT, WirePortDataType.FLOAT2, WirePortDataType.FLOAT3, WirePortDataType.FLOAT4, WirePortDataType.COLOR, WirePortDataType.INT, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + port.CreatePortRestrictions( WirePortDataType.FLOAT3x3, WirePortDataType.FLOAT4x4, WirePortDataType.OBJECT ); + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.OBJECT ); + } + break; + default: + break; + } + } + + void OutputPortSwitchRestriction( WirePort port ) + { + switch( port.DataType ) + { + case WirePortDataType.OBJECT: + break; + case WirePortDataType.FLOAT: + case WirePortDataType.FLOAT2: + case WirePortDataType.FLOAT3: + case WirePortDataType.FLOAT4: + case WirePortDataType.COLOR: + case WirePortDataType.INT: + case WirePortDataType.FLOAT3x3: + case WirePortDataType.FLOAT4x4: + { + port.AddPortForbiddenTypes( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE ); + } + break; + case WirePortDataType.SAMPLER1D: + case WirePortDataType.SAMPLER2D: + case WirePortDataType.SAMPLER3D: + case WirePortDataType.SAMPLERCUBE: + { + port.CreatePortRestrictions( WirePortDataType.SAMPLER1D, WirePortDataType.SAMPLER2D, WirePortDataType.SAMPLER3D, WirePortDataType.SAMPLERCUBE, WirePortDataType.OBJECT ); + } + break; + default: + break; + } + } + + public override void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + m_outsideGraph = cachedGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_allFunctionOutputs[ i ].PropagateNodeData( nodeData, ref dataCollector ); + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + base.PropagateNodeData( nodeData, ref dataCollector ); + } + + protected override void OnUniqueIDAssigned() + { + base.OnUniqueIDAssigned(); + UIUtils.RegisterFunctionNode( this ); + } + + public override void SetupFromCastObject( UnityEngine.Object obj ) + { + base.SetupFromCastObject( obj ); + AmplifyShaderFunction function = obj as AmplifyShaderFunction; + CommonInit( function, UniqueId ); + RefreshExternalReferences(); + } + + public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) + { + base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ portId ] : GetFunctionInputByUniqueId( portId ); + functionInput.PreviewIsDirty = true; + if( functionInput.AutoCast ) + { + InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ portId ] : GetInputPortByUniqueId( portId ); + inputPort.MatchPortToConnection(); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + functionInput.ChangeOutputType( inputPort.DataType, false ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + } + + public override void OnInputPortDisconnected( int portId ) + { + base.OnInputPortDisconnected( portId ); + + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ portId ] : GetFunctionInputByUniqueId( portId ); + functionInput.PreviewIsDirty = true; + } + + public override void OnConnectedOutputNodeChanges( int inputPortId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) + { + base.OnConnectedOutputNodeChanges( inputPortId, otherNodeId, otherPortId, name, type ); + FunctionInput functionInput = m_refreshIdsRequired ? m_allFunctionInputs[ inputPortId ] : GetFunctionInputByUniqueId( inputPortId ); + functionInput.PreviewIsDirty = true; + if( functionInput.AutoCast ) + { + InputPort inputPort = m_refreshIdsRequired ? m_inputPorts[ inputPortId ] : GetInputPortByUniqueId( inputPortId ); + inputPort.MatchPortToConnection(); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + functionInput.ChangeOutputType( inputPort.DataType, false ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + } + + public override void DrawProperties() + { + base.DrawProperties(); + + if( Function == null ) + return; + + if( Function.Description.Length > 0 || m_allFunctionSwitches.Count > 0 ) + NodeUtils.DrawPropertyGroup( ref m_parametersFoldout, "Parameters", DrawDescription ); + + bool drawInternalDataUI = false; + int inputCount = m_inputPorts.Count; + if( inputCount > 0 ) + { + for( int i = 0; i < inputCount; i++ ) + { + if( m_inputPorts[ i ].Available && m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].AutoDrawInternalData /*&& ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) )*/ /*&& m_inputPorts[ i ].AutoDrawInternalData*/ ) + { + drawInternalDataUI = true; + break; + } + } + } + + if( drawInternalDataUI ) + NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () => + { + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible && m_inputPorts[ i ].AutoDrawInternalData ) + { + EditorGUI.BeginChangeCheck(); + m_inputPorts[ i ].ShowInternalData( this ); + if( EditorGUI.EndChangeCheck() ) + { + m_allFunctionInputs[ i ].PreviewIsDirty = true; + } + } + } + } ); + } + + private void DrawDescription() + { + if( Function.Description.Length > 0 ) + EditorGUILayout.HelpBox( Function.Description, MessageType.Info ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + m_allFunctionSwitches[ i ].AsDrawn = false; + } + + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + if( m_allFunctionSwitches[ i ].DrawOption( this ) ) + { + m_portsChanged = true; + } + } + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + private void RemoveShaderFunctionDirectivesInternal( int lod ) + { + List<TemplateMultiPassMasterNode> nodes = ContainerGraph.ParentWindow.OutsideGraph.GetMultiPassMasterNodes( lod ); + int count = nodes.Count; + for( int i = 0; i < count; i++ ) + { + nodes[ i ].PassModule.AdditionalDirectives.RemoveShaderFunctionItems( OutputId ); + } + } + + public override void Destroy() + { + m_mainPreviewNode = null; + base.Destroy(); + + m_duplicatesBuffer.Clear(); + m_duplicatesBuffer = null; + + if( m_functionGraph != null && ContainerGraph.ParentWindow.CurrentGraph != m_functionGraph ) + ContainerGraph.ParentWindow.CurrentGraph.InstancePropertyCount -= m_functionGraph.InstancePropertyCount; + + if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface != null ) + { + //for( int i = 0; i < m_includes.Count; i++ ) + //{ + // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Contains( m_includes[ i ] ) ) + // //{ + // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalIncludes.OutsideList.Remove( m_includes[ i ] ); + // //} + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Include, m_includes[ i ] ); + //} + + //for( int i = 0; i < m_pragmas.Count; i++ ) + //{ + // //if( ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Contains( m_pragmas[ i ] ) ) + // //{ + // // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalPragmas.OutsideList.Remove( m_pragmas[ i ] ); + // //} + // ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItem( AdditionalLineType.Pragma, m_pragmas[ i ] ); + //} + ContainerGraph.ParentWindow.OutsideGraph.CurrentStandardSurface.AdditionalDirectives.RemoveShaderFunctionItems( OutputId/*, m_directives */); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + RemoveShaderFunctionDirectivesInternal( lod ); + } + } + } + + + + + // Cannot GameObject.Destroy(m_directives[i]) since we would be removing them from + // the shader function asset itself + + m_directives.Clear(); + m_directives = null; + + if( m_reordenator != null ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + UIUtils.UnregisterPropertyNode( m_reordenator ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + m_reordenator.Destroy(); + m_reordenator = null; + } + + UIUtils.UnregisterFunctionNode( this ); + + ParentGraph cachedGraph2 = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( m_allFunctionInputs != null ) + m_allFunctionInputs.Clear(); + m_allFunctionInputs = null; + + if( m_allFunctionOutputs != null ) + m_allFunctionOutputs.Clear(); + m_allFunctionOutputs = null; + + if( m_functionGraph != null ) + m_functionGraph.SoftDestroy(); + m_functionGraph = null; + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph2; + m_function = null; + + m_allFunctionOutputsDict.Clear(); + m_allFunctionOutputsDict = null; + + m_allFunctionSwitchesDict.Clear(); + m_allFunctionSwitchesDict = null; + + m_allFunctionInputsDict.Clear(); + m_allFunctionInputsDict = null; + + UIUtils.CurrentWindow.OutsideGraph.OnLODMasterNodesAddedEvent -= OnLODMasterNodesAddedEvent; + } + + public override void OnNodeLogicUpdate( DrawInfo drawInfo ) + { + if( m_lateRefresh ) + { + m_lateRefresh = false; + RefreshExternalReferences(); + } + + CheckForChangesRecursively(); + + base.OnNodeLogicUpdate( drawInfo ); + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + + if( m_functionGraph != null ) + { + int nodeCount = m_functionGraph.AllNodes.Count; + for( int i = 0; i < nodeCount; i++ ) + { + m_functionGraph.AllNodes[ i ].OnNodeLogicUpdate( drawInfo ); + } + + if( !string.IsNullOrEmpty( FunctionGraph.CurrentFunctionOutput.SubTitle ) ) + { + SetAdditonalTitleText( FunctionGraph.CurrentFunctionOutput.SubTitle ); + } + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + if( m_portsChanged ) + { + m_portsChanged = false; + for( int i = 0; i < m_allFunctionOutputs.Count; i++ ) + { + m_outputPorts[ i ].ChangeType( m_allFunctionOutputs[ i ].InputPorts[ 0 ].DataType, false ); + } + + CheckPortVisibility(); + } + } + + public override void Draw( DrawInfo drawInfo ) + { + //CheckForChangesRecursively(); + + if( !m_initialGraphDraw && drawInfo.CurrentEventType == EventType.Repaint ) + { + m_initialGraphDraw = true; + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; + if( m_functionGraph != null ) + { + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + ParentNode node = m_functionGraph.AllNodes[ i ]; + if( node != null ) + { + node.OnNodeLayout( drawInfo ); + } + } + } + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + } + + base.Draw( drawInfo ); + } + + public bool CheckForChanges( bool forceCheck = false, bool forceChange = false ) + { + if( ( ContainerGraph.ParentWindow.CheckFunctions || forceCheck || forceChange ) && m_function != null ) + { + //string newCheckSum = LastLine( m_function.FunctionInfo ); + string newCheckSum = AssetDatabase.GetAssetDependencyHash( AssetDatabase.GetAssetPath( m_function ) ).ToString(); + if( !m_functionCheckSum.Equals( newCheckSum ) || forceChange ) + { + m_functionCheckSum = newCheckSum; + ContainerGraph.OnDuplicateEvent += DuplicateMe; + return true; + } + } + return false; + } + + public bool CheckForChangesRecursively() + { + if( m_functionGraph == null ) + return false; + + bool result = false; + for( int i = 0; i < m_functionGraph.FunctionNodes.NodesList.Count; i++ ) + { + if( m_functionGraph.FunctionNodes.NodesList[ i ].CheckForChangesRecursively() ) + result = true; + } + if( CheckForChanges( false, result ) ) + result = true; + + return result; + } + + public void DuplicateMe() + { + bool previewOpen = m_showPreview; + + string allOptions = m_allFunctionSwitches.Count.ToString(); + for( int i = 0; i < m_allFunctionSwitches.Count; i++ ) + { + allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput(); + } + + ReadOptionsHelper = allOptions.Split( ',' ); + + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = null; + MasterNode masterNode = ContainerGraph.ParentWindow.CurrentGraph.CurrentMasterNode; + if( masterNode != null ) + masterNode.InvalidateMaterialPropertyCount(); + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + ParentNode newNode = ContainerGraph.CreateNode( m_function, false, Vec2Position ); + newNode.ShowPreview = previewOpen; + ( newNode as FunctionNode ).ReadOptionsHelper = ReadOptionsHelper; + newNode.RefreshExternalReferences(); + if( ( newNode as FunctionNode ).m_reordenator && m_reordenator ) + ( newNode as FunctionNode ).m_reordenator.OrderIndex = m_reordenator.OrderIndex; + + for( int i = 0; i < m_outputPorts.Count; i++ ) + { + if( m_outputPorts[ i ].IsConnected ) + { + OutputPort newOutputPort = newNode.GetOutputPortByUniqueId( m_outputPorts[ i ].PortId ); + if( newNode.OutputPorts != null && newOutputPort != null ) + { + for( int j = m_outputPorts[ i ].ExternalReferences.Count - 1; j >= 0; j-- ) + { + ContainerGraph.CreateConnection( m_outputPorts[ i ].ExternalReferences[ j ].NodeId, m_outputPorts[ i ].ExternalReferences[ j ].PortId, newOutputPort.NodeId, newOutputPort.PortId ); + } + } + } + //else + //{ + //if( newNode.OutputPorts != null && newNode.OutputPorts[ i ] != null ) + //{ + // ContainerGraph.DeleteConnection( false, newNode.UniqueId, newNode.OutputPorts[ i ].PortId, false, false, false ); + //} + //} + } + + for( int i = 0; i < m_inputPorts.Count; i++ ) + { + if( m_inputPorts[ i ].IsConnected ) + { + InputPort newInputPort = newNode.GetInputPortByUniqueId( m_inputPorts[ i ].PortId ); + if( newNode.InputPorts != null && newInputPort != null ) + { + ContainerGraph.CreateConnection( newInputPort.NodeId, newInputPort.PortId, m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId, m_inputPorts[ i ].ExternalReferences[ 0 ].PortId ); + } + } + } + + ContainerGraph.OnDuplicateEvent -= DuplicateMe; + + if( Selected ) + { + ContainerGraph.DeselectNode( this ); + ContainerGraph.SelectNode( newNode, true, false ); + } + + ContainerGraph.DestroyNode( this, false ); + } + + private FunctionOutput GetFunctionOutputByUniqueId( int uniqueId ) + { + int listCount = m_allFunctionOutputs.Count; + if( m_allFunctionOutputsDict.Count != m_allFunctionOutputs.Count ) + { + m_allFunctionOutputsDict.Clear(); + for( int i = 0; i < listCount; i++ ) + { + m_allFunctionOutputsDict.Add( m_allFunctionOutputs[ i ].UniqueId, m_allFunctionOutputs[ i ] ); + } + } + + if( m_allFunctionOutputsDict.ContainsKey( uniqueId ) ) + return m_allFunctionOutputsDict[ uniqueId ]; + + return null; + } + + private FunctionInput GetFunctionInputByUniqueId( int uniqueId ) + { + int listCount = m_allFunctionInputs.Count; + if( m_allFunctionInputsDict.Count != m_allFunctionInputs.Count ) + { + m_allFunctionInputsDict.Clear(); + for( int i = 0; i < listCount; i++ ) + { + m_allFunctionInputsDict.Add( m_allFunctionInputs[ i ].UniqueId, m_allFunctionInputs[ i ] ); + } + } + + if( m_allFunctionInputsDict.ContainsKey( uniqueId ) ) + return m_allFunctionInputsDict[ uniqueId ]; + + return null; + } + + public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) + { + OutputPort outputPort = GetOutputPortByUniqueId( outputId ); + FunctionOutput functionOutput = GetFunctionOutputByUniqueId( outputId ); + + if( outputPort.IsLocalValue( dataCollector.PortCategory ) ) + return outputPort.LocalValue( dataCollector.PortCategory ); + + m_functionGraph.CurrentPrecision = ContainerGraph.ParentWindow.CurrentGraph.CurrentPrecision; + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + m_outsideGraph = cachedGraph; + ContainerGraph.ParentWindow.CustomGraph = m_functionGraph; +#if ADD_SHADER_FUNCTION_HEADERS + if( m_reordenator != null && m_reordenator.RecursiveCount() > 0 && m_reordenator.HasTitle ) + { + dataCollector.AddToProperties( UniqueId, "[Header(" + m_reordenator.HeaderTitle.Replace( "-", " " ) + ")]", m_reordenator.OrderIndex ); + } +#endif + string result = string.Empty; + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected ) + m_allFunctionInputs[ i ].OnPortGeneration += FunctionNodeOnPortGeneration; + } + + result += functionOutput.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar ); + + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( !m_allFunctionInputs[ i ].InputPorts[ 0 ].IsConnected || m_inputPorts[ i ].IsConnected ) + m_allFunctionInputs[ i ].OnPortGeneration -= FunctionNodeOnPortGeneration; + } + + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + + if( outputPort.ConnectionCount > 1 ) + RegisterLocalVariable( outputId, result, ref dataCollector ); + else + outputPort.SetLocalValue( result, dataCollector.PortCategory ); + + return outputPort.LocalValue( dataCollector.PortCategory ); + } + + private string FunctionNodeOnPortGeneration( ref MasterNodeDataCollector dataCollector, int index, ParentGraph graph ) + { + ParentGraph cachedGraph = ContainerGraph.ParentWindow.CustomGraph; + ContainerGraph.ParentWindow.CustomGraph = m_outsideGraph; + string result = m_inputPorts[ index ].GeneratePortInstructions( ref dataCollector ); + ContainerGraph.ParentWindow.CustomGraph = cachedGraph; + return result; + } + + public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) + { + base.WriteToString( ref nodeInfo, ref connectionsInfo ); + + if( Function != null ) + IOUtils.AddFieldValueToString( ref nodeInfo, m_function.name ); + else + IOUtils.AddFieldValueToString( ref nodeInfo, m_filename ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_reordenator != null ? m_reordenator.RawOrderIndex : -1 ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_headerTitle ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_functionGraphId ); + IOUtils.AddFieldValueToString( ref nodeInfo, m_functionGUID ); + + int functionSwitchCount = m_allFunctionSwitches != null ? m_allFunctionSwitches.Count : 0; + string allOptions = functionSwitchCount.ToString(); + for( int i = 0; i < functionSwitchCount; i++ ) + { + allOptions += "," + m_allFunctionSwitches[ i ].UniqueId + "," + m_allFunctionSwitches[ i ].GetCurrentSelectedInput(); + } + IOUtils.AddFieldValueToString( ref nodeInfo, allOptions ); + } + + public override void ReadFromString( ref string[] nodeParams ) + { + base.ReadFromString( ref nodeParams ); + m_filename = GetCurrentParam( ref nodeParams ); + m_orderIndex = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + m_headerTitle = GetCurrentParam( ref nodeParams ); + + if( UIUtils.CurrentShaderVersion() > 7203 ) + { + m_functionGraphId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); + } + + if( UIUtils.CurrentShaderVersion() > 13704 ) + { + m_functionGUID = GetCurrentParam( ref nodeParams ); + } + + AmplifyShaderFunction loaded = AssetDatabase.LoadAssetAtPath<AmplifyShaderFunction>( AssetDatabase.GUIDToAssetPath( m_functionGUID ) ); + if( loaded != null ) + { + CommonInit( loaded, UniqueId ); + } + else + { + string[] guids = AssetDatabase.FindAssets( "t:AmplifyShaderFunction " + m_filename ); + if( guids.Length > 0 ) + { + string sfGuid = null; + + foreach( string guid in guids ) + { + string assetPath = AssetDatabase.GUIDToAssetPath( guid ); + string name = System.IO.Path.GetFileNameWithoutExtension( assetPath ); + if( name.Equals( m_filename, StringComparison.OrdinalIgnoreCase ) ) + { + sfGuid = guid; + break; + } + } + loaded = AssetDatabase.LoadAssetAtPath<AmplifyShaderFunction>( AssetDatabase.GUIDToAssetPath( sfGuid ) ); + + if( loaded != null ) + { + CommonInit( loaded, UniqueId ); + } + else + { + SetTitleText( "ERROR" ); + UIUtils.ShowMessage( UniqueId, string.Format( "Error loading {0} shader function from project folder", m_filename ), MessageSeverity.Error ); + } + } + else + { + SetTitleText( "Missing Function" ); + UIUtils.ShowMessage( UniqueId, string.Format( "Missing {0} shader function on project folder", m_filename ), MessageSeverity.Error ); + } + } + if( UIUtils.CurrentShaderVersion() > 14203 ) + { + ReadOptionsHelper = GetCurrentParam( ref nodeParams ).Split( ',' ); + } + } + + public override void ReadOutputDataFromString( ref string[] nodeParams ) + { + if( Function == null ) + return; + + base.ReadOutputDataFromString( ref nodeParams ); + + ConfigureInputportsAfterRead(); + } + + public override void OnNodeDoubleClicked( Vector2 currentMousePos2D ) + { + if( Function == null ) + return; + + ContainerGraph.DeSelectAll(); + this.Selected = true; + + ContainerGraph.ParentWindow.OnLeftMouseUp(); + AmplifyShaderEditorWindow.LoadShaderFunctionToASE( Function, true ); + this.Selected = false; + } + + private void ConfigureInputportsAfterRead() + { + if( InputPorts != null ) + { + int inputCount = InputPorts.Count; + for( int i = 0; i < inputCount; i++ ) + { + InputPorts[ i ].ChangeProperties( m_allFunctionInputs[ i ].InputName, m_allFunctionInputs[ i ].SelectedInputType, false ); + } + } + + if( OutputPorts != null ) + { + int outputCount = OutputPorts.Count; + for( int i = 0; i < outputCount; i++ ) + { + OutputPorts[ i ].ChangeProperties( m_allFunctionOutputs[ i ].OutputName, m_allFunctionOutputs[ i ].AutoOutputType, false ); + } + } + } + + private void CheckPortVisibility() + { + bool changes = false; + if( InputPorts != null ) + { + for( int i = 0; i < m_allFunctionInputs.Count; i++ ) + { + if( m_inputPorts[ i ].Visible != m_allFunctionInputs[ i ].IsConnected ) + { + m_inputPorts[ i ].Visible = m_allFunctionInputs[ i ].IsConnected; + changes = true; + } + } + } + + if( changes ) + m_sizeIsDirty = true; + } + + public bool HasProperties { get { return m_reordenator != null; } } + + public ParentGraph FunctionGraph + { + get { return m_functionGraph; } + set { m_functionGraph = value; } + } + + public AmplifyShaderFunction Function + { + get { return m_function; } + set { m_function = value; } + } + + public override void RecordObjectOnDestroy( string Id ) + { + base.RecordObjectOnDestroy( Id ); + if( m_reordenator != null ) + m_reordenator.RecordObject( Id ); + + if( m_functionGraph != null ) + { + Undo.RegisterCompleteObjectUndo( m_functionGraph, Id ); + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + m_functionGraph.AllNodes[ i ].RecordObject( Id ); + } + } + } + + public override void SetContainerGraph( ParentGraph newgraph ) + { + base.SetContainerGraph( newgraph ); + if( m_functionGraph == null ) + return; + for( int i = 0; i < m_functionGraph.AllNodes.Count; i++ ) + { + m_functionGraph.AllNodes[ i ].SetContainerGraph( m_functionGraph ); + } + } + + public override void OnMasterNodeReplaced( MasterNode newMasterNode ) + { + base.OnMasterNodeReplaced( newMasterNode ); + if( m_functionGraph == null ) + return; + + m_functionGraph.FireMasterNodeReplacedEvent( newMasterNode ); + + StandardSurfaceOutputNode surface = newMasterNode as StandardSurfaceOutputNode; + if( surface != null ) + { + surface.AdditionalDirectives.AddShaderFunctionItems( OutputId, Function.AdditionalDirectives.DirectivesList ); + } + else + { + if( ContainerGraph.ParentWindow.OutsideGraph.MultiPassMasterNodes.Count > 0 ) + { + for( int lod = -1; lod < ContainerGraph.ParentWindow.OutsideGraph.LodMultiPassMasternodes.Count; lod++ ) + { + AddShaderFunctionDirectivesInternal( lod ); + } + } + } + } + } +} |