You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

562 lines
16 KiB

// Amplify Shader Editor - Visual Shader Editing Tool
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using UnityEngine;
using UnityEditor;
using System;
namespace AmplifyShaderEditor
{
[Serializable]
[NodeAttributes( "Grab Screen Color", "Camera And Screen", "Grabed pixel color value from screen" )]
public sealed class ScreenColorNode : PropertyNode
{
private readonly Color ReferenceHeaderColor = new Color( 0.6f, 3.0f, 1.25f, 1.0f );
private const string SamplerType = "tex2D";
private const string GrabTextureDefault = "_GrabTexture";
private const string ScreenColorStr = "screenColor";
[SerializeField]
private TexReferenceType m_referenceType = TexReferenceType.Object;
[SerializeField]
private int m_referenceArrayId = -1;
[SerializeField]
private int m_referenceNodeId = -1;
[SerializeField]
private GUIStyle m_referenceIconStyle = null;
private ScreenColorNode m_referenceNode = null;
[SerializeField]
private bool m_normalize = false;
[SerializeField]
private bool m_useCustomGrab = false;
[SerializeField]
private float m_referenceWidth = -1;
//SRP specific code
private string OpaqueTextureDefine = "REQUIRE_OPAQUE_TEXTURE 1";
private string FetchOpaqueTexture = "SAMPLE_TEXTURE2D( _CameraOpaqueTexture, sampler_CameraOpaqueTexture, {0})";
private string FetchVarName = "fetchOpaqueVal";
#if !UNITY_2018_3_OR_NEWER
// Legacy SRP code
private string DeclareOpaqueTextureObject = "TEXTURE2D( _CameraOpaqueTexture);";
private string DeclareOpaqueTextureSampler = "SAMPLER( sampler_CameraOpaqueTexture);";
#endif
public ScreenColorNode() : base() { }
public ScreenColorNode( int uniqueId, float x, float y, float width, float height ) : base( uniqueId, x, y, width, height ) { }
protected override void CommonInit( int uniqueId )
{
base.CommonInit( uniqueId );
AddInputPort( WirePortDataType.FLOAT2, false, "UV" );
AddOutputColorPorts( "RGBA" );
m_currentParameterType = PropertyType.Global;
m_underscoredGlobal = true;
m_useVarSubtitle = true;
m_customPrefix = "Grab Screen ";
m_freeType = false;
m_drawAttributes = false;
m_showTitleWhenNotEditing = false;
m_textLabelWidth = 125;
m_showAutoRegisterUI = true;
m_globalDefaultBehavior = false;
}
protected override void OnUniqueIDAssigned()
{
base.OnUniqueIDAssigned();
if( m_referenceType == TexReferenceType.Object )
UIUtils.RegisterScreenColorNode( this );
}
void UpdateHeaderColor()
{
m_headerColorModifier = ( m_referenceType == TexReferenceType.Object ) ? Color.white : ReferenceHeaderColor;
}
public override void OnNodeLogicUpdate( DrawInfo drawInfo )
{
base.OnNodeLogicUpdate( drawInfo );
if( m_referenceNodeId > -1 && m_referenceNode == null )
{
m_referenceNode = UIUtils.GetScreenColorNode( m_referenceNodeId ) as ScreenColorNode;
if( m_referenceNode == null )
{
m_referenceNodeId = -1;
m_referenceArrayId = -1;
m_sizeIsDirty = true;
}
}
if( m_showSubtitle == m_containerGraph.IsSRP )
{
m_showSubtitle = !m_containerGraph.IsSRP;
m_sizeIsDirty = true;
}
}
protected override void ChangeSizeFinished()
{
if( m_referenceType == TexReferenceType.Instance )
{
m_position.width += 20;
}
}
public override void Draw( DrawInfo drawInfo )
{
base.Draw( drawInfo );
CheckReference();
if( SoftValidReference )
{
m_content.text = m_referenceNode.TitleContent.text + Constants.InstancePostfixStr;
SetAdditonalTitleText( m_referenceNode.AdditonalTitleContent.text );
if( m_referenceIconStyle == null )
{
m_referenceIconStyle = UIUtils.GetCustomStyle( CustomStyle.SamplerTextureIcon );
}
Rect iconPos = m_globalPosition;
iconPos.width = 19 * drawInfo.InvertedZoom;
iconPos.height = 19 * drawInfo.InvertedZoom;
iconPos.y += 6 * drawInfo.InvertedZoom;
iconPos.x += m_globalPosition.width - iconPos.width - 7 * drawInfo.InvertedZoom;
if( GUI.Button( iconPos, string.Empty, m_referenceIconStyle ) )
{
UIUtils.FocusOnNode( m_referenceNode, 1, true );
}
}
}
void CheckReference()
{
if( m_referenceType != TexReferenceType.Instance )
{
return;
}
if( m_referenceArrayId > -1 )
{
ParentNode newNode = UIUtils.GetScreenColorNode( m_referenceArrayId );
if( newNode == null || newNode.UniqueId != m_referenceNodeId )
{
m_referenceNode = null;
int count = UIUtils.GetScreenColorNodeAmount();
for( int i = 0; i < count; i++ )
{
ParentNode node = UIUtils.GetScreenColorNode( i );
if( node.UniqueId == m_referenceNodeId )
{
m_referenceNode = node as ScreenColorNode;
m_referenceArrayId = i;
break;
}
}
}
}
if( m_referenceNode == null && m_referenceNodeId > -1 )
{
m_referenceNodeId = -1;
m_referenceArrayId = -1;
}
}
public override void DrawMainPropertyBlock()
{
ShowAutoRegister();
EditorGUI.BeginChangeCheck();
m_referenceType = (TexReferenceType)EditorGUILayoutPopup( Constants.ReferenceTypeStr, (int)m_referenceType, Constants.ReferenceArrayLabels );
if( EditorGUI.EndChangeCheck() )
{
m_sizeIsDirty = true;
if( m_referenceType == TexReferenceType.Object )
{
UIUtils.RegisterScreenColorNode( this );
m_content.text = m_propertyInspectorName;
}
else
{
UIUtils.UnregisterScreenColorNode( this );
if( SoftValidReference )
{
m_content.text = m_referenceNode.TitleContent.text + Constants.InstancePostfixStr;
}
}
UpdateHeaderColor();
}
if( m_referenceType == TexReferenceType.Object )
{
EditorGUI.BeginDisabledGroup( m_containerGraph.IsSRP );
{
EditorGUI.BeginChangeCheck();
m_useCustomGrab = EditorGUILayoutToggle( "Custom Grab Pass", m_useCustomGrab );
EditorGUI.BeginDisabledGroup( !m_useCustomGrab );
DrawMainPropertyBlockNoPrecision();
EditorGUI.EndDisabledGroup();
m_normalize = EditorGUILayoutToggle( "Normalize", m_normalize );
if( EditorGUI.EndChangeCheck() )
{
UpdatePort();
if( m_useCustomGrab )
{
BeginPropertyFromInspectorCheck();
}
}
}
EditorGUI.EndDisabledGroup();
}
else
{
string[] arr = UIUtils.ScreenColorNodeArr();
bool guiEnabledBuffer = GUI.enabled;
if( arr != null && arr.Length > 0 )
{
GUI.enabled = true;
}
else
{
m_referenceArrayId = -1;
GUI.enabled = false;
}
m_referenceArrayId = EditorGUILayoutPopup( Constants.AvailableReferenceStr, m_referenceArrayId, arr );
GUI.enabled = guiEnabledBuffer;
EditorGUI.BeginDisabledGroup( m_containerGraph.IsSRP );
{
EditorGUI.BeginChangeCheck();
m_normalize = EditorGUILayoutToggle( "Normalize", m_normalize );
if( EditorGUI.EndChangeCheck() )
{
UpdatePort();
}
}
EditorGUI.EndDisabledGroup();
}
}
private void UpdatePort()
{
if( m_normalize )
m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT4, false );
else
m_inputPorts[ 0 ].ChangeType( WirePortDataType.FLOAT2, false );
}
public override void DrawTitle( Rect titlePos )
{
if( !m_isEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
{
GUI.Label( titlePos, "Grab Screen Color", UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) );
}
if( m_useCustomGrab || SoftValidReference )
{
base.DrawTitle( titlePos );
m_previousAdditonalTitle = m_additionalContent.text;
}
else
if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
{
SetAdditonalTitleTextOnCallback( GrabTextureDefault, ( instance, newSubTitle ) => instance.AdditonalTitleContent.text = string.Format( Constants.SubTitleVarNameFormatStr, newSubTitle ) );
//GUI.Label( titlePos, PropertyInspectorName, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) );
}
}
public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar )
{
if( dataCollector.IsTemplate && dataCollector.CurrentSRPType == TemplateSRPType.HD )
{
UIUtils.ShowMessage( "GrabPasses are not supported on Unity HD Scriptable Rendering Pipeline." );
return GetOutputColorItem( 0, outputId, "(0).xxxx" );
}
if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) )
return GetOutputColorItem( 0, outputId, m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory ) );
string valueName = string.Empty;
if( dataCollector.IsSRP )
{
#if !UNITY_2018_3_OR_NEWER
dataCollector.AddToUniforms( UniqueId, DeclareOpaqueTextureObject );
dataCollector.AddToUniforms( UniqueId, DeclareOpaqueTextureSampler );
#endif
valueName = FetchVarName + OutputId;
dataCollector.AddToDefines( UniqueId, OpaqueTextureDefine );
string uvCoords = GetUVCoords( ref dataCollector, ignoreLocalVar, false );
dataCollector.AddLocalVariable( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT4, valueName, string.Format( FetchOpaqueTexture, uvCoords ) );
}
else
{
base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalVar );
string propertyName = CurrentPropertyReference;
OnPropertyNameChanged();
bool emptyName = string.IsNullOrEmpty( m_propertyInspectorName ) || propertyName == GrabTextureDefault;
dataCollector.AddGrabPass( emptyName ? string.Empty : propertyName );
valueName = SetFetchedData( ref dataCollector, ignoreLocalVar );
}
m_outputPorts[ 0 ].SetLocalValue( valueName, dataCollector.PortCategory );
return GetOutputColorItem( 0, outputId, valueName );
}
public string SetFetchedData( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar )
{
string propertyName = CurrentPropertyReference;
bool isProjecting = m_normalize;
if( !m_inputPorts[ 0 ].IsConnected ) // to generate proper screen pos by itself
isProjecting = true;
if( ignoreLocalVar )
{
string samplerValue = SamplerType + ( isProjecting ? "proj" : "" ) + "( " + propertyName + ", " + GetUVCoords( ref dataCollector, ignoreLocalVar, isProjecting ) + " )";
return samplerValue;
}
if( m_outputPorts[ 0 ].IsLocalValue( dataCollector.PortCategory ) )
return m_outputPorts[ 0 ].LocalValue( dataCollector.PortCategory );
string samplerOp = SamplerType + ( isProjecting ? "proj" : "" ) + "( " + propertyName + ", " + GetUVCoords( ref dataCollector, ignoreLocalVar, isProjecting ) + " )";
dataCollector.AddLocalVariable( UniqueId, UIUtils.PrecisionWirePortToCgType( m_currentPrecisionType, m_outputPorts[ 0 ].DataType ) + " " + ScreenColorStr + OutputId + " = " + samplerOp + ";" );
return ScreenColorStr + OutputId;
}
public string GetUVCoords( ref MasterNodeDataCollector dataCollector, bool ignoreLocalVar, bool isProjecting )
{
string result = string.Empty;
if( m_inputPorts[ 0 ].IsConnected )
{
result = m_inputPorts[ 0 ].GenerateShaderForOutput( ref dataCollector, ( isProjecting ? WirePortDataType.FLOAT4 : WirePortDataType.FLOAT2 ), ignoreLocalVar, true );
}
else
{
string customScreenPos = null;
if( dataCollector.IsTemplate )
customScreenPos = dataCollector.TemplateDataCollectorInstance.GetScreenPos();
if( isProjecting )
result = GeneratorUtils.GenerateGrabScreenPosition( ref dataCollector, UniqueId, m_currentPrecisionType, !dataCollector.UsingCustomScreenPos, customScreenPos );
else
result = GeneratorUtils.GenerateGrabScreenPositionNormalized( ref dataCollector, UniqueId, m_currentPrecisionType, !dataCollector.UsingCustomScreenPos, customScreenPos );
}
if( isProjecting && !dataCollector.IsSRP )
return "UNITY_PROJ_COORD( " + result + " )";
else
return result;
}
public override void Destroy()
{
base.Destroy();
if( m_referenceType == TexReferenceType.Object )
{
UIUtils.UnregisterScreenColorNode( this );
}
}
public bool SoftValidReference
{
get
{
if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 )
{
m_referenceNode = UIUtils.GetScreenColorNode( m_referenceArrayId );
if( m_referenceNode == null )
{
m_referenceArrayId = -1;
m_referenceWidth = -1;
}
else if( m_referenceWidth != m_referenceNode.Position.width )
{
m_referenceWidth = m_referenceNode.Position.width;
m_sizeIsDirty = true;
}
return m_referenceNode != null;
}
return false;
}
}
public string CurrentPropertyReference
{
get
{
string propertyName = string.Empty;
if( m_referenceType == TexReferenceType.Instance && m_referenceArrayId > -1 )
{
ScreenColorNode node = UIUtils.GetScreenColorNode( m_referenceArrayId );
propertyName = ( node != null ) ? node.PropertyName : m_propertyName;
}
else if( !m_useCustomGrab )
{
propertyName = GrabTextureDefault;
}
else
{
propertyName = m_propertyName;
}
return propertyName;
}
}
public override void ReadFromString( ref string[] nodeParams )
{
base.ReadFromString( ref nodeParams );
if( UIUtils.CurrentShaderVersion() > 12 )
{
m_referenceType = (TexReferenceType)Enum.Parse( typeof( TexReferenceType ), GetCurrentParam( ref nodeParams ) );
if( UIUtils.CurrentShaderVersion() > 22 )
{
m_referenceNodeId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
}
else
{
m_referenceArrayId = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
}
if( m_referenceType == TexReferenceType.Instance )
{
UIUtils.UnregisterScreenColorNode( this );
}
UpdateHeaderColor();
}
if( UIUtils.CurrentShaderVersion() > 12101 )
{
m_useCustomGrab = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
}
else
{
m_useCustomGrab = true;
}
if( UIUtils.CurrentShaderVersion() > 14102 )
{
m_normalize = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
}
}
public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
{
base.WriteToString( ref nodeInfo, ref connectionsInfo );
IOUtils.AddFieldValueToString( ref nodeInfo, m_referenceType );
IOUtils.AddFieldValueToString( ref nodeInfo, ( ( m_referenceNode != null ) ? m_referenceNode.UniqueId : -1 ) );
IOUtils.AddFieldValueToString( ref nodeInfo, m_useCustomGrab );
IOUtils.AddFieldValueToString( ref nodeInfo, m_normalize );
}
public override void RefreshExternalReferences()
{
base.RefreshExternalReferences();
if( m_referenceType == TexReferenceType.Instance )
{
if( UIUtils.CurrentShaderVersion() > 22 )
{
m_referenceNode = UIUtils.GetNode( m_referenceNodeId ) as ScreenColorNode;
m_referenceArrayId = UIUtils.GetScreenColorNodeRegisterId( m_referenceNodeId );
}
else
{
m_referenceNode = UIUtils.GetScreenColorNode( m_referenceArrayId );
if( m_referenceNode != null )
{
m_referenceNodeId = m_referenceNode.UniqueId;
}
}
}
if( UIUtils.CurrentShaderVersion() <= 14102 )
{
if( m_inputPorts[ 0 ].DataType == WirePortDataType.FLOAT4 )
m_normalize = true;
else
m_normalize = false;
}
}
public override string PropertyName
{
get
{
if( m_useCustomGrab )
return base.PropertyName;
else
return GrabTextureDefault;
}
}
public override string GetPropertyValStr()
{
return PropertyName;
}
public override string DataToArray { get { return m_propertyName; } }
public override string GetUniformValue()
{
if( SoftValidReference )
{
if( m_referenceNode.IsConnected )
return string.Empty;
return m_referenceNode.GetUniformValue();
}
return "uniform sampler2D " + PropertyName + ";";
}
public override bool GetUniformData( out string dataType, out string dataName )
{
if( SoftValidReference )
{
//if ( m_referenceNode.IsConnected )
//{
// dataType = string.Empty;
// dataName = string.Empty;
//}
return m_referenceNode.GetUniformData( out dataType, out dataName );
}
dataType = "sampler2D";
dataName = PropertyName;
return true;
}
public override void CheckIfAutoRegister( ref MasterNodeDataCollector dataCollector )
{
if( m_autoRegister && m_connStatus != NodeConnectionStatus.Connected )
{
RegisterProperty( ref dataCollector );
string propertyName = CurrentPropertyReference;
bool emptyName = string.IsNullOrEmpty( m_propertyInspectorName ) || propertyName == GrabTextureDefault;
dataCollector.AddGrabPass( emptyName ? string.Empty : propertyName );
}
}
}
}