// Amplify Shader Editor - Visual Shader Editing Tool // Copyright (c) Amplify Creations, Lda //#define SHOW_TEMPLATE_HELP_BOX using System; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.Linq; namespace AmplifyShaderEditor { public enum HDSRPMaterialType { SubsurfaceScattering, Standard, Specular, Anisotropy, Iridescence, Translucent } public enum InvisibilityStatus { LockedInvisible, Invisible, Visible } public enum SetTemplateSource { NewShader, ShaderLoad, HotCodeReload }; [Serializable] [NodeAttributes( "Template Master Node", "Master", "Shader Generated according to template rules", null, KeyCode.None, false )] public sealed class TemplateMultiPassMasterNode : MasterNode { private const double MaxLODEditTimestamp = 1; private static int PASS_SELECTOR_VERSION = 16200; private static int PASS_UNIQUE_ID_VERSION = 16204; private const string LodNameId = "LODName"; private const string LodValueId = "LODValue"; private const string LodSubtitle = "LOD( {0} )"; private const string AdditionalLODsStr = "LODs"; private const string SubTitleFormatterStr = "(SubShader {0} Pass {1})"; private const string NoSubShaderPropertyStr = "No Sub-Shader properties available"; private const string NoPassPropertyStr = "No Pass properties available"; private const string WarningMessage = "Templates is a feature that is still heavily under development and users may experience some problems.\nPlease email support@amplify.pt if any issue occurs."; private const string OpenTemplateStr = "Edit Template"; private const string ReloadTemplateStr = "Reload Template"; private const string CommonPropertiesStr = "Common Properties "; private const string SubShaderModuleStr = "SubShader "; private const string PassModuleStr = "Pass "; private const string PassNameStr = "Name"; private const string PassNameFormateStr = "Name \"{0}\""; private const string SubShaderLODValueLabel = "LOD Value"; private const string SubShaderLODNameLabel = "LOD Name"; private bool m_reRegisterTemplateData = false; private bool m_fireTemplateChange = false; private bool m_fetchMasterNodeCategory = false; [SerializeField] private string m_templateGUID = "4e1801f860093ba4f9eb58a4b556825b"; [SerializeField] private int m_passIdx = 0; //[SerializeField] //private string m_passIdxStr = string.Empty; [SerializeField] private bool m_passFoldout = false; [SerializeField] private int m_subShaderIdx = 0; //[SerializeField] //private string m_subShaderIdxStr = string.Empty; [SerializeField] private bool m_subStringFoldout = false; [SerializeField] private bool m_lodFoldout = false; [SerializeField] private string m_mainLODName = string.Empty; //[SerializeField] //private string m_subShaderLODStr; //[SerializeField] //private bool m_mainMPMasterNode = false; [NonSerialized] private TemplateMultiPass m_templateMultiPass = null; [NonSerialized] private TemplateMultiPassMasterNode m_mainMasterNodeRef = null; [SerializeField] private TemplateModulesHelper m_subShaderModule = new TemplateModulesHelper(); [SerializeField] private TemplateModulesHelper m_passModule = new TemplateModulesHelper(); [SerializeField] private UsePassHelper m_usePass; [SerializeField] private string m_passName = string.Empty; [SerializeField] private string m_passUniqueId = string.Empty; [SerializeField] private string m_originalPassName = string.Empty; [SerializeField] private bool m_hasLinkPorts = false; [SerializeField] private InvisibilityStatus m_isInvisible = InvisibilityStatus.Visible; [SerializeField] private int m_invisibleOptions = 0; [SerializeField] private bool m_invalidNode = false; [SerializeField] private FallbackPickerHelper m_fallbackHelper = null; [SerializeField] private DependenciesHelper m_dependenciesHelper = new DependenciesHelper(); [SerializeField] private TemplateOptionsUIHelper m_subShaderOptions = new TemplateOptionsUIHelper( true ); [SerializeField] private TemplateOptionsUIHelper m_passOptions = new TemplateOptionsUIHelper( false ); [SerializeField] private TemplatePassSelectorHelper m_passSelector = new TemplatePassSelectorHelper(); [SerializeField] private TemplateOptionsDefinesContainer m_optionsDefineContainer = new TemplateOptionsDefinesContainer(); [SerializeField] private TerrainDrawInstancedHelper m_drawInstancedHelper = new TerrainDrawInstancedHelper(); // HATE THIS BELOW, MUST REMOVE HD SPECIFIC CODE FROM GENERIC MASTER NODE private const string HDSRPMaterialTypeStr = "Material Type"; private const string SRPMaterialSubsurfaceScatteringKeyword = "_MATERIAL_FEATURE_SUBSURFACE_SCATTERING 1"; private const string SRPMaterialTransmissionKeyword = "_MATERIAL_FEATURE_TRANSMISSION 1"; private const string SRPHDMaterialSpecularKeyword = "_MATERIAL_FEATURE_SPECULAR_COLOR 1"; //private const string SRPLWMaterialSpecularKeyword = "_SPECULAR_SETUP 1"; private const string SRPMaterialAnisotropyKeyword = "_MATERIAL_FEATURE_ANISOTROPY 1"; private const string SRPMaterialIridiscenceKeyword = "_MATERIAL_FEATURE_IRIDESCENCE 1"; //private const string SRPMaterialNormalMapKeyword = "_NORMALMAP 1"; //private const string SRPMaterialAlphaTestKeyword = "_ALPHATEST_ON 1"; //private const string SRPMaterialBlendModeAlphaClipThresholdKeyword = "_AlphaClip 1"; private const string SRPMaterialTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT 1"; private const string SRPMaterialBlendModeAddKeyword = "_BLENDMODE_ADD 1"; private const string SRPMaterialBlendModeAlphaKeyword = "_BLENDMODE_ALPHA 1"; private const string SRPMaterialClearCoatKeyword = "_MATERIAL_FEATURE_CLEAR_COAT"; [NonSerialized] private bool m_fetchPorts = true; [NonSerialized] private InputPort m_specularPort; [NonSerialized] private InputPort m_metallicPort; [NonSerialized] private InputPort m_coatMaskPort; [NonSerialized] private InputPort m_diffusionProfilePort; [NonSerialized] private InputPort m_subsurfaceMaskPort; [NonSerialized] private InputPort m_thicknessPort; [NonSerialized] private InputPort m_anisotropyPort; [NonSerialized] private InputPort m_iridescenceThicknessPort; [NonSerialized] private InputPort m_iridescenceMaskPort; [NonSerialized] private InputPort m_indexOfRefractionPort; [NonSerialized] private InputPort m_transmittanceColorPort; [NonSerialized] private InputPort m_transmittanceAbsorptionDistancePort; [NonSerialized] private InputPort m_transmittanceMaskPort; [SerializeField] private HDSRPMaterialType m_hdSrpMaterialType = HDSRPMaterialType.Standard; [NonSerialized] private bool m_refreshLODValueMasterNodes = false; [NonSerialized] private bool m_refocusLODValueMasterNodes = false; [NonSerialized] private double m_refreshLODValueMasterNodesTimestamp; ////////////////////////////////////////////////////////////////////////// protected override void CommonInit( int uniqueId ) { base.CommonInit( uniqueId ); m_masterNodeCategory = 1;// First Template m_marginPreviewLeft = 20; m_shaderNameIsTitle = true; m_customInspectorName = string.Empty; m_customPrecision = true; } public override void ReleaseResources() { // Internal template resources ( for inline properties) are released by first node on the list // As it's also registered that way if( IsLODMainFirstPass ) m_containerGraph.ClearInternalTemplateNodes(); if( !IsLODMainMasterNode ) return; TemplateMultiPass template = ( m_templateMultiPass == null ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : m_templateMultiPass; //Maintained the logic of being the main master node to unregister since this method is being called //over the main master node in multiple places //but it will unregister with unique of the first master node (pass 0) since it was the one //to register it int passUniqueId = ( m_passIdx == 0 ) ? UniqueId : ContainerGraph.MultiPassMasterNodes.NodesList[ 0 ].UniqueId; if( template != null && template.AvailableShaderProperties != null ) { // Unregister old template properties int oldPropertyCount = template.AvailableShaderProperties.Count; for( int i = 0; i < oldPropertyCount; i++ ) { UIUtils.ReleaseUniformName( passUniqueId, template.AvailableShaderProperties[ i ].PropertyName ); } } } public void CopyOptionsFrom( TemplateMultiPassMasterNode origin ) { //Copy options SubShaderOptions.CopyOptionsValuesFrom( origin.SubShaderOptions ); PassOptions.CopyOptionsValuesFrom( origin.PassOptions ); //Copy selected passes if( IsMainOutputNode ) m_passSelector.CopyFrom( origin.PassSelector ); } void RegisterProperties() { //First pass must be the one to always register properties so all modules //can extract a valid negative Id when reading inline properties if( /*!IsLODMainMasterNode*/!IsLODMainFirstPass ) { m_reRegisterTemplateData = false; return; } if( m_templateMultiPass != null ) { m_reRegisterTemplateData = false; // Register old template properties int newPropertyCount = m_templateMultiPass.AvailableShaderProperties.Count; for( int i = 0; i < newPropertyCount; i++ ) { m_containerGraph.AddInternalTemplateNode( m_templateMultiPass.AvailableShaderProperties[ i ] ); int nodeId = UIUtils.CheckUniformNameOwner( m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ); if( nodeId > -1 ) { if( UniqueId != nodeId ) { ParentNode node = m_containerGraph.GetNode( nodeId ); if( node != null ) { UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being used by {1}. Please rename it and reload template.", m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName, node.Attributes.Name ) ); } else { UIUtils.ShowMessage( string.Format( "Template requires property name {0} which is currently being on your graph. Please rename it and reload template.", m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ) ); } } } else { UIUtils.RegisterUniformName( UniqueId, m_templateMultiPass.AvailableShaderProperties[ i ].PropertyName ); } } } } public override void OnEnable() { base.OnEnable(); m_reRegisterTemplateData = true; if( m_usePass == null ) { m_usePass = ScriptableObject.CreateInstance(); m_usePass.Init( " Additional Use Passes" ); } if( m_fallbackHelper == null ) { m_fallbackHelper = ScriptableObject.CreateInstance(); m_fallbackHelper.Init(); } } protected override void OnUniqueIDAssigned() { base.OnUniqueIDAssigned(); if( UniqueId >= 0 ) { if( m_lodIndex == -1 ) { m_containerGraph.MultiPassMasterNodes.AddNode( this ); } else { m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this ); } } } public override void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true ) { base.OnInputPortConnected( portId, otherNodeId, otherPortId, activateNode ); m_passOptions.CheckImediateActionsForPort( this, portId ); } public override void OnInputPortDisconnected( int portId ) { base.OnInputPortDisconnected( portId ); m_passOptions.CheckImediateActionsForPort( this, portId ); } public void ForceTemplateRefresh() { SetTemplate( null, false, true, m_subShaderIdx, m_passIdx, SetTemplateSource.HotCodeReload ); } public void SetTemplate( TemplateMultiPass template, bool writeDefaultData, bool fetchMasterNodeCategory, int subShaderIdx, int passIdx , SetTemplateSource source ) { if( subShaderIdx > -1 ) m_subShaderIdx = subShaderIdx; if( passIdx > -1 ) m_passIdx = passIdx; ReleaseResources(); bool hotCodeOrRead = ( template == null ); m_templateMultiPass = ( hotCodeOrRead ) ? m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( m_templateGUID ) as TemplateMultiPass : template; if( m_templateMultiPass != null ) { string passName = string.IsNullOrEmpty( m_passUniqueId ) ? ( m_isInvisible == InvisibilityStatus.LockedInvisible ? m_passName : m_originalPassName ) : m_passUniqueId; int newPassIdx = m_passIdx; int newSubShaderIdx = m_subShaderIdx; m_templateMultiPass.GetSubShaderandPassFor( passName, ref newSubShaderIdx, ref newPassIdx ); if( newPassIdx == -1 || newSubShaderIdx == -1 ) { //m_containerGraph.MarkToDelete( this ); ContainerGraph.ParentWindow.SetOutdatedShaderFromTemplate(); m_invalidNode = true; UIUtils.ShowMessage( "Template changed drastically. Removing invalid passes." ); return; } else { if( m_passIdx != newPassIdx ) m_passIdx = newPassIdx; if( m_subShaderIdx != newSubShaderIdx ) m_subShaderIdx = newSubShaderIdx; } m_containerGraph.CurrentSRPType = m_templateMultiPass.SRPtype; if( m_templateMultiPass.IsSinglePass ) { SetAdditonalTitleText( string.Empty ); } else if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx ) { SetAdditonalTitleText( string.Format( SubTitleFormatterStr, m_subShaderIdx, m_passIdx ) ); } m_invalidNode = false; if( m_subShaderIdx >= m_templateMultiPass.SubShaders.Count || m_passIdx >= m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes.Count ) { if( DebugConsoleWindow.DeveloperMode ) Debug.LogFormat( "Inexisting pass {0}. Cancelling template fetch", m_originalPassName ); return; } m_isMainOutputNode = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsMainPass; if( m_isMainOutputNode ) { // We cannot use UIUtils.MasterNodeOnTexture.height since this method can be // called before UIUtils is initialized m_insideSize.y = 55; } else { m_insideSize.y = 0; } //IsMainOutputNode = m_mainMPMasterNode; if( source != SetTemplateSource.HotCodeReload ) { //Only set this if no hotcode reload happens ( via new shader or load ) m_isInvisible = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible ? InvisibilityStatus.LockedInvisible : InvisibilityStatus.Visible; } else { // On hot code reload we only need to verify if template pass visibility data changes // and change accordingly if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].IsInvisible ) { if( m_isInvisible != InvisibilityStatus.LockedInvisible ) m_isInvisible = InvisibilityStatus.LockedInvisible; } else { if( m_isInvisible == InvisibilityStatus.LockedInvisible ) { m_isInvisible = InvisibilityStatus.Visible; } } } m_invisibleOptions = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InvisibleOptions; m_originalPassName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; if( !hotCodeOrRead ) { if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Index > -1 ) { //m_subShaderLODStr = m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id; ShaderLOD = Convert.ToInt32( m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Data ); } else { ShaderLOD = 0; } } m_shaderNameIsTitle = IsMainOutputNode; m_fetchMasterNodeCategory = fetchMasterNodeCategory; m_templateGUID = m_templateMultiPass.GUID; UpdatePortInfo(); RegisterProperties(); // template is null when hot code reloading or loading from file so inspector name shouldn't be changed if( !hotCodeOrRead ) { m_customInspectorName = m_templateMultiPass.CustomInspectorContainer.Data; if( m_isMainOutputNode ) { m_passSelector.Clear(); m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] ); } } else { //Hotcode reload or ReadFromString // Setup is only made if internal pass array is null if( m_isMainOutputNode ) { m_passSelector.Setup( m_templateMultiPass.SubShaders[ m_subShaderIdx ] ); } } SetupCustomOptionsFromTemplate( template != null ); if( string.IsNullOrEmpty( m_fallbackHelper.RawFallbackShader ) ) m_fallbackHelper.RawFallbackShader = m_templateMultiPass.FallbackContainer.Data; //bool updateInfofromTemplate = UpdatePortInfo(); //if( updateInfofromTemplate ) //{ m_subShaderModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); m_passModule.FetchDataFromTemplate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules ); //} //RegisterProperties(); if( writeDefaultData ) { //ShaderName = m_templateMultiPass.DefaultShaderName; ShaderName = m_shaderName; m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; if( !m_templateMultiPass.IsSinglePass /*&& !m_shaderNameIsTitle*/ ) { if( m_templateMultiPass.SubShaders[ 0 ].MainPass != m_passIdx ) SetClippedTitle( m_passName ); } } UpdateSubShaderPassStr(); if( m_isMainOutputNode ) m_fireTemplateChange = true; } else { m_invalidNode = true; } } public override void OnRefreshLinkedPortsComplete() { if( m_invalidNode ) return; if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD ) ConfigHDPorts(); SetReadOptions(); } public void SetReadOptions() { m_passOptions.SetReadOptions(); if( m_isMainOutputNode ) m_subShaderOptions.SetReadOptions(); } bool UpdatePortInfo() { List inputDataList = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].InputDataList; int count = inputDataList.Count; if( count != m_inputPorts.Count ) { DeleteAllInputConnections( true ); for( int i = 0; i < count; i++ ) { InputPort port = AddInputPort( inputDataList[ i ].DataType, false, inputDataList[ i ].PortName, inputDataList[ i ].OrderId, inputDataList[ i ].PortCategory, inputDataList[ i ].PortUniqueId ); port.ExternalLinkId = inputDataList[ i ].LinkId; m_hasLinkPorts = m_hasLinkPorts || !string.IsNullOrEmpty( inputDataList[ i ].LinkId ); } return true; } else { for( int i = 0; i < count; i++ ) { m_inputPorts[ i ].ChangeProperties( inputDataList[ i ].PortName, inputDataList[ i ].DataType, false ); m_inputPorts[ i ].ExternalLinkId = inputDataList[ i ].LinkId; } return false; } } public void SetPropertyActionFromItem( TemplateModulesHelper module, TemplateActionItem item ) { // this was added because when switching templates the m_mainMasterNodeRef was not properly set yet and was causing issues, there's probably a better place for this if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) { m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; } TemplateModulesHelper subShaderModule = m_isMainOutputNode ? m_subShaderModule : m_mainMasterNodeRef.SubShaderModule; switch( item.PropertyAction ) { case PropertyActionsEnum.CullMode: { if( item.CopyFromSubShader ) { module.CullModeHelper.CurrentCullMode = subShaderModule.CullModeHelper.CurrentCullMode; } else { module.CullModeHelper.CurrentCullMode = item.ActionCullMode; } } break; case PropertyActionsEnum.ColorMask: { if( item.CopyFromSubShader ) module.ColorMaskHelper.ColorMask = subShaderModule.ColorMaskHelper.ColorMask; else module.ColorMaskHelper.ColorMask = item.ColorMask.GetColorMask( module.ColorMaskHelper.ColorMask ); } break; case PropertyActionsEnum.ColorMask1: { if( item.CopyFromSubShader ) module.ColorMaskHelper1.ColorMask = subShaderModule.ColorMaskHelper1.ColorMask; else module.ColorMaskHelper1.ColorMask = item.ColorMask1.GetColorMask( module.ColorMaskHelper1.ColorMask ); } break; case PropertyActionsEnum.ColorMask2: { if( item.CopyFromSubShader ) module.ColorMaskHelper2.ColorMask = subShaderModule.ColorMaskHelper2.ColorMask; else module.ColorMaskHelper2.ColorMask = item.ColorMask2.GetColorMask( module.ColorMaskHelper2.ColorMask ); } break; case PropertyActionsEnum.ColorMask3: { if( item.CopyFromSubShader ) module.ColorMaskHelper3.ColorMask = subShaderModule.ColorMaskHelper3.ColorMask; else module.ColorMaskHelper3.ColorMask = item.ColorMask3.GetColorMask( module.ColorMaskHelper3.ColorMask ); } break; case PropertyActionsEnum.ZWrite: { if( item.CopyFromSubShader ) { module.DepthOphelper.ZWriteModeValue = subShaderModule.DepthOphelper.ZWriteModeValue; } else { module.DepthOphelper.ZWriteModeValue = item.ActionZWrite; } } break; case PropertyActionsEnum.ZTest: { if( item.CopyFromSubShader ) { module.DepthOphelper.ZTestModeValue = subShaderModule.DepthOphelper.ZTestModeValue; } else { module.DepthOphelper.ZTestModeValue = item.ActionZTest; } } break; case PropertyActionsEnum.ZOffsetFactor: { if( item.CopyFromSubShader ) { module.DepthOphelper.OffsetFactorValue = subShaderModule.DepthOphelper.OffsetFactorValue; } else { module.DepthOphelper.OffsetFactorValue = item.ActionZOffsetFactor; } } break; case PropertyActionsEnum.ZOffsetUnits: { if( item.CopyFromSubShader ) { module.DepthOphelper.OffsetUnitsValue = subShaderModule.DepthOphelper.OffsetUnitsValue; } else { module.DepthOphelper.OffsetUnitsValue = item.ActionZOffsetUnits; } } break; case PropertyActionsEnum.BlendRGB: { if( item.CopyFromSubShader ) { module.BlendOpHelper.SourceFactorRGB = subShaderModule.BlendOpHelper.SourceFactorRGB; module.BlendOpHelper.DestFactorRGB = subShaderModule.BlendOpHelper.DestFactorRGB; } else { module.BlendOpHelper.SourceFactorRGB = item.ActionBlendRGBSource; module.BlendOpHelper.DestFactorRGB = item.ActionBlendRGBDest; } } break; case PropertyActionsEnum.BlendRGB1: { if( item.CopyFromSubShader ) { module.BlendOpHelper1.SourceFactorRGB = subShaderModule.BlendOpHelper1.SourceFactorRGB; module.BlendOpHelper1.DestFactorRGB = subShaderModule.BlendOpHelper1.DestFactorRGB; } else { module.BlendOpHelper1.SourceFactorRGB = item.ActionBlendRGBSource1; module.BlendOpHelper1.DestFactorRGB = item.ActionBlendRGBDest1; } } break; case PropertyActionsEnum.BlendRGB2: { if( item.CopyFromSubShader ) { module.BlendOpHelper2.SourceFactorRGB = subShaderModule.BlendOpHelper2.SourceFactorRGB; module.BlendOpHelper2.DestFactorRGB = subShaderModule.BlendOpHelper2.DestFactorRGB; } else { module.BlendOpHelper2.SourceFactorRGB = item.ActionBlendRGBSource2; module.BlendOpHelper2.DestFactorRGB = item.ActionBlendRGBDest2; } } break; case PropertyActionsEnum.BlendRGB3: { if( item.CopyFromSubShader ) { module.BlendOpHelper3.SourceFactorRGB = subShaderModule.BlendOpHelper3.SourceFactorRGB; module.BlendOpHelper3.DestFactorRGB = subShaderModule.BlendOpHelper3.DestFactorRGB; } else { module.BlendOpHelper3.SourceFactorRGB = item.ActionBlendRGBSource3; module.BlendOpHelper3.DestFactorRGB = item.ActionBlendRGBDest3; } } break; case PropertyActionsEnum.BlendAlpha: { if( item.CopyFromSubShader ) { module.BlendOpHelper.SourceFactorAlpha = subShaderModule.BlendOpHelper.SourceFactorAlpha; module.BlendOpHelper.DestFactorAlpha = subShaderModule.BlendOpHelper.DestFactorAlpha; } else { module.BlendOpHelper.CurrentAlphaIndex = 1; module.BlendOpHelper.SourceFactorAlpha = item.ActionBlendAlphaSource; module.BlendOpHelper.DestFactorAlpha = item.ActionBlendAlphaDest; } } break; case PropertyActionsEnum.BlendAlpha1: { if( item.CopyFromSubShader ) { module.BlendOpHelper1.SourceFactorAlpha = subShaderModule.BlendOpHelper1.SourceFactorAlpha; module.BlendOpHelper1.DestFactorAlpha = subShaderModule.BlendOpHelper1.DestFactorAlpha; } else { module.BlendOpHelper1.CurrentAlphaIndex = 1; module.BlendOpHelper1.SourceFactorAlpha = item.ActionBlendAlphaSource1; module.BlendOpHelper1.DestFactorAlpha = item.ActionBlendAlphaDest1; } } break; case PropertyActionsEnum.BlendAlpha2: { if( item.CopyFromSubShader ) { module.BlendOpHelper2.SourceFactorAlpha = subShaderModule.BlendOpHelper2.SourceFactorAlpha; module.BlendOpHelper2.DestFactorAlpha = subShaderModule.BlendOpHelper2.DestFactorAlpha; } else { module.BlendOpHelper2.CurrentAlphaIndex = 1; module.BlendOpHelper2.SourceFactorAlpha = item.ActionBlendAlphaSource2; module.BlendOpHelper2.DestFactorAlpha = item.ActionBlendAlphaDest2; } } break; case PropertyActionsEnum.BlendAlpha3: { if( item.CopyFromSubShader ) { module.BlendOpHelper3.SourceFactorAlpha = subShaderModule.BlendOpHelper3.SourceFactorAlpha; module.BlendOpHelper3.DestFactorAlpha = subShaderModule.BlendOpHelper3.DestFactorAlpha; } else { module.BlendOpHelper3.CurrentAlphaIndex = 1; module.BlendOpHelper3.SourceFactorAlpha = item.ActionBlendAlphaSource3; module.BlendOpHelper3.DestFactorAlpha = item.ActionBlendAlphaDest3; } } break; case PropertyActionsEnum.BlendOpRGB: { if( item.CopyFromSubShader ) { module.BlendOpHelper.BlendOpRGB = subShaderModule.BlendOpHelper.BlendOpRGB; } else { module.BlendOpHelper.BlendOpRGB = item.ActionBlendOpRGB; } } break; case PropertyActionsEnum.BlendOpAlpha: { if( item.CopyFromSubShader ) { module.BlendOpHelper.BlendOpAlpha = subShaderModule.BlendOpHelper.BlendOpAlpha; } else { module.BlendOpHelper.BlendOpAlpha = item.ActionBlendOpAlpha; } } break; case PropertyActionsEnum.StencilReference: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.ReferenceValue = subShaderModule.StencilBufferHelper.ReferenceValue; } else { module.StencilBufferHelper.ReferenceValue = item.ActionStencilReference; } } break; case PropertyActionsEnum.StencilReadMask: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.ReadMaskValue = subShaderModule.StencilBufferHelper.ReadMaskValue; } else { module.StencilBufferHelper.ReadMaskValue = item.ActionStencilReadMask; } } break; case PropertyActionsEnum.StencilWriteMask: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.WriteMaskValue = subShaderModule.StencilBufferHelper.WriteMaskValue; } else { module.StencilBufferHelper.WriteMaskValue = item.ActionStencilWriteMask; } } break; case PropertyActionsEnum.StencilComparison: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.ComparisonFunctionIdxValue = subShaderModule.StencilBufferHelper.ComparisonFunctionIdxValue; } else { module.StencilBufferHelper.ComparisonFunctionIdxValue = item.ActionStencilComparison; } } break; case PropertyActionsEnum.StencilPass: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.PassStencilOpIdxValue = subShaderModule.StencilBufferHelper.PassStencilOpIdxValue; } else { module.StencilBufferHelper.PassStencilOpIdxValue = item.ActionStencilPass; } } break; case PropertyActionsEnum.StencilFail: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.FailStencilOpIdxValue = subShaderModule.StencilBufferHelper.FailStencilOpIdxValue; } else { module.StencilBufferHelper.FailStencilOpIdxValue = item.ActionStencilFail; } } break; case PropertyActionsEnum.StencilZFail: { if( item.CopyFromSubShader ) { module.StencilBufferHelper.ZFailStencilOpIdxValue = subShaderModule.StencilBufferHelper.ZFailStencilOpIdxValue; } else { module.StencilBufferHelper.ZFailStencilOpIdxValue = item.ActionStencilZFail; } } break; case PropertyActionsEnum.RenderType: { module.TagsHelper.AddSpecialTag( TemplateSpecialTags.RenderType, item ); } break; case PropertyActionsEnum.RenderQueue: { module.TagsHelper.AddSpecialTag( TemplateSpecialTags.Queue, item ); } break; case PropertyActionsEnum.DisableBatching: { module.TagsHelper.AddSpecialTag( TemplateSpecialTags.DisableBatching, item ); } break; } } public void OnCustomPassOptionSelected( bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions ) { m_passOptions.OnCustomOptionSelected( isRefreshing, invertAction, this, uiItem, validActions ); } public void OnCustomSubShaderOptionSelected( bool isRefreshing, bool invertAction, TemplateOptionUIItem uiItem, params TemplateActionItem[] validActions ) { if( m_isMainOutputNode ) m_subShaderOptions.OnCustomOptionSelected( isRefreshing, invertAction, this, uiItem, validActions ); } void SetupCustomOptionsFromTemplate( bool newTemplate ) { m_passOptions.SetupCustomOptionsFromTemplate( this, newTemplate ); if( m_isMainOutputNode ) m_subShaderOptions.SetupCustomOptionsFromTemplate( this, newTemplate ); } void SetPassCustomOptionsInfo( TemplateMultiPassMasterNode masterNode ) { TemplateMultiPassMasterNode mainMasterNode = masterNode.IsMainOutputNode ? masterNode : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ); mainMasterNode.SubShaderOptions.SetSubShaderCustomOptionsPortsInfo( masterNode, ref m_currentDataCollector ); masterNode.PassOptions.SetCustomOptionsInfo( masterNode, ref m_currentDataCollector ); } void RefreshCustomOptionsDict() { m_passOptions.RefreshCustomOptionsDict(); if( m_isMainOutputNode ) m_subShaderOptions.RefreshCustomOptionsDict(); } void SetCategoryIdxFromTemplate() { int templateCount = m_containerGraph.ParentWindow.TemplatesManagerInstance.TemplateCount; for( int i = 0; i < templateCount; i++ ) { int idx = i + 1; TemplateMultiPass templateData = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( i ) as TemplateMultiPass; if( templateData != null && m_templateMultiPass != null && m_templateMultiPass.GUID.Equals( templateData.GUID ) ) m_masterNodeCategory = idx; } } public void CheckTemplateChanges() { if( m_invalidNode ) return; if( IsLODMainMasterNode ) { if( m_containerGraph.MultiPassMasterNodes.Count != m_templateMultiPass.MasterNodesRequired ) { if( m_availableCategories == null ) RefreshAvailableCategories(); if( DebugConsoleWindow.DeveloperMode ) Debug.Log( "Template Pass amount was changed. Rebuiling master nodes" ); m_containerGraph.ParentWindow.ReplaceMasterNode( m_availableCategories[ m_masterNodeCategory ], true ); } } } public override void OnNodeLogicUpdate( DrawInfo drawInfo ) { if( m_invalidNode ) { return; } base.OnNodeLogicUpdate( drawInfo ); if( m_templateMultiPass == null ) { // Hotcode reload has happened SetTemplate( null, false, true, m_subShaderIdx, m_passIdx , SetTemplateSource.HotCodeReload ); CheckTemplateChanges(); } if( m_reRegisterTemplateData ) { RegisterProperties(); } if( m_fetchMasterNodeCategory ) { if( m_availableCategories != null ) { m_fetchMasterNodeCategory = false; SetCategoryIdxFromTemplate(); } } if( m_fireTemplateChange ) { m_fireTemplateChange = false; m_containerGraph.FireMasterNodeReplacedEvent(); } if( m_subShaderModule.HasValidData ) { m_subShaderModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); } if( m_passModule.HasValidData ) { m_passModule.OnLogicUpdate( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules ); } if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) { m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; } if( m_refreshLODValueMasterNodes && ( EditorApplication.timeSinceStartup - m_refreshLODValueMasterNodesTimestamp ) > MaxLODEditTimestamp ) { m_refreshLODValueMasterNodes = false; m_refocusLODValueMasterNodes = true; m_containerGraph.SortLODMasterNodes(); } } public override void Draw( DrawInfo drawInfo ) { if( m_isInvisible == InvisibilityStatus.Visible ) { base.Draw( drawInfo ); } } public override void OnNodeLayout( DrawInfo drawInfo ) { if( m_invalidNode ) { if( m_isMainOutputNode ) { UIUtils.ShowMessage( "Invalid current template. Switching to Standard Surface", MessageSeverity.Error ); m_shaderModelIdx = 0; m_masterNodeCategory = 0; m_containerGraph.ParentWindow.ReplaceMasterNode( new MasterNodeCategoriesData( AvailableShaderTypes.SurfaceShader, m_shaderName ), false ); } return; } if( m_isInvisible != InvisibilityStatus.Visible ) { return; } if( !IsMainOutputNode ) { if( !IsInvisible && Docking ) { m_useSquareNodeTitle = true; TemplateMultiPassMasterNode master = ContainerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; m_position = master.TruePosition; m_position.height = 32; int masterIndex = ContainerGraph.MultiPassMasterNodes.NodesList.IndexOf( master ); int index = ContainerGraph.MultiPassMasterNodes.GetNodeRegisterIdx( UniqueId ); if( index > masterIndex ) { int backTracking = 0; for( int i = index - 1; i > masterIndex; i-- ) { if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking ) backTracking++; } m_position.y = master.TruePosition.yMax + 1 + 33 * ( backTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax; base.OnNodeLayout( drawInfo ); } else { int forwardTracking = 1; for( int i = index + 1; i < masterIndex; i++ ) { if( !ContainerGraph.MultiPassMasterNodes.NodesList[ i ].IsInvisible && ContainerGraph.MultiPassMasterNodes.NodesList[ i ].Docking ) forwardTracking++; } m_position.y = master.TruePosition.y - 33 * ( forwardTracking );// ContainerGraph.MultiPassMasterNodes.NodesList[ index - 1 ].TruePosition.yMax; base.OnNodeLayout( drawInfo ); } } else { m_useSquareNodeTitle = false; base.OnNodeLayout( drawInfo ); } } else { base.OnNodeLayout( drawInfo ); } } public override void OnNodeRepaint( DrawInfo drawInfo ) { base.OnNodeRepaint( drawInfo ); if( m_invalidNode ) return; if( m_isInvisible == InvisibilityStatus.Visible ) { if( m_containerGraph.IsInstancedShader ) { DrawInstancedIcon( drawInfo ); } } } public override void UpdateFromShader( Shader newShader ) { if( m_currentMaterial != null && m_currentMaterial.shader != newShader ) { m_currentMaterial.shader = newShader; } CurrentShader = newShader; } public override void UpdateMasterNodeMaterial( Material material ) { m_currentMaterial = material; FireMaterialChangedEvt(); } void DrawReloadButton() { if( GUILayout.Button( ReloadTemplateStr ) && m_templateMultiPass != null ) { m_templateMultiPass.Reload(); } } void DrawOpenTemplateButton() { GUILayout.BeginHorizontal(); { if( GUILayout.Button( OpenTemplateStr ) && m_templateMultiPass != null ) { try { string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID ); if( !string.IsNullOrEmpty( pathname ) ) { Shader selectedTemplate = AssetDatabase.LoadAssetAtPath( pathname ); if( selectedTemplate != null ) { AssetDatabase.OpenAsset( selectedTemplate, 1 ); } } } catch( Exception e ) { Debug.LogException( e ); } } if( GUILayout.Button( "\u25C4", GUILayout.Width( 18 ), GUILayout.Height( 18 ) ) && m_templateMultiPass != null ) { try { string pathname = AssetDatabase.GUIDToAssetPath( m_templateMultiPass.GUID ); if( !string.IsNullOrEmpty( pathname ) ) { Shader selectedTemplate = AssetDatabase.LoadAssetAtPath( pathname ); if( selectedTemplate != null ) { Event.current.Use(); Selection.activeObject = selectedTemplate; EditorGUIUtility.PingObject( Selection.activeObject ); } } } catch( Exception e ) { Debug.LogException( e ); } } } GUILayout.EndHorizontal(); } public override void DrawProperties() { base.DrawProperties(); if( m_invalidNode ) return; NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, CommonPropertiesStr, DrawCommonProperties ); NodeUtils.DrawPropertyGroup( ref m_subStringFoldout, SubShaderModuleStr, DrawSubShaderProperties ); NodeUtils.DrawPropertyGroup( ref m_passFoldout, PassModuleStr, DrawPassProperties ); DrawMaterialInputs( UIUtils.MenuItemToolbarStyle, false ); if( m_propertyOrderChanged ) { List mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList; int count = mpNodes.Count; for( int i = 0; i < count; i++ ) { if( mpNodes[ i ].UniqueId != UniqueId ) { mpNodes[ i ].CopyPropertyListFrom( this ); } } } #if SHOW_TEMPLATE_HELP_BOX EditorGUILayout.HelpBox( WarningMessage, MessageType.Warning ); #endif } // this will be removed later when PBR options are created void SetExtraDefine( string define ) { List nodes = this.ContainerGraph.MultiPassMasterNodes.NodesList; int count = nodes.Count; for( int nodeIdx = 0; nodeIdx < count; nodeIdx++ ) { nodes[ nodeIdx ].OptionsDefineContainer.AddDefine( "#define " + define, false ); } } void AddHDKeywords() { if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None ) return; if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD || !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR ) return; switch( m_hdSrpMaterialType ) { case HDSRPMaterialType.SubsurfaceScattering: { SetExtraDefine( SRPMaterialSubsurfaceScatteringKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialSubsurfaceScatteringKeyword ); if( m_thicknessPort != null && m_thicknessPort.HasOwnOrLinkConnection ) { SetExtraDefine( SRPMaterialTransmissionKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword ); } } break; case HDSRPMaterialType.Standard: break; case HDSRPMaterialType.Specular: { SetExtraDefine( SRPHDMaterialSpecularKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPHDMaterialSpecularKeyword ); } break; case HDSRPMaterialType.Anisotropy: { SetExtraDefine( SRPMaterialAnisotropyKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAnisotropyKeyword ); } break; case HDSRPMaterialType.Iridescence: { SetExtraDefine( SRPMaterialIridiscenceKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialIridiscenceKeyword ); } break; case HDSRPMaterialType.Translucent: { SetExtraDefine( SRPMaterialTransmissionKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransmissionKeyword ); } break; } if( m_coatMaskPort != null && m_coatMaskPort.HasOwnOrLinkConnection ) { SetExtraDefine( SRPMaterialClearCoatKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialClearCoatKeyword ); } } void FetchHDPorts() { if( m_fetchPorts ) { m_fetchPorts = false; if( m_inputPorts.Count > 4 ) { m_specularPort = GetInputPortByUniqueId( 3 ); m_metallicPort = GetInputPortByUniqueId( 4 ); m_coatMaskPort = GetInputPortByUniqueId( 11 ); m_diffusionProfilePort = GetInputPortByUniqueId( 12 ); m_subsurfaceMaskPort = GetInputPortByUniqueId( 13 ); m_thicknessPort = GetInputPortByUniqueId( 14 ); m_anisotropyPort = GetInputPortByUniqueId( 15 ); m_iridescenceThicknessPort = GetInputPortByUniqueId( 16 ); m_iridescenceMaskPort = GetInputPortByUniqueId( 17 ); m_indexOfRefractionPort = GetInputPortByUniqueId( 18 ); m_transmittanceColorPort = GetInputPortByUniqueId( 19 ); m_transmittanceAbsorptionDistancePort = GetInputPortByUniqueId( 20 ); m_transmittanceMaskPort = GetInputPortByUniqueId( 21 ); } } } void ConfigHDPorts() { if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.None ) return; if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType != TemplateSRPType.HD || !m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBR ) return; FetchHDPorts(); if( m_inputPorts.Count > 4 ) { switch( m_hdSrpMaterialType ) { case HDSRPMaterialType.SubsurfaceScattering: { m_specularPort.Visible = false; m_metallicPort.Visible = false; m_coatMaskPort.Visible = true; m_diffusionProfilePort.Visible = true; m_subsurfaceMaskPort.Visible = true; m_thicknessPort.Visible = true; m_anisotropyPort.Visible = false; m_iridescenceThicknessPort.Visible = false; m_iridescenceMaskPort.Visible = false; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; case HDSRPMaterialType.Standard: { m_specularPort.Visible = false; m_metallicPort.Visible = true; m_coatMaskPort.Visible = true; m_diffusionProfilePort.Visible = false; m_subsurfaceMaskPort.Visible = false; m_thicknessPort.Visible = false; m_anisotropyPort.Visible = false; m_iridescenceThicknessPort.Visible = false; m_iridescenceMaskPort.Visible = false; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; case HDSRPMaterialType.Specular: { m_specularPort.Visible = true; m_metallicPort.Visible = false; m_coatMaskPort.Visible = true; m_diffusionProfilePort.Visible = false; m_subsurfaceMaskPort.Visible = false; m_thicknessPort.Visible = false; m_anisotropyPort.Visible = false; m_iridescenceThicknessPort.Visible = false; m_iridescenceMaskPort.Visible = false; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; case HDSRPMaterialType.Anisotropy: { m_specularPort.Visible = false; m_metallicPort.Visible = true; m_coatMaskPort.Visible = true; m_diffusionProfilePort.Visible = false; m_subsurfaceMaskPort.Visible = false; m_thicknessPort.Visible = false; m_anisotropyPort.Visible = true; m_iridescenceThicknessPort.Visible = false; m_iridescenceMaskPort.Visible = false; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; case HDSRPMaterialType.Iridescence: { m_specularPort.Visible = false; m_metallicPort.Visible = true; m_coatMaskPort.Visible = true; m_diffusionProfilePort.Visible = false; m_subsurfaceMaskPort.Visible = false; m_thicknessPort.Visible = false; m_anisotropyPort.Visible = false; m_iridescenceThicknessPort.Visible = true; m_iridescenceMaskPort.Visible = true; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; case HDSRPMaterialType.Translucent: { m_specularPort.Visible = false; m_metallicPort.Visible = false; m_coatMaskPort.Visible = false; m_diffusionProfilePort.Visible = true; m_subsurfaceMaskPort.Visible = false; m_thicknessPort.Visible = true; m_anisotropyPort.Visible = false; m_iridescenceThicknessPort.Visible = false; m_iridescenceMaskPort.Visible = false; m_indexOfRefractionPort.Visible = false; m_transmittanceColorPort.Visible = false; m_transmittanceAbsorptionDistancePort.Visible = false; m_transmittanceMaskPort.Visible = false; } break; } } m_sizeIsDirty = ( m_isInvisible == InvisibilityStatus.Visible ); } public void SetShaderLODValueAndLabel( int value ) { if( ShaderLOD != value ) ShaderLOD = value; if( ContainerGraph.HasLODs ) { SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) ); } else { SetAdditonalTitleText( string.Empty ); } } void DrawLODAddRemoveButtons() { DrawLODAddRemoveButtons( -2 , true ); } void DrawLODAddRemoveButtons( int index , bool showRemove ) { if( GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( 15 ) ) ) { Vector2 minPos = Vec2Position; //bool newNodePositionMode = false; //if( newNodePositionMode ) //{ // for( int lod = 0; lod < ContainerGraph.LodMultiPassMasternodes.Count; lod++ ) // { // if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 ) // { // Vector2 currPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position; // if( currPos.y > minPos.y ) // { // minPos = currPos; // } // } // else // { // if( index < 0 ) // { // index = lod; // } // break; // } // } //} //else //{ for( int lod = ContainerGraph.LodMultiPassMasternodes.Count - 1 ; lod >= 0; lod-- ) { if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count != 0 ) { minPos = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList[ m_passIdx ].Vec2Position; break; } } //} minPos.y += HeightEstimate + 10; ContainerGraph.CreateLodMasterNodes( m_templateMultiPass, index, minPos ); } if( showRemove && GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( 15 ) ) ) { ContainerGraph.DestroyLodMasterNodes( index ); } } void SetupLODNodeName() { if( IsMainOutputNode ) { if( string.IsNullOrEmpty( m_mainLODName ) ) { m_shaderNameIsTitle = true; m_content.text = GenerateClippedTitle( m_croppedShaderName ); } else { m_shaderNameIsTitle = false; m_content.text = GenerateClippedTitle( m_mainLODName ); } } else { m_shaderNameIsTitle = false; m_content.text = GenerateClippedTitle( m_passName ); } } public void DrawLodRowItem(bool listMode) { float labelWidthBuffer = EditorGUIUtility.labelWidth; EditorGUILayout.BeginHorizontal(); if( listMode ) { if( GUILayout.Button( "\u25b6", GUILayout.Width( 18 ), GUILayout.Height( 18 ) ) ) { m_containerGraph.ParentWindow.FocusOnNode( this, 1, false, true ); } EditorGUI.BeginChangeCheck(); GUI.SetNextControlName( LodValueId + m_lodIndex ); m_shaderLOD = EditorGUILayoutIntField( string.Empty, m_shaderLOD, GUILayout.Width( 50 ) ); } else { EditorGUI.BeginChangeCheck(); EditorGUIUtility.labelWidth = 45; GUI.SetNextControlName( LodValueId + m_lodIndex ); m_shaderLOD = EditorGUILayoutIntField( "LOD", ShaderLOD, GUILayout.Width(100)); EditorGUIUtility.labelWidth = labelWidthBuffer; } if( EditorGUI.EndChangeCheck() ) { m_refreshLODValueMasterNodes = true; m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup; if( ContainerGraph.HasLODs ) SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) ); } EditorGUI.BeginChangeCheck(); GUI.SetNextControlName( LodNameId + ShaderLOD ); if( listMode ) { m_mainLODName = EditorGUILayoutTextField( string.Empty, m_mainLODName, GUILayout.Width( 100 ) ); } else { GUILayout.Space( -15 ); EditorGUIUtility.labelWidth = 45; m_mainLODName = EditorGUILayoutTextField( string.Empty, m_mainLODName ); EditorGUIUtility.labelWidth = labelWidthBuffer; } if( EditorGUI.EndChangeCheck() ) { // If reorder is scheduled make sure it doesn't happen when editing LOD name if( m_refreshLODValueMasterNodes ) m_refreshLODValueMasterNodesTimestamp = EditorApplication.timeSinceStartup; SetupLODNodeName(); } if( listMode ) DrawLODAddRemoveButtons( m_lodIndex, ( m_lodIndex >= 0) ); EditorGUILayout.EndHorizontal(); if( m_refocusLODValueMasterNodes ) { m_refocusLODValueMasterNodes = false; string focusedControl = GUI.GetNameOfFocusedControl(); if( focusedControl.Contains( LodValueId ) ) { GUI.FocusControl( LodValueId + m_lodIndex ); TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl ); if( te != null ) { te.SelectTextEnd(); } } else if( focusedControl.Contains( LodNameId ) ) { GUI.FocusControl( LodNameId + m_lodIndex ); TextEditor te = (TextEditor)GUIUtility.GetStateObject( typeof( TextEditor ), GUIUtility.keyboardControl ); if( te != null ) { te.SelectTextEnd(); } } } } void DrawLOD() { if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 ) { EditorGUILayout.Space(); DrawLodRowItem(true); EditorGUILayout.Space(); for( int i = 0; i < ContainerGraph.LodMultiPassMasternodes.Count; i++ ) { if( ContainerGraph.LodMultiPassMasternodes[ i ].NodesList.Count > 0 ) { TemplateMultiPassMasterNode masterNode = m_containerGraph.LodMultiPassMasternodes[ i ].NodesList[ m_passIdx ]; masterNode.DrawLodRowItem( true ); EditorGUILayout.Space(); } } EditorGUILayout.Space(); } } void DrawCommonProperties() { if( m_isMainOutputNode ) { //if( m_templateMultiPass.CanAddLODs && m_lodIndex == -1 ) //{ // if( GUILayoutButton( string.Empty, UIUtils.PlusStyle, GUILayout.Width( 15 ) ) ) // { // ContainerGraph.CreateLodMasterNodes( m_templateMultiPass, Vec2Position ); // } // if( GUILayoutButton( string.Empty, UIUtils.MinusStyle, GUILayout.Width( 15 ) ) ) // { // ContainerGraph.DestroyLodMasterNodes(); // } //} //EditorGUILayout.LabelField( "LOD: " + m_lodIndex ); DrawShaderName(); DrawCurrentShaderType(); if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD ) { if( m_templateMultiPass.CustomTemplatePropertyUI == CustomTemplatePropertyUIEnum.HDPBR ) { EditorGUI.BeginChangeCheck(); CurrentHDMaterialType = (HDSRPMaterialType)EditorGUILayoutEnumPopup( HDSRPMaterialTypeStr, m_hdSrpMaterialType ); if( EditorGUI.EndChangeCheck() ) ConfigHDPorts(); } } EditorGUI.BeginChangeCheck(); DrawPrecisionProperty( false ); if( EditorGUI.EndChangeCheck() ) ContainerGraph.CurrentPrecision = m_currentPrecisionType; DrawSamplingMacros(); m_drawInstancedHelper.Draw( this ); m_fallbackHelper.Draw( this ); DrawCustomInspector( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ); m_subShaderOptions.DrawCustomOptions( this ); m_dependenciesHelper.Draw( this, true ); } //EditorGUILayout.LabelField( m_subShaderIdxStr ); //EditorGUILayout.LabelField( m_passIdxStr ); if( IsLODMainMasterNode && m_templateMultiPass.CanAddLODs ) { NodeUtils.DrawNestedPropertyGroup( ref m_lodFoldout, AdditionalLODsStr, DrawLOD, DrawLODAddRemoveButtons ); } DrawOpenTemplateButton(); if( DebugConsoleWindow.DeveloperMode ) DrawReloadButton(); } public void DrawSubShaderProperties() { if( !m_isMainOutputNode ) { m_mainMasterNodeRef.DrawSubShaderProperties(); return; } bool noValidData = true; if( ShaderLOD > 0 ) { noValidData = false; if( m_templateMultiPass.CanAddLODs && m_containerGraph.LodMultiPassMasternodes[0].Count > 0 ) { DrawLodRowItem( false ); } else { ShaderLOD = EditorGUILayoutIntField( SubShaderLODValueLabel, ShaderLOD ); } } if( m_subShaderModule.HasValidData ) { noValidData = false; m_subShaderModule.Draw( this, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules ); //if( m_subShaderModule.IsDirty ) //{ // List mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList; // int count = mpNodes.Count; // for( int i = 0; i < count; i++ ) // { // if( mpNodes[ i ].SubShaderIdx == m_subShaderIdx && mpNodes[ i ].UniqueId != UniqueId ) // { // mpNodes[ i ].SubShaderModule.CopyFrom( m_subShaderModule ); // } // } // m_subShaderModule.IsDirty = false; //} } m_passSelector.Draw( this ); if( noValidData ) { EditorGUILayout.HelpBox( NoSubShaderPropertyStr, MessageType.Info ); } } void DrawPassProperties() { EditorGUI.BeginChangeCheck(); m_passName = EditorGUILayoutTextField( PassNameStr, m_passName ); if( EditorGUI.EndChangeCheck() ) { if( m_passName.Length > 0 ) { m_passName = UIUtils.RemoveShaderInvalidCharacters( m_passName ); } else { m_passName = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; } //if( !m_templateMultiPass.IsSinglePass ) // SetClippedTitle( m_passName ); } EditorGUILayout.LabelField( Pass.Modules.PassUniqueName ); if( m_passModule.HasValidData ) { m_passModule.Draw( this, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules, m_subShaderModule ); } m_usePass.Draw( this, false ); m_passOptions.DrawCustomOptions( this ); } bool CreateInstructionsForList( TemplateData templateData, ref List ports, ref string shaderBody, ref List vertexInstructions, ref List fragmentInstructions ) { if( ports.Count == 0 ) return true; AddHDKeywords(); bool isValid = true; //UIUtils.CurrentWindow.CurrentGraph.ResetNodesLocalVariables(); for( int i = 0; i < ports.Count; i++ ) { TemplateInputData inputData = templateData.InputDataFromId( ports[ i ].PortId ); if( ports[ i ].HasOwnOrLinkConnection ) { //if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.Lightweight ) //{ // if( ports[ i ].Name.Contains( "Normal" ) ) // { // m_currentDataCollector.AddToDirectives( SRPMaterialNormalMapKeyword, -1, AdditionalLineType.Define ); // } // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) ) // { // m_currentDataCollector.AddToDirectives( SRPMaterialBlendModeAlphaClipThresholdKeyword, -1, AdditionalLineType.Define ); // } // if( ports[ i ].Name.Contains( "Specular" ) ) // { // m_currentDataCollector.AddToDirectives( SRPLWMaterialSpecularKeyword, -1, AdditionalLineType.Define ); // } //} //else if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType == TemplateSRPType.HD ) //{ // if( ports[ i ].Name.Contains( "Normal" ) ) // { // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialNormalMapKeyword ); // } // if( ports[ i ].Name.Contains( "Alpha Clip Threshold" ) ) // { // //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialAlphaTestKeyword ); // } //} m_currentDataCollector.ResetInstructions(); m_currentDataCollector.ResetVertexInstructions(); m_currentDataCollector.PortCategory = ports[ i ].Category; string newPortInstruction = ports[ i ].GeneratePortInstructions( ref m_currentDataCollector ); if( m_currentDataCollector.DirtySpecialLocalVariables ) { string cleanVariables = m_currentDataCollector.SpecialLocalVariables.Replace( "\t", string.Empty ); m_currentDataCollector.AddInstructions( cleanVariables, false ); m_currentDataCollector.ClearSpecialLocalVariables(); } if( m_currentDataCollector.DirtyVertexVariables ) { string cleanVariables = m_currentDataCollector.VertexLocalVariables.Replace( "\t", string.Empty ); m_currentDataCollector.AddVertexInstruction( cleanVariables, UniqueId, false ); m_currentDataCollector.ClearVertexLocalVariables(); } // fill functions for( int j = 0; j < m_currentDataCollector.InstructionsList.Count; j++ ) { fragmentInstructions.Add( m_currentDataCollector.InstructionsList[ j ].PropertyName ); } for( int j = 0; j < m_currentDataCollector.VertexDataList.Count; j++ ) { vertexInstructions.Add( m_currentDataCollector.VertexDataList[ j ].PropertyName ); } m_templateMultiPass.SetPassInputData( m_subShaderIdx, m_passIdx, ports[ i ].PortId, newPortInstruction ); isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx, m_passIdx, inputData.TagId, ref shaderBody, newPortInstruction ) && isValid; } else { m_templateMultiPass.SetPassInputData( m_subShaderIdx, m_passIdx, ports[ i ].PortId, inputData.DefaultValue ); isValid = m_templateMultiPass.FillTemplateBody( m_subShaderIdx, m_passIdx, inputData.TagId, ref shaderBody, inputData.DefaultValue ) && isValid; } } return isValid; } public string BuildShaderBody( MasterNodeDataCollector inDataCollector, ref MasterNodeDataCollector outDataCollector ) { List list = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList; int currentSubshader = list[ 0 ].SubShaderIdx; m_templateMultiPass.SetShaderName( string.Format( TemplatesManager.NameFormatter, m_shaderName ) ); if( string.IsNullOrEmpty( m_customInspectorName ) ) { m_templateMultiPass.SetCustomInspector( string.Empty ); } else { m_templateMultiPass.SetCustomInspector( CustomInspectorFormatted ); } m_templateMultiPass.SetFallback( m_fallbackHelper.FallbackShader ); m_templateMultiPass.SetDependencies( m_dependenciesHelper.GenerateDependencies() ); if( inDataCollector != null ) outDataCollector.CopyPropertiesFromDataCollector( inDataCollector ); outDataCollector.TemplateDataCollectorInstance.CurrentSRPType = m_templateMultiPass.SRPtype; int lastActivePass = m_passSelector.LastActivePass; int count = list.Count; for( int i = 0; i < count; i++ ) { bool removePass = !m_passSelector.IsVisible( i ); list[ 0 ].CurrentTemplate.IdManager.SetPassIdUsage( i, removePass ); if( removePass ) continue; list[ i ].CollectData(); list[ i ].FillPassData( this, outDataCollector.TemplateDataCollectorInstance ); if( list[ i ].SubShaderIdx == currentSubshader ) { outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector ); } else { list[ i - 1 ].FillPropertyData( outDataCollector ); list[ i - 1 ].FillSubShaderData(); outDataCollector.Destroy(); outDataCollector = new MasterNodeDataCollector(); outDataCollector.CopyPropertiesFromDataCollector( list[ i ].CurrentDataCollector ); currentSubshader = list[ i ].SubShaderIdx; } // Last element must the one filling subshader data // as only there all properties are caught //if( i == ( count - 1 ) ) if( i == lastActivePass ) { list[ i ].FillPropertyData( outDataCollector ); } if( list[ i ].IsMainOutputNode ) list[ i ].FillSubShaderData(); } outDataCollector.TemplateDataCollectorInstance.BuildCBuffer( -1 ); //Fill uniforms is set on last since we need to collect all srp batcher data ( if needed ) //To set it into each pass for( int i = 0; i < count; i++ ) { bool removePass = !m_passSelector.IsVisible( i ); if( removePass ) continue; list[ i ].FillUniforms( outDataCollector.TemplateDataCollectorInstance ); } return list[ 0 ].CurrentTemplate.IdManager.BuildShader(); } public string BuildLOD( MasterNodeDataCollector inDataCollector, ref MasterNodeDataCollector outDataCollector ) { UsageListTemplateMultiPassMasterNodes bufferNodesList = ContainerGraph.MultiPassMasterNodes; int bufferMasterNodeId = ContainerGraph.CurrentMasterNodeId; ContainerGraph.MultiPassMasterNodes = ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ]; ContainerGraph.CurrentMasterNodeId = UniqueId; m_templateMultiPass.ResetState(); base.Execute( string.Empty, false ); string shaderBody = BuildShaderBody( inDataCollector, ref outDataCollector ); ContainerGraph.MultiPassMasterNodes = bufferNodesList; ContainerGraph.CurrentMasterNodeId = bufferMasterNodeId; return shaderBody; } public override Shader Execute( string pathname, bool isFullPath ) { ForceReordering(); MasterNodeDataCollector overallDataCollector = new MasterNodeDataCollector(); //BUILD LOD string allLodSubShaders = string.Empty; if( ContainerGraph.HasLODs ) { for( int lod = 0; lod < ContainerGraph.LodMultiPassMasternodes.Count; lod++ ) { if( ContainerGraph.LodMultiPassMasternodes[ lod ].Count == 0 ) break; TemplateMultiPassMasterNode newMasterNode = ContainerGraph.LodMultiPassMasternodes[ lod ].NodesList.Find( ( x ) => x.IsMainOutputNode ); string lodSubShaders = newMasterNode.BuildLOD( null, ref overallDataCollector ); lodSubShaders = TemplateHelperFunctions.GetSubShaderFrom( lodSubShaders ) + "\n"; allLodSubShaders += lodSubShaders; } } //BUILD MAIN m_templateMultiPass.ResetState(); base.Execute( pathname, isFullPath ); MasterNodeDataCollector dummy = new MasterNodeDataCollector(); string shaderBody = BuildShaderBody( overallDataCollector, ref dummy ); //COMBINE LOD WITH MAIN if( !string.IsNullOrEmpty( allLodSubShaders ) ) shaderBody = shaderBody.Replace( TemplatesManager.TemplateLODsTag, allLodSubShaders ); UpdateShaderAsset( ref pathname, ref shaderBody, isFullPath ); return m_currentShader; } public void CollectData() { if( m_inputPorts.Count == 0 ) return; ContainerGraph.ResetNodesLocalVariables(); m_optionsDefineContainer.RemoveTemporaries(); m_currentDataCollector = new MasterNodeDataCollector( this ); m_currentDataCollector.TemplateDataCollectorInstance.SetMultipassInfo( m_templateMultiPass, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.SRPType ); m_currentDataCollector.TemplateDataCollectorInstance.FillSpecialVariables( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ] ); SetupNodeCategories(); if( m_containerGraph.IsInstancedShader ) { string blockName = UIUtils.RemoveInvalidCharacters( ContainerGraph.GetMainMasterNodeOfLOD( -1 ).ShaderName ); m_currentDataCollector.SetupInstancePropertiesBlock( blockName ); } TemplateData templateData = m_templateMultiPass.CreateTemplateData( m_shaderName, string.Empty, m_subShaderIdx, m_passIdx ); m_currentDataCollector.TemplateDataCollectorInstance.BuildFromTemplateData( m_currentDataCollector, templateData ); if( m_currentDataCollector.TemplateDataCollectorInstance.InterpData.DynamicMax ) { int interpolatorAmount = -1; if( m_passModule.ShaderModelHelper.ValidData ) { interpolatorAmount = m_passModule.ShaderModelHelper.InterpolatorAmount; } else { TemplateModulesHelper subShaderModule = IsMainOutputNode ? m_subShaderModule : ( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ).SubShaderModule; if( subShaderModule.ShaderModelHelper.ValidData ) { interpolatorAmount = subShaderModule.ShaderModelHelper.InterpolatorAmount; } } if( interpolatorAmount > -1 ) { m_currentDataCollector.TemplateDataCollectorInstance.InterpData.RecalculateAvailableInterpolators( interpolatorAmount ); } } //Copy Properties { int shaderPropertiesAmount = m_templateMultiPass.AvailableShaderProperties.Count; for( int i = 0; i < shaderPropertiesAmount; i++ ) { m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.AvailableShaderProperties[ i ] ); } } //Copy Globals from SubShader level { int subShaderGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals.Count; for( int i = 0; i < subShaderGlobalAmount; i++ ) { m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].AvailableShaderGlobals[ i ] ); } } //Copy Globals from Pass Level { int passGlobalAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals.Count; for( int i = 0; i < passGlobalAmount; i++ ) { m_currentDataCollector.SoftRegisterUniform( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].AvailableShaderGlobals[ i ] ); } } // Check Current Options for property changes on subshader if( m_isMainOutputNode ) { CheckPropertyChangesOnOptions( m_subShaderOptions ); } // Check Current Options for property changes on pass CheckPropertyChangesOnOptions( m_passOptions ); //Set SRP info #if UNITY_2018_3_OR_NEWER if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ) ASEPackageManagerHelper.SetSRPInfoOnDataCollector( ref m_currentDataCollector ); #endif RegisterStandaloneFuntions(); m_containerGraph.CheckPropertiesAutoRegister( ref m_currentDataCollector ); //Sort ports by both List fragmentPorts = new List(); List vertexPorts = new List(); SortInputPorts( ref vertexPorts, ref fragmentPorts ); string shaderBody = templateData.TemplateBody; List vertexInstructions = new List(); List fragmentInstructions = new List(); bool validBody = true; //validBody = CreateInstructionsForList( templateData, ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; //ContainerGraph.ResetNodesLocalVariablesIfNot( MasterNodePortCategory.Vertex ); //validBody = CreateInstructionsForList( templateData, ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; validBody = CreateInstructionsForList( templateData, ref vertexPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; validBody = CreateInstructionsForList( templateData, ref fragmentPorts, ref shaderBody, ref vertexInstructions, ref fragmentInstructions ) && validBody; if( !m_isMainOutputNode && m_mainMasterNodeRef == null ) { m_mainMasterNodeRef = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; } TerrainDrawInstancedHelper drawInstanced = m_isMainOutputNode ? m_drawInstancedHelper : m_mainMasterNodeRef.DrawInstancedHelperInstance; drawInstanced.UpdateDataCollectorForTemplates( ref m_currentDataCollector, ref vertexInstructions ); templateData.ResetTemplateUsageData(); // Fill vertex interpolators assignment for( int i = 0; i < m_currentDataCollector.VertexInterpDeclList.Count; i++ ) { vertexInstructions.Add( m_currentDataCollector.VertexInterpDeclList[ i ] ); } vertexInstructions.AddRange( m_currentDataCollector.TemplateDataCollectorInstance.GetInterpUnusedChannels() ); //Fill common local variables and operations validBody = m_templateMultiPass.FillVertexInstructions( m_subShaderIdx, m_passIdx, vertexInstructions.ToArray() ) && validBody; validBody = m_templateMultiPass.FillFragmentInstructions( m_subShaderIdx, m_passIdx, fragmentInstructions.ToArray() ) && validBody; vertexInstructions.Clear(); vertexInstructions = null; fragmentInstructions.Clear(); fragmentInstructions = null; // Add Instanced Properties if( m_containerGraph.IsInstancedShader ) { m_currentDataCollector.OptimizeInstancedProperties(); m_currentDataCollector.TabifyInstancedVars(); //string cbufferBegin = m_currentDataCollector.IsSRP ? // string.Format( IOUtils.SRPInstancedPropertiesBegin, "UnityPerMaterial" ) : // string.Format( IOUtils.InstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName ); //string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.SRPInstancedPropertiesEnd, m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd; string cbufferBegin = m_currentDataCollector.IsSRP ? string.Format( IOUtils.LWSRPInstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName ) : string.Format( IOUtils.InstancedPropertiesBegin, m_currentDataCollector.InstanceBlockName ); string cBufferEnd = m_currentDataCollector.IsSRP ? ( string.Format( IOUtils.LWSRPInstancedPropertiesEnd, m_currentDataCollector.InstanceBlockName ) ) : IOUtils.InstancedPropertiesEnd; m_currentDataCollector.InstancedPropertiesList.Insert( 0, new PropertyDataCollector( -1, cbufferBegin ) ); m_currentDataCollector.InstancedPropertiesList.Add( new PropertyDataCollector( -1, cBufferEnd ) ); m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.InstancedPropertiesList ); } if( m_currentDataCollector.DotsPropertiesList.Count > 0 ) { m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)" ) ); m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "#ifdef UNITY_DOTS_INSTANCING_ENABLED" ) ); m_currentDataCollector.DotsPropertiesList.Insert( 0, new PropertyDataCollector( -1, "" ) ); m_currentDataCollector.DotsPropertiesList.Add( new PropertyDataCollector( -1, "UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)" ) ); m_currentDataCollector.DotsDefinesList.Add( new PropertyDataCollector( -1, "#endif" ) ); m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsPropertiesList ); m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.DotsDefinesList ); } TemplateShaderModelModule shaderModelModule = m_isMainOutputNode ? m_subShaderModule.ShaderModelHelper : m_mainMasterNodeRef.SubShaderModule.ShaderModelHelper; string shaderModel = string.Empty; if( m_passModule.ShaderModelHelper.ValidData ) { shaderModel = m_passModule.ShaderModelHelper.CurrentShaderModel; } else if( shaderModelModule.ValidData ) { shaderModel = shaderModelModule.CurrentShaderModel; } else if( m_templateMultiPass.GlobalShaderModel.IsValid ) { shaderModel = m_templateMultiPass.GlobalShaderModel.Value; } else { shaderModel = ( m_templateMultiPass.SRPtype == TemplateSRPType.HD ) ? "4.5" : "3.0"; } m_currentDataCollector.TemplateDataCollectorInstance.CheckInterpolatorOverflow( shaderModel, m_passName ); } public void CheckPropertyChangesOnOptions( TemplateOptionsUIHelper optionsUI ) { //Only Main LOD master node can change shader properties if( !IsLODMainMasterNode ) return; List options = optionsUI.PassCustomOptionsUI; for( int optionIdx = 0; optionIdx < options.Count; optionIdx++ ) { if( options[ optionIdx ].IsVisible ) { TemplateActionItem[] actionItems = options[ optionIdx ].CurrentOptionActions.Columns; for( int actionIdx = 0; actionIdx < actionItems.Length; actionIdx++ ) { if( actionItems[ actionIdx ].ActionType == AseOptionsActionType.SetShaderProperty && !string.IsNullOrEmpty( actionItems[ actionIdx ].ActionBuffer ) ) { TemplateShaderPropertyData data = m_templateMultiPass.GetShaderPropertyData( actionItems[ actionIdx ].ActionData ); if( data != null ) { string newPropertyValue = data.CreatePropertyForValue( actionItems[ actionIdx ].ActionBuffer ); CurrentTemplate.IdManager.SetReplacementText( data.FullValue, newPropertyValue ); } } } if( options[ optionIdx ].Options.Type == AseOptionsType.Field ) { foreach( var item in CurrentTemplate.IdManager.RegisteredTags ) { if( item.Output.Equals( options[ optionIdx ].Options.FieldInlineName ) ) { var node = options[ optionIdx ].Options.FieldValue.GetPropertyNode(); if( node != null && ( node.IsConnected || node.AutoRegister ) && options[ optionIdx ].Options.FieldValue.Active ) { item.Replacement = node.PropertyName; } } } } } } } public void FillPropertyData( MasterNodeDataCollector dataCollector = null ) { MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector; #if UNITY_2019_2_OR_NEWER // Temporary hack if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn && ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_0 ) { if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_AlphaCutoff" ) ) == null ) { if( !currDataCollector.ContainsProperty("_AlphaCutoff") ) { currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _AlphaCutoff(\"Alpha Cutoff \", Range(0, 1)) = 0.5", -1 ); } } if( m_templateMultiPass.AvailableShaderProperties.Find( x => x.PropertyName.Equals( "_EmissionColor" ) ) == null ) { if( !currDataCollector.ContainsProperty( "_EmissionColor" ) ) { currDataCollector.AddToProperties( UniqueId, "[HideInInspector] _EmissionColor(\"Emission Color\", Color) = (1,1,1,1)", -1 ); } } } #endif // here we add ASE attributes to the material properties that allows materials to communicate with ASE if( m_templateMultiPass.SRPtype != TemplateSRPType.BuiltIn ) { List list = new List( currDataCollector.PropertiesDict.Values ); list.Sort( ( x, y ) => { return x.OrderIndex.CompareTo( y.OrderIndex ); } ); for( int i = 0; i < list.Count; i++ ) { if( !( list[ i ].PropertyName.Contains( "[HideInInspector]" ) || list[ i ].PropertyName.Contains( "//" ) ) ) { list[ i ].PropertyName = "[ASEBegin]" + list[ i ].PropertyName; break; } } for( int i = list.Count - 1; i >= 0; i-- ) { if( !( list[ i ].PropertyName.Contains( "[HideInInspector]" ) || list[ i ].PropertyName.Contains( "//" ) ) ) { list[ i ].PropertyName = "[ASEEnd]" + list[ i ].PropertyName; break; } } } m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() ); } public void FillSubShaderData( /*MasterNodeDataCollector dataCollector = null */) { //MasterNodeDataCollector currDataCollector = ( dataCollector == null ) ? m_currentDataCollector : dataCollector; //// SubShader Data //m_templateMultiPass.SetPropertyData( currDataCollector.BuildUnformatedPropertiesStringArr() ); //templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModulePass, m_subShaderIdx, currDataCollector.GrabPassList ); if( ShaderLOD > -1 ) { string lodUniqueId = m_templateMultiPass.SubShaders[ m_subShaderIdx ].UniquePrefix + "Module" + m_templateMultiPass.SubShaders[ m_subShaderIdx ].LODContainer.Id; m_templateMultiPass.IdManager.SetReplacementText( lodUniqueId, "LOD " + ShaderLOD ); } SetModuleData( m_subShaderModule, true ); } public void FillPassData( TemplateMultiPassMasterNode masterNode, TemplateDataCollector mainTemplateDataCollector ) { if( m_isInvisible != InvisibilityStatus.Visible ) { if( masterNode.UniqueId != UniqueId ) { if( ( m_invisibleOptions & (int)InvisibleOptionsEnum.SyncProperties ) > 0 ) { PassModule.SyncWith( masterNode.PassModule ); } } int inputCount = m_inputPorts.Count; for( int i = 0; i < inputCount; i++ ) { if( m_inputPorts[ i ].HasExternalLink ) { TemplateMultiPassMasterNode linkedNode = m_inputPorts[ i ].ExternalLinkNode as TemplateMultiPassMasterNode; if( linkedNode != null ) { SetLinkedModuleData( linkedNode.PassModule ); } } } } SetModuleData( m_passModule, false ); if( m_currentDataCollector != null ) { if( Pass.CustomOptionsContainer.CopyOptionsFromMainPass ) { SetPassCustomOptionsInfo( m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode ); } else { SetPassCustomOptionsInfo( this ); } var inputArray = m_currentDataCollector.VertexInputList.ToArray(); m_templateMultiPass.SetPassData( TemplateModuleDataType.PassVertexData, m_subShaderIdx, m_passIdx, inputArray ); m_templateMultiPass.SetPassData( TemplateModuleDataType.PassInterpolatorData, m_subShaderIdx, m_passIdx, m_currentDataCollector.InterpolatorList.ToArray() ); SetHDInfoOnPass(); List afterNativesIncludePragmaDefineList = new List(); afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.IncludesList ); afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.DefinesList ); //includePragmaDefineList.AddRange( m_optionsDefineContainer.DefinesList ); afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.PragmasList ); m_currentDataCollector.AddASEMacros(); afterNativesIncludePragmaDefineList.AddRange( m_currentDataCollector.AfterNativeDirectivesList ); //includePragmaDefineList.AddRange( m_currentDataCollector.MiscList ); List beforeNatives = new List(); beforeNatives.AddRange( m_optionsDefineContainer.DefinesList ); beforeNatives.AddRange( m_currentDataCollector.BeforeNativeDirectivesList ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragmaBefore, m_subShaderIdx, m_passIdx, beforeNatives ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePragma, m_subShaderIdx, m_passIdx, afterNativesIncludePragmaDefineList ); m_currentDataCollector.TemplateDataCollectorInstance.CloseLateDirectives(); //Add Functions if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.FunctionsTag.IsValid ) { m_currentDataCollector.FunctionsList.InsertRange( 0, m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleFunctions, m_subShaderIdx, m_passIdx, m_currentDataCollector.FunctionsList ); } else { m_currentDataCollector.UniformsList.InsertRange( 0, m_currentDataCollector.TemplateDataCollectorInstance.LateDirectivesList ); m_currentDataCollector.UniformsList.AddRange( m_currentDataCollector.FunctionsList ); } //copy srp batch if present //if( m_currentDataCollector.IsSRP ) //{ // m_currentDataCollector.UniformsList.AddRange( mainTemplateDataCollector.SrpBatcherPropertiesList ); //} //m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals, m_subShaderIdx, m_passIdx, m_currentDataCollector.UniformsList ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputVert, m_subShaderIdx, m_passIdx, m_currentDataCollector.TemplateDataCollectorInstance.VertexInputParamsStr ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleInputFrag, m_subShaderIdx, m_passIdx, m_currentDataCollector.TemplateDataCollectorInstance.FragInputParamsStr ); if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessVControlTag.IsValid ) m_templateMultiPass.SetPassData( TemplateModuleDataType.VControl, m_subShaderIdx, m_passIdx, inputArray ); if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.IsValid ) m_templateMultiPass.SetPassData( TemplateModuleDataType.ControlData, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessControlData.GenerateControl( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict, m_currentDataCollector.VertexInputList ) ); if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.IsValid ) m_templateMultiPass.SetPassData( TemplateModuleDataType.DomainData, m_subShaderIdx, m_passIdx, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].TessDomainData.GenerateDomain( m_currentDataCollector.TemplateDataCollectorInstance.VertexDataDict, m_currentDataCollector.VertexInputList ) ); afterNativesIncludePragmaDefineList.Clear(); afterNativesIncludePragmaDefineList = null; beforeNatives.Clear(); beforeNatives = null; } m_templateMultiPass.SetPassData( TemplateModuleDataType.PassNameData, m_subShaderIdx, m_passIdx, string.Format( PassNameFormateStr, m_passName ) ); } public List CrossCheckSoftRegisteredUniformList( List uniformList ) { List newItems = new List(); for( int i = 0; i < uniformList.Count; i++ ) { if( !m_currentDataCollector.CheckIfSoftRegistered( uniformList[ i ].PropertyName ) ) { newItems.Add( uniformList[ i ] ); } } return newItems; } public void FillUniforms( TemplateDataCollector mainTemplateDataCollector ) { if( m_currentDataCollector.IsSRP ) { if( m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPBatcherTag.IsValid ) { List finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.SrpBatcherPropertiesList ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleSRPBatcher, m_subShaderIdx, m_passIdx, finalList ); finalList.Clear(); finalList = null; } else { List finalList = CrossCheckSoftRegisteredUniformList( mainTemplateDataCollector.FullSrpBatcherPropertiesList ); m_currentDataCollector.UniformsList.AddRange( finalList ); finalList.Clear(); finalList = null; } } m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleGlobals, m_subShaderIdx, m_passIdx, m_currentDataCollector.UniformsList ); } void SetHDInfoOnPass() { #if UNITY_2019_3_OR_NEWER if( ASEPackageManagerHelper.CurrentHDVersion > ASESRPVersions.ASE_SRP_6_9_1 ) return; #endif if( m_currentDataCollector.TemplateDataCollectorInstance.CurrentSRPType == TemplateSRPType.HD ) { TemplateModulesHelper subShaderHelper = null; TemplateModulesHelper passHelper = null; if( m_isMainOutputNode ) { subShaderHelper = m_subShaderModule; passHelper = m_passModule; } else { TemplateMultiPassMasterNode masterNode = m_containerGraph.CurrentMasterNode as TemplateMultiPassMasterNode; if( masterNode != null ) { subShaderHelper = masterNode.SubShaderModule; passHelper = masterNode.PassModule; } else { subShaderHelper = m_subShaderModule; passHelper = m_passModule; } } RenderQueue renderQueue = RenderQueue.Geometry; RenderType renderType = RenderType.Opaque; if( passHelper.TagsHelper.HasRenderInfo( ref renderType, ref renderQueue ) || subShaderHelper.TagsHelper.HasRenderInfo( ref renderType, ref renderQueue ) ) { if( renderType == RenderType.Transparent && renderQueue == RenderQueue.Transparent ) { SetExtraDefine( SRPMaterialTransparentKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialTransparentKeyword ); TemplatesBlendModule blendOpHelper = passHelper.BlendOpHelper.ValidBlendMode ? passHelper.BlendOpHelper : subShaderHelper.BlendOpHelper; if( blendOpHelper.IsAdditiveRGB ) { SetExtraDefine( SRPMaterialBlendModeAddKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAddKeyword ); } else if( blendOpHelper.IsAlphaBlendRGB ) { SetExtraDefine( SRPMaterialBlendModeAlphaKeyword ); //m_currentDataCollector.AddToDefines( UniqueId, SRPMaterialBlendModeAlphaKeyword ); } } } } } void SetLinkedModuleData( TemplateModulesHelper linkedModule ) { //if( linkedModule.AdditionalPragmas.ValidData ) //{ // linkedModule.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} //if( linkedModule.AdditionalIncludes.ValidData ) //{ // linkedModule.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} //if( linkedModule.AdditionalDefines.ValidData ) //{ // linkedModule.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} if( linkedModule.AdditionalDirectives.ValidData ) { linkedModule.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); } } void SetModuleData( TemplateModulesHelper module, bool isSubShader ) { if( isSubShader ) { //if ( module.AdditionalPragmas.ValidData ) //{ // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); //} //if ( module.AdditionalIncludes.ValidData ) //{ // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); //} //if ( module.AdditionalDefines.ValidData ) //{ // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); //} if( module.AdditionalDirectives.ValidData ) { module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Modules.IncludePragmaContainer ); } if( module.TagsHelper.ValidData ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleTag, m_subShaderIdx, module.TagsHelper.GenerateTags() ); } if( module.AllModulesMode ) { string body = module.GenerateAllModulesString( isSubShader ); m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.AllModules, m_subShaderIdx, body.Split( '\n' ) ); } if( module.ShaderModelHelper.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleShaderModel, m_subShaderIdx, module.ShaderModelHelper.GenerateShaderData( isSubShader ) ); } if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode, m_subShaderIdx, module.BlendOpHelper.CurrentBlendFactor ); } if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendMode ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode1, m_subShaderIdx, module.BlendOpHelper1.CurrentBlendFactor ); } if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendMode ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode2, m_subShaderIdx, module.BlendOpHelper2.CurrentBlendFactor ); } if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendMode ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendMode3, m_subShaderIdx, module.BlendOpHelper3.CurrentBlendFactor ); } if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp, m_subShaderIdx, module.BlendOpHelper.CurrentBlendOp ); } if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendOp ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp1, m_subShaderIdx, module.BlendOpHelper1.CurrentBlendOp ); } if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendOp ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp2, m_subShaderIdx, module.BlendOpHelper2.CurrentBlendOp ); } if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendOp ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleBlendOp3, m_subShaderIdx, module.BlendOpHelper3.CurrentBlendOp ); } if( module.AlphaToMaskHelper.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleAlphaToMask, m_subShaderIdx, module.AlphaToMaskHelper.GenerateShaderData( isSubShader ) ); } if( module.CullModeHelper.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleCullMode, m_subShaderIdx, module.CullModeHelper.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask, m_subShaderIdx, module.ColorMaskHelper.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper1.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask1, m_subShaderIdx, module.ColorMaskHelper1.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper2.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask2, m_subShaderIdx, module.ColorMaskHelper2.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper3.ValidAndIndependent ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleColorMask3, m_subShaderIdx, module.ColorMaskHelper3.GenerateShaderData( isSubShader ) ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZTest, m_subShaderIdx, module.DepthOphelper.CurrentZTestMode ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZwrite, m_subShaderIdx, module.DepthOphelper.CurrentZWriteMode ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset ) { m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleZOffset, m_subShaderIdx, module.DepthOphelper.CurrentOffset ); } if( module.StencilBufferHelper.ValidAndIndependent ) { CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back; string value = module.StencilBufferHelper.CreateStencilOp( cullMode ); m_templateMultiPass.SetSubShaderData( TemplateModuleDataType.ModuleStencil, m_subShaderIdx, value.Split( '\n' ) ); } } else { //if ( module.AdditionalPragmas.ValidData ) //{ // module.AdditionalPragmas.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} //if ( module.AdditionalIncludes.ValidData ) //{ // module.AdditionalIncludes.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} //if ( module.AdditionalDefines.ValidData ) //{ // module.AdditionalDefines.AddToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); //} List aboveUsePass = new List(); List belowUsePass = new List(); m_usePass.BuildUsePassInfo( m_currentDataCollector, ref aboveUsePass, ref belowUsePass ); //TODO Must place this on the correct place aboveUsePass.AddRange( belowUsePass ); //adding grab pass after use pass on purpose, so it wont be caught by them aboveUsePass.AddRange( m_currentDataCollector.GrabPassList ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModulePass, m_subShaderIdx, m_passIdx, aboveUsePass ); //m_templateMultiPass.SetPassData( TemplateModuleDataType.EndPass, m_subShaderIdx, m_passIdx, bellowUsePass); if( module.AdditionalDirectives.ValidData ) { module.AdditionalDirectives.AddAllToDataCollector( ref m_currentDataCollector, m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.IncludePragmaContainer ); } if( module.TagsHelper.ValidData ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleTag, m_subShaderIdx, m_passIdx, module.TagsHelper.GenerateTags() ); } if( module.AllModulesMode ) { string body = module.GenerateAllModulesString( isSubShader ); m_templateMultiPass.SetPassData( TemplateModuleDataType.AllModules, m_subShaderIdx, m_passIdx, body.Split( '\n' ) ); } if( module.ShaderModelHelper.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleShaderModel, m_subShaderIdx, m_passIdx, module.ShaderModelHelper.GenerateShaderData( isSubShader ) ); } if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendMode ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode, m_subShaderIdx, m_passIdx, module.BlendOpHelper.CurrentBlendFactor ); } if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendMode ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode1, m_subShaderIdx, m_passIdx, module.BlendOpHelper1.CurrentBlendFactor ); } if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendMode ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode2, m_subShaderIdx, m_passIdx, module.BlendOpHelper2.CurrentBlendFactor ); } if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendMode ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendMode3, m_subShaderIdx, m_passIdx, module.BlendOpHelper3.CurrentBlendFactor ); } if( module.BlendOpHelper.IndependentModule && module.BlendOpHelper.ValidBlendOp ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp, m_subShaderIdx, m_passIdx, module.BlendOpHelper.CurrentBlendOp ); } if( module.BlendOpHelper1.IndependentModule && module.BlendOpHelper1.ValidBlendOp ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp1, m_subShaderIdx, m_passIdx, module.BlendOpHelper1.CurrentBlendOp ); } if( module.BlendOpHelper2.IndependentModule && module.BlendOpHelper2.ValidBlendOp ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp2, m_subShaderIdx, m_passIdx, module.BlendOpHelper2.CurrentBlendOp ); } if( module.BlendOpHelper3.IndependentModule && module.BlendOpHelper3.ValidBlendOp ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleBlendOp3, m_subShaderIdx, m_passIdx, module.BlendOpHelper3.CurrentBlendOp ); } if( module.AlphaToMaskHelper.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleAlphaToMask, m_subShaderIdx, m_passIdx, module.AlphaToMaskHelper.GenerateShaderData( isSubShader ) ); } if( module.CullModeHelper.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleCullMode, m_subShaderIdx, m_passIdx, module.CullModeHelper.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask, m_subShaderIdx, m_passIdx, module.ColorMaskHelper.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper1.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask1, m_subShaderIdx, m_passIdx, module.ColorMaskHelper1.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper2.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask2, m_subShaderIdx, m_passIdx, module.ColorMaskHelper2.GenerateShaderData( isSubShader ) ); } if( module.ColorMaskHelper3.ValidAndIndependent ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleColorMask3, m_subShaderIdx, m_passIdx, module.ColorMaskHelper3.GenerateShaderData( isSubShader ) ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZTest ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZTest, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentZTestMode ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidZWrite ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZwrite, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentZWriteMode ); } if( module.DepthOphelper.IndependentModule && module.DepthOphelper.ValidOffset ) { m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleZOffset, m_subShaderIdx, m_passIdx, module.DepthOphelper.CurrentOffset ); } if( module.StencilBufferHelper.ValidAndIndependent ) { CullMode cullMode = ( module.CullModeHelper.ValidData ) ? module.CullModeHelper.CurrentCullMode : CullMode.Back; string value = module.StencilBufferHelper.CreateStencilOp( cullMode ); m_templateMultiPass.SetPassData( TemplateModuleDataType.ModuleStencil, m_subShaderIdx, m_passIdx, value.Split( '\n' ) ); } } } public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar ) { return "0"; } public override void Destroy() { base.Destroy(); m_drawInstancedHelper = null; m_optionsDefineContainer.Destroy(); m_optionsDefineContainer = null; m_passSelector.Destroy(); m_passSelector = null; m_subShaderOptions.Destroy(); m_passOptions.Destroy(); m_fallbackHelper.Destroy(); GameObject.DestroyImmediate( m_fallbackHelper ); m_fallbackHelper = null; m_usePass.Destroy(); GameObject.DestroyImmediate( m_usePass ); m_usePass = null; m_dependenciesHelper.Destroy(); m_dependenciesHelper = null; m_subShaderModule.Destroy(); m_subShaderModule = null; m_passModule.Destroy(); m_passModule = null; if( m_lodIndex == -1 ) { ContainerGraph.MultiPassMasterNodes.RemoveNode( this ); } else { ContainerGraph.LodMultiPassMasternodes[ m_lodIndex ].RemoveNode( this ); } } void UpdateSubShaderPassStr() { //m_subShaderIdxStr = SubShaderModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Idx; //m_passIdxStr = PassModuleStr + m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Idx; } public override void ReadFromString( ref string[] nodeParams ) { base.ReadFromString( ref nodeParams ); try { string currShaderName = GetCurrentParam( ref nodeParams ); if( currShaderName.Length > 0 ) currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName ); m_templateGUID = GetCurrentParam( ref nodeParams ); bool hasUniqueName = false; if( UIUtils.CurrentShaderVersion() > PASS_UNIQUE_ID_VERSION ) { hasUniqueName = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); } if( hasUniqueName ) m_passUniqueId = GetCurrentParam( ref nodeParams ); m_subShaderIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); m_passIdx = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); if( UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION ) { if( m_lodIndex != -1 ) { m_containerGraph.MultiPassMasterNodes.RemoveNode( this ); m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].AddNode( this ); } } m_passName = GetCurrentParam( ref nodeParams ); SetTemplate( null, false, true, m_subShaderIdx, m_passIdx, SetTemplateSource.ShaderLoad ); ////If value gotten from template is > -1 then it contains the LOD field ////and we can properly write the value //if( m_subShaderLOD > -1 ) //{ // m_subShaderLOD = subShaderLOD; //} // only in here, after SetTemplate, we know if shader name is to be used as title or not ShaderName = currShaderName; m_visiblePorts = Convert.ToInt32( GetCurrentParam( ref nodeParams ) ); m_subShaderModule.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); m_passModule.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); if( UIUtils.CurrentShaderVersion() > 15308 ) { m_fallbackHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); m_dependenciesHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( UIUtils.CurrentShaderVersion() > 15402 ) { m_usePass.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( UIUtils.CurrentShaderVersion() > 15409 ) { m_hdSrpMaterialType = (HDSRPMaterialType)Enum.Parse( typeof( HDSRPMaterialType ), GetCurrentParam( ref nodeParams ) ); } if( UIUtils.CurrentShaderVersion() > 15501 ) { if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION ) m_subShaderOptions.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); m_passOptions.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > PASS_SELECTOR_VERSION ) { m_passSelector.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > 16203 ) { m_drawInstancedHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_isMainOutputNode && UIUtils.CurrentShaderVersion() > LOD_SUBSHADER_VERSION ) { m_mainLODName = GetCurrentParam( ref nodeParams ); SetupLODNodeName(); } else { m_content.text = GenerateClippedTitle( m_passName ); } if( UIUtils.CurrentShaderVersion() > 18302 ) SamplingMacros = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) ); else SamplingMacros = false; //if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass ) //{ // SetClippedTitle( m_passName ); //} } catch( Exception e ) { Debug.LogException( e, this ); } m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader; m_containerGraph.CurrentPrecision = m_currentPrecisionType; } public override void WriteToString( ref string nodeInfo, ref string connectionsInfo ) { base.WriteToString( ref nodeInfo, ref connectionsInfo ); IOUtils.AddFieldValueToString( ref nodeInfo, ShaderName ); IOUtils.AddFieldValueToString( ref nodeInfo, m_templateGUID ); bool hasUniquePassName = Pass.Modules.HasPassUniqueName; IOUtils.AddFieldValueToString( ref nodeInfo, hasUniquePassName ); if( hasUniquePassName ) { IOUtils.AddFieldValueToString( ref nodeInfo, Pass.Modules.PassUniqueName ); } IOUtils.AddFieldValueToString( ref nodeInfo, m_subShaderIdx ); IOUtils.AddFieldValueToString( ref nodeInfo, m_passIdx ); IOUtils.AddFieldValueToString( ref nodeInfo, m_passName ); IOUtils.AddFieldValueToString( ref nodeInfo, m_visiblePorts ); m_subShaderModule.WriteToString( ref nodeInfo ); m_passModule.WriteToString( ref nodeInfo ); m_fallbackHelper.WriteToString( ref nodeInfo ); m_dependenciesHelper.WriteToString( ref nodeInfo ); m_usePass.WriteToString( ref nodeInfo ); IOUtils.AddFieldValueToString( ref nodeInfo, m_hdSrpMaterialType ); if( m_isMainOutputNode ) m_subShaderOptions.WriteToString( ref nodeInfo ); m_passOptions.WriteToString( ref nodeInfo ); if( m_isMainOutputNode ) { m_passSelector.WriteToString( ref nodeInfo ); m_drawInstancedHelper.WriteToString( ref nodeInfo ); } if( m_isMainOutputNode ) IOUtils.AddFieldValueToString( ref nodeInfo, m_mainLODName ); IOUtils.AddFieldValueToString( ref nodeInfo, m_samplingMacros ); } public override void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) { base.ReadFromString( ref nodeParams ); try { string currShaderName = GetCurrentParam( ref nodeParams ); if( currShaderName.Length > 0 ) currShaderName = UIUtils.RemoveShaderInvalidCharacters( currShaderName ); string templateGUID = GetCurrentParam( ref nodeParams ); string templateShaderName = string.Empty; if( UIUtils.CurrentShaderVersion() > 13601 ) { templateShaderName = GetCurrentParam( ref nodeParams ); } TemplateMultiPass template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplate( templateGUID ) as TemplateMultiPass; if( template != null ) { m_templateGUID = templateGUID; SetTemplate( null, false, true, 0, 0,SetTemplateSource.ShaderLoad ); } else { template = m_containerGraph.ParentWindow.TemplatesManagerInstance.GetTemplateByName( templateShaderName ) as TemplateMultiPass; if( template != null ) { m_templateGUID = template.GUID; SetTemplate( null, false, true, 0, 0, SetTemplateSource.ShaderLoad ); } else { m_masterNodeCategory = -1; } } if( m_invalidNode ) return; // only in here, after SetTemplate, we know if shader name is to be used as title or not ShaderName = currShaderName; if( UIUtils.CurrentShaderVersion() > 13902 ) { //BLEND MODULE if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendMode ) { m_subShaderModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendMode ) { m_passModule.BlendOpHelper.ReadBlendModeFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_templateMultiPass.SubShaders[ 0 ].Modules.BlendData.ValidBlendOp ) { m_subShaderModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.BlendData.ValidBlendOp ) { m_passModule.BlendOpHelper.ReadBlendOpFromString( ref m_currentReadParamIdx, ref nodeParams ); } //CULL MODE if( m_templateMultiPass.SubShaders[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid ) { m_subShaderModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.CullModeData.DataCheck == TemplateDataCheck.Valid ) { m_passModule.CullModeHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } //COLOR MASK if( m_templateMultiPass.SubShaders[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) { m_subShaderModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.ColorMaskData.DataCheck == TemplateDataCheck.Valid ) { m_passModule.ColorMaskHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } //STENCIL BUFFER if( m_templateMultiPass.SubShaders[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid ) { m_subShaderModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.StencilData.DataCheck == TemplateDataCheck.Valid ) { m_passModule.StencilBufferHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } } if( UIUtils.CurrentShaderVersion() > 14202 ) { //DEPTH OPTIONS if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZWrite ) { m_subShaderModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZWrite ) { m_passModule.DepthOphelper.ReadZWriteFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidZTest ) { m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidZTest ) { m_subShaderModule.DepthOphelper.ReadZTestFromString( ref m_currentReadParamIdx, ref nodeParams ); } if( m_templateMultiPass.SubShaders[ 0 ].Modules.DepthData.ValidOffset ) { m_subShaderModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.DepthData.ValidOffset ) { m_passModule.DepthOphelper.ReadOffsetFromString( ref m_currentReadParamIdx, ref nodeParams ); } } //TAGS if( UIUtils.CurrentShaderVersion() > 14301 ) { if( m_templateMultiPass.SubShaders[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid ) { m_subShaderModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } else if( m_templateMultiPass.SubShaders[ 0 ].Passes[ 0 ].Modules.TagData.DataCheck == TemplateDataCheck.Valid ) { m_passModule.TagsHelper.ReadFromString( ref m_currentReadParamIdx, ref nodeParams ); } } SamplingMacros = false; } catch( Exception e ) { Debug.LogException( e, this ); } m_containerGraph.CurrentCanvasMode = NodeAvailability.TemplateShader; } public void ForceOptionsRefresh() { m_passOptions.Refresh(); if( m_isMainOutputNode ) m_subShaderOptions.Refresh(); } public void SetPassVisible( string passName, bool visible ) { TemplateMultiPassMasterNode node = m_containerGraph.GetMasterNodeOfPass( passName, m_lodIndex ); if( node != null ) { m_passSelector.SetPassVisible( passName, visible ); node.IsInvisible = !visible; } } public override void RefreshExternalReferences() { if( m_invalidNode ) return; base.RefreshExternalReferences(); if( IsLODMainMasterNode ) { SetMasterNodeCategoryFromGUID( m_templateGUID ); } CheckTemplateChanges(); if( m_templateMultiPass != null && m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].Modules.SRPIsPBRHD && UIUtils.CurrentShaderVersion() < 15410 ) { FetchHDPorts(); m_hdSrpMaterialType = ( m_specularPort != null && m_specularPort.HasOwnOrLinkConnection ) ? HDSRPMaterialType.Specular : HDSRPMaterialType.Standard; ConfigHDPorts(); } if( ContainerGraph.HasLODs ) { SetClippedAdditionalTitle( string.Format( LodSubtitle, ShaderLOD ) ); } if( m_isMainOutputNode ) { List masterNodes = ( m_lodIndex == -1 ) ? m_containerGraph.MultiPassMasterNodes.NodesList : m_containerGraph.LodMultiPassMasternodes[ m_lodIndex ].NodesList; masterNodes.Sort( ( x, y ) => ( x.PassIdx.CompareTo( y.PassIdx ) )); int passAmount = m_templateMultiPass.SubShaders[ m_subShaderIdx ].PassAmount; if( passAmount != masterNodes.Count ) { UIUtils.ShowMessage( "Template master nodes amount was modified. Could not set correctly its visibility options." ); } else { for( int i = 0; i < passAmount; i++ ) { if( i != m_passIdx ) { masterNodes[ i ].IsInvisible = !m_passSelector.IsVisible( i ); } } } } } public override void ReadInputDataFromString( ref string[] nodeParams ) { //For a Template Master Node an input port data must be set by its template and not meta data if( UIUtils.CurrentShaderVersion() > 17007 ) return; int count = 0; if( UIUtils.CurrentShaderVersion() > 7003 ) { try { count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); } catch( Exception e ) { Debug.LogException( e ); } } else { count = ( m_oldInputCount < 0 ) ? m_inputPorts.Count : m_oldInputCount; } for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ ) { if( UIUtils.CurrentShaderVersion() < 5003 ) { int newId = VersionConvertInputPortId( i ); if( UIUtils.CurrentShaderVersion() > 23 ) { m_currentReadParamIdx++; } m_currentReadParamIdx++; if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length ) { m_currentReadParamIdx++; } } else { m_currentReadParamIdx++; m_currentReadParamIdx++; m_currentReadParamIdx++; bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] ); if( isEditable && m_currentReadParamIdx < nodeParams.Length ) { m_currentReadParamIdx++; } } } } //For a Template Master Node an input port data must be set by its template and not meta data public override void WriteInputDataToString( ref string nodeInfo ) { } public override float HeightEstimate { get { float heightEstimate = 0; heightEstimate = 32 + Constants.INPUT_PORT_DELTA_Y; if( m_templateMultiPass != null && !m_templateMultiPass.IsSinglePass ) { heightEstimate += 22; } float internalPortSize = 0; for( int i = 0; i < InputPorts.Count; i++ ) { if( InputPorts[ i ].Visible ) internalPortSize += 18 + Constants.INPUT_PORT_DELTA_Y; } return heightEstimate + Mathf.Max( internalPortSize, m_insideSize.y ); } } public HDSRPMaterialType CurrentHDMaterialType { get { return m_hdSrpMaterialType; } set { m_hdSrpMaterialType = value; if( m_isMainOutputNode ) { List mpNodes = UIUtils.CurrentWindow.CurrentGraph.MultiPassMasterNodes.NodesList; int count = mpNodes.Count; for( int i = 0; i < count; i++ ) { if( mpNodes[ i ].UniqueId != UniqueId ) { mpNodes[ i ].CurrentHDMaterialType = value; } } } } } public TemplateSubShader SubShader { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ]; } } public TemplatePass Pass { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ]; } } public int SubShaderIdx { get { return m_subShaderIdx; } } public int PassIdx { get { return m_passIdx; } } public TemplateMultiPass CurrentTemplate { get { return m_templateMultiPass; } } public TemplateModulesHelper SubShaderModule { get { return m_subShaderModule; } } public TemplateModulesHelper PassModule { get { return m_passModule; } } public string PassName { get { return m_templateMultiPass.SubShaders[ m_subShaderIdx ].Passes[ m_passIdx ].PassNameContainer.Data; } } public string PassUniqueName { get { return string.IsNullOrEmpty( m_passUniqueId ) ? m_originalPassName : m_passUniqueId; } } public string OriginalPassName { get { return m_originalPassName; } } public bool HasLinkPorts { get { return m_hasLinkPorts; } } public bool IsInvisible { get { return m_isInvisible != InvisibilityStatus.Visible; } set { if( m_isInvisible != InvisibilityStatus.LockedInvisible && !m_isMainOutputNode ) { m_isInvisible = value ? InvisibilityStatus.Invisible : InvisibilityStatus.Visible; if( value ) { for( int i = 0; i < m_inputPorts.Count; i++ ) { m_inputPorts[ i ].FullDeleteConnections(); } } } } } public TemplatePassSelectorHelper PassSelector { get { return m_passSelector; } } public TemplateOptionsUIHelper PassOptions { get { return m_passOptions; } } public TemplateOptionsUIHelper SubShaderOptions { get { return m_subShaderOptions; } } public TemplateOptionsDefinesContainer OptionsDefineContainer { get { return m_optionsDefineContainer; } } public TerrainDrawInstancedHelper DrawInstancedHelperInstance { get { return m_drawInstancedHelper; } } public bool InvalidNode { get { return m_invalidNode; } } public override void SetName( string name ) { ShaderName = name; } public bool IsLODMainFirstPass { get { return m_passIdx == 0 && m_lodIndex == -1; } } } }