summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs')
-rw-r--r--Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs3778
1 files changed, 3778 insertions, 0 deletions
diff --git a/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs
new file mode 100644
index 00000000..179413d5
--- /dev/null
+++ b/Assets/ThirdParty/AmplifyShaderEditor/Plugins/Editor/Nodes/ParentNode.cs
@@ -0,0 +1,3778 @@
+// Amplify Shader Editor - Visual Shader Editing Tool
+// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
+
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace AmplifyShaderEditor
+{
+ public enum PreviewLocation
+ {
+ Auto,
+ TopCenter,
+ BottomCenter,
+ Left,
+ Right
+ }
+
+ public enum NodeMessageType
+ {
+ Error,
+ Warning,
+ Info
+ }
+
+ [Serializable]
+ public class ParentNode : UndoParentNode, ISerializationCallbackReceiver
+ {
+ public const int PreviewWidth = 128;
+ public const int PreviewHeight = 128;
+
+ protected readonly string[] PrecisionLabels = { "Float", "Half" };
+ protected readonly string[] PrecisionLabelsExtra = { "Float", "Half", "Inherit" };
+
+ private const double NodeClickTime = 0.2;
+ protected GUIContent PrecisionContent = new GUIContent( "Precision", "Changes the precision of internal calculations, using lower types saves some performance\nDefault: Float" );
+ private const int MoveCountBuffer = 3;// When testing for stopped movement we need to take Layout and Repaint into account for them not to interfere with tests
+ private const float MinInsideBoxWidth = 20;
+ private const float MinInsideBoxHeight = 10;
+
+ private const string WikiLinkStr = "online reference";
+
+ public delegate void OnNodeEvent( ParentNode node, bool testOnlySelected, InteractionMode interactionMode );
+ public delegate void OnNodeGenericEvent( ParentNode node );
+ public delegate void OnNodeReOrder( ParentNode node, int index );
+ public delegate void DrawPropertySection();
+ public delegate void OnSRPAction( int outputId, ref MasterNodeDataCollector dataCollector );
+
+ [SerializeField]
+ protected PrecisionType m_currentPrecisionType = PrecisionType.Inherit;
+
+ [SerializeField]
+ protected bool m_customPrecision = false;
+
+ [SerializeField]
+ protected InteractionMode m_defaultInteractionMode = InteractionMode.Other;
+
+ public event OnNodeEvent OnNodeStoppedMovingEvent;
+ public OnNodeGenericEvent OnNodeChangeSizeEvent;
+ public OnNodeGenericEvent OnNodeDestroyedEvent;
+ public event OnNodeReOrder OnNodeReOrderEvent;
+ public OnSRPAction OnLightweightAction;
+ public OnSRPAction OnHDAction;
+
+ [SerializeField]
+ private int m_uniqueId;
+
+ [SerializeField]
+ protected Rect m_position;
+
+ [SerializeField]
+ protected Rect m_unpreviewedPosition;
+
+ [SerializeField]
+ protected GUIContent m_content;
+
+ [SerializeField]
+ protected GUIContent m_additionalContent;
+
+ [SerializeField]
+ protected bool m_initialized;
+
+ [SerializeField]
+ protected NodeConnectionStatus m_connStatus;
+ protected bool m_selfPowered = false;
+
+ [SerializeField]
+ protected int m_activeConnections;
+
+ [SerializeField]
+ protected System.Type m_activeType;
+
+ [SerializeField]
+ protected int m_activePort;
+
+ [SerializeField]
+ protected int m_activeNode;
+
+ protected NodeRestrictions m_restrictions;
+
+ [SerializeField]
+ protected Color m_statusColor;
+
+ [SerializeField]
+ protected Rect m_propertyDrawPos;
+
+ // Ports
+ [SerializeField]
+ protected List<InputPort> m_inputPorts = new List<InputPort>();
+
+ protected Dictionary<int, InputPort> m_inputPortsDict = new Dictionary<int, InputPort>();
+
+ [SerializeField]
+ protected List<OutputPort> m_outputPorts = new List<OutputPort>();
+
+ protected Dictionary<int, OutputPort> m_outputPortsDict = new Dictionary<int, OutputPort>();
+
+ [SerializeField]
+ protected Rect m_globalPosition;
+
+ [SerializeField]
+ protected Rect m_headerPosition;
+
+ //private Vector2 m_tooltipOffset;
+
+ [SerializeField]
+ protected bool m_sizeIsDirty = false;
+
+ [SerializeField]
+ protected Vector2 m_extraSize;
+
+ [SerializeField]
+ protected Vector2 m_insideSize;
+
+ [SerializeField]
+ protected float m_fontHeight;
+
+ // Editor State save on Play Button
+ [SerializeField]
+ protected bool m_isDirty;
+
+ [SerializeField]
+ private int m_isMoving = 0;
+ [SerializeField]
+ private Rect m_lastPosition;
+
+ // Live Shader Gen
+ [SerializeField]
+ private bool m_saveIsDirty;
+
+ [SerializeField]
+ protected bool m_requireMaterialUpdate = false;
+
+ [SerializeField]
+ protected int m_commentaryParent = -1;
+
+ [SerializeField]
+ protected int m_depth = -1;
+
+ [SerializeField]
+ protected bool m_materialMode = false;
+
+ [SerializeField]
+ protected bool m_showPreview = false;
+
+ [SerializeField]
+ protected int m_previewMaterialPassId = -1;
+
+ protected bool m_useSquareNodeTitle = false;
+
+ [SerializeField]
+ protected bool m_continuousPreviewRefresh = false;
+ private bool m_previewIsDirty = true;
+
+ // Error Box Messages
+ private Rect m_errorBox;
+ private bool m_previousErrorMessage = false;
+ protected bool m_showErrorMessage = false;
+ protected NodeMessageType m_errorMessageTypeIsError = NodeMessageType.Error;
+ protected string m_errorMessageTooltip = string.Empty;
+
+ private GUIContent m_errorIcon = new GUIContent();
+ private GUIContent m_errorMessage = new GUIContent();
+ private GUIStyle m_errorCurrentStyle;
+
+ private const string ErrorTitle = "ERROR";
+ private const string WarningTitle = "WARNING";
+ private const string InfoTitle = "INFO";
+
+ // Drawing Node
+ protected PreviewLocation m_selectedLocation = PreviewLocation.Auto;
+ private int m_extraHeaderHeight = 0;
+ protected bool m_isVisible;
+ protected bool m_selected = false;
+ protected bool m_rmbIgnore;
+ protected GUIContent m_sizeContentAux;
+
+ protected uint m_currentReadParamIdx = 1;
+ protected bool m_reorderLocked = false;
+
+ protected Rect m_cachedPos;
+ protected Vector2 m_accumDelta = Vector2.zero;
+
+ private bool m_isOnGrid = false;
+ protected bool m_useInternalPortData = false;
+ protected bool m_autoDrawInternalPortData = true;
+ protected DrawOrder m_drawOrder = DrawOrder.Default;
+
+ protected bool m_movingInFrame = false;
+ protected float m_anchorAdjust = -1;
+
+ protected Color m_headerColor;
+
+ [SerializeField] // needs to be serialized because of Undo
+ protected Color m_headerColorModifier = Color.white;
+
+ protected bool m_infiniteLoopDetected = false;
+ protected int m_textLabelWidth = -1;
+
+ private bool m_linkVisibility = false;
+ [SerializeField]
+ protected bool m_hasTooltipLink = true;
+
+ protected int m_category = 0;
+
+ protected double m_lastTimeSelected;
+ private double m_tooltipTimestamp;
+ protected string m_tooltipText;
+
+ protected Rect m_unscaledRemainingBox;
+ protected Rect m_remainingBox;
+
+ private int m_visibleInputs = 0;
+ private int m_visibleOutputs = 0;
+
+ private double m_doubleClickTimestamp;
+ private const double DoubleClickTime = 0.25;
+
+ protected bool m_canExpand = true;
+
+ protected bool m_firstDraw = true;
+
+ protected int m_matrixId = -1;
+
+ private float m_paddingTitleLeft = 0;
+ private float m_paddingTitleRight = 0;
+
+ // Preview Fields
+ private Material m_previewMaterial = null;
+ private Shader m_previewShader = null;
+ protected string m_previewShaderGUID = string.Empty;
+ protected float m_marginPreviewLeft = 0;
+ protected bool m_globalShowPreview = false;
+ protected Rect m_unscaledPreviewRect;
+ protected Rect m_previewRect;
+ protected bool m_drawPreviewMaskButtons = true;
+ private int m_channelNumber = 0;
+ protected bool m_firstPreviewDraw = true;
+ [SerializeField]
+ protected bool m_drawPreview = true;
+ protected bool m_drawPreviewExpander = true;
+ private bool m_spherePreview = false;
+ protected bool m_drawPreviewAsSphere = false;
+ protected bool m_forceDrawPreviewAsPlane = false;
+ private bool m_finishPreviewRender = false;
+
+ private int m_cachedMainTexId = -1;
+ private int m_cachedMaskTexId = -1;
+ private int m_cachedPortsId = -1;
+ private int m_cachedPortId = -1;
+
+ private int m_cachedDrawSphereId = -1;
+ private int m_cachedInvertedZoomId = -1;
+ //private int m_cachedIsLinearId = -1;
+
+ private bool[] m_previewChannels = { true, true, true, false };
+
+ // Others
+ protected bool m_hasSubtitle = false;
+ protected bool m_showSubtitle = true;
+ protected bool m_hasLeftDropdown = false;
+ protected bool m_autoWrapProperties = false;
+ protected bool m_internalDataFoldout = true;
+ protected bool m_propertiesFoldout = true;
+ protected bool m_repopulateDictionaries = true;
+
+ protected Vector2 m_lastInputBottomRight = Vector2.zero;
+ protected Vector2 m_lastOutputBottomLeft = Vector2.zero;
+
+ private Vector4 m_portMask = Vector4.zero;
+
+ private Vector2 m_auxVector2 = Vector4.zero;
+ protected Rect m_auxRect;
+
+ protected PreviewLocation m_autoLocation;
+ protected Rect m_titlePos;
+ protected Rect m_addTitlePos;
+ protected Rect m_expandRect;
+ protected Rect m_dropdownRect;
+ protected Rect m_currInputPortPos;
+ protected Rect m_currOutputPortPos;
+ protected Color m_colorBuffer;
+
+ [SerializeField]
+ protected bool m_docking = false;
+
+ [SerializeField]
+ protected int m_visiblePorts = 0;
+
+ protected int m_graphDepth = 0;
+
+ protected int m_oldInputCount = -1;
+
+ protected bool m_dropdownEditing = false;
+
+ protected bool m_isNodeBeingCopied = false;
+
+ protected string m_previousTitle = string.Empty;
+
+ protected string m_previousAdditonalTitle = string.Empty;
+
+ private bool m_alive = true;
+
+ private double m_timedUpdateInitialValue;
+ private double m_timedUpdateInterval;
+ private bool m_fireTimedUpdateRequest = false;
+
+ public ParentNode()
+ {
+ m_position = new Rect( 0, 0, 0, 0 );
+ m_content = new GUIContent( GUIContent.none );
+ m_additionalContent = new GUIContent( GUIContent.none );
+ CommonInit( -1 );
+ }
+
+ public ParentNode( int uniqueId, float x, float y, float width, float height )
+ {
+ m_position = new Rect( x, y, width, height );
+ m_content = new GUIContent( GUIContent.none );
+ m_additionalContent = new GUIContent( GUIContent.none );
+ CommonInit( uniqueId );
+ }
+
+ public virtual void OnEnable()
+ {
+ hideFlags = HideFlags.HideAndDontSave;
+ if( m_nodeAttribs != null )
+ {
+ if( UIUtils.HasColorCategory( m_nodeAttribs.Category ) )
+ {
+ m_headerColor = UIUtils.GetColorFromCategory( m_nodeAttribs.Category );
+ }
+ else
+ {
+ if( !string.IsNullOrEmpty( m_nodeAttribs.CustomCategoryColor ) )
+ {
+ m_headerColor = UIUtils.AddColorCategory( m_nodeAttribs.Category, m_nodeAttribs.CustomCategoryColor );
+ }
+ }
+ }
+
+ m_tooltipTimestamp = Time.realtimeSinceStartup;
+ hideFlags = HideFlags.DontSave;
+ }
+
+ protected virtual void CommonInit( int uniqueId )
+ {
+ m_uniqueId = uniqueId;
+
+ m_isOnGrid = false;
+ ConnStatus = NodeConnectionStatus.Not_Connected;
+ m_inputPorts = new List<InputPort>();
+ m_inputPortsDict = new Dictionary<int, InputPort>();
+
+ m_outputPorts = new List<OutputPort>();
+ m_outputPortsDict = new Dictionary<int, OutputPort>();
+
+ System.Reflection.MemberInfo info = this.GetType();
+ m_nodeAttribs = info.GetCustomAttributes( true )[ 0 ] as NodeAttributes;
+ if( m_nodeAttribs != null )
+ {
+ m_content.text = m_nodeAttribs.Name;
+ //m_content.tooltip = m_nodeAttribs.Description;
+ m_tooltipText = m_nodeAttribs.Description;
+ m_selected = false;
+ }
+
+ m_sizeContentAux = new GUIContent();
+ m_extraSize = new Vector2( 0, 0 );
+ m_insideSize = new Vector2( 0, 0 );
+ m_sizeIsDirty = true;
+ m_initialized = true;
+ m_restrictions = new NodeRestrictions();
+
+ m_propertyDrawPos = new Rect();
+ }
+
+ public virtual void AfterCommonInit()
+ {
+ if( PreviewShader && !HasPreviewShader )
+ {
+ m_drawPreview = false;
+ m_drawPreviewExpander = false;
+ m_canExpand = false;
+ }
+
+ if( m_drawPreviewExpander || m_hasLeftDropdown )
+ {
+ m_paddingTitleRight += Constants.PreviewExpanderWidth + Constants.IconsLeftRightMargin;
+ m_paddingTitleLeft = Constants.PreviewExpanderWidth + Constants.IconsLeftRightMargin;
+ }
+ }
+
+ public virtual void Destroy()
+ {
+ m_alive = false;
+ if( OnNodeDestroyedEvent != null )
+ {
+ OnNodeDestroyedEvent( this );
+ OnNodeDestroyedEvent = null;
+ }
+
+ OnLightweightAction = null;
+ OnHDAction = null;
+
+ OnNodeStoppedMovingEvent = null;
+ OnNodeChangeSizeEvent = null;
+ OnNodeReOrderEvent = null;
+ if( m_restrictions != null )
+ m_restrictions.Destroy();
+ m_restrictions = null;
+
+ if( m_inputPorts != null )
+ {
+ int inputCount = m_inputPorts.Count;
+ for( int i = 0; i < inputCount; i++ )
+ {
+ m_inputPorts[ i ].Destroy();
+ }
+ m_inputPorts.Clear();
+ m_inputPorts = null;
+ }
+
+ if( m_outputPorts != null )
+ {
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ m_outputPorts[ i ].Destroy();
+ }
+ m_outputPorts.Clear();
+ m_outputPorts = null;
+ }
+
+ if( m_inputPortsDict != null )
+ m_inputPortsDict.Clear();
+
+ m_inputPortsDict = null;
+
+ if( m_outputPortsDict != null )
+ m_outputPortsDict.Clear();
+
+ m_outputPortsDict = null;
+
+ if( m_previewMaterial != null )
+ DestroyImmediate( m_previewMaterial );
+ m_previewMaterial = null;
+
+ m_previewShader = null;
+ //m_containerGraph = null;
+ }
+
+ public virtual void Move( Vector2 delta )
+ {
+ if( m_docking )
+ return;
+
+ Move( delta, false );
+ }
+
+ public virtual void Move( Vector2 delta, bool snap )
+ {
+ if( m_docking )
+ return;
+
+ if( m_isMoving == 0 )
+ {
+ m_cachedPos = m_position;
+ m_accumDelta = Vector2.zero;
+ }
+
+ m_isMoving = MoveCountBuffer;
+ m_accumDelta += delta;
+
+ if( snap )
+ {
+ m_position.x = Mathf.Round( ( m_cachedPos.x + m_accumDelta.x ) / 16 ) * 16;
+ m_position.y = Mathf.Round( ( m_cachedPos.y + m_accumDelta.y ) / 16 ) * 16;
+ }
+ else
+ {
+ m_position.x += delta.x;
+ m_position.y += delta.y;
+ }
+ //if(Event.current.type == EventType.Layout)
+ m_movingInFrame = true;
+ }
+
+ public virtual void UpdateMaterial( Material mat )
+ {
+ m_requireMaterialUpdate = false;
+ }
+
+ public virtual void SetMaterialMode( Material mat, bool fetchMaterialValues )
+ {
+ m_materialMode = ( mat != null );
+ }
+
+ public virtual bool UpdateShaderDefaults( ref Shader shader, ref TextureDefaultsDataColector defaultCol ) { return false; }
+ public virtual void ForceUpdateFromMaterial( Material material ) { }
+ public void SetSaveIsDirty()
+ {
+ if( m_connStatus == NodeConnectionStatus.Connected )
+ {
+ SaveIsDirty = true;
+ }
+ }
+
+ public void ActivateNodeReordering( int index )
+ {
+ if( OnNodeReOrderEvent != null )
+ OnNodeReOrderEvent( this, index );
+ }
+
+ void RecalculateInputPortIdx()
+ {
+ m_inputPortsDict.Clear();
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ int nodeId = m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId;
+ int portId = m_inputPorts[ i ].ExternalReferences[ 0 ].PortId;
+ ParentNode node = UIUtils.GetNode( nodeId );
+ if( node != null )
+ {
+ OutputPort outputPort = node.GetOutputPortByUniqueId( portId );
+ int outputCount = outputPort.ExternalReferences.Count;
+ for( int j = 0; j < outputCount; j++ )
+ {
+ if( outputPort.ExternalReferences[ j ].NodeId == m_uniqueId &&
+ outputPort.ExternalReferences[ j ].PortId == m_inputPorts[ i ].PortId )
+ {
+ outputPort.ExternalReferences[ j ].PortId = i;
+ }
+ }
+ }
+ }
+ m_inputPorts[ i ].PortId = i;
+ m_inputPortsDict.Add( i, m_inputPorts[ i ] );
+ }
+ }
+
+ public void SwapInputPorts( int fromIdx, int toIdx )
+ {
+ InputPort port = m_inputPorts[ fromIdx ];
+ //if( toIdx > fromIdx )
+ // toIdx--;
+ m_inputPorts.Remove( port );
+ m_inputPorts.Insert( toIdx, port );
+ RecalculateInputPortIdx();
+ SetSaveIsDirty();
+ }
+
+ public void RemoveInputPort( int idx )
+ {
+ if( idx < m_inputPorts.Count )
+ {
+ m_inputPortsDict.Remove( m_inputPorts[ idx ].PortId );
+ m_inputPorts.RemoveAt( idx );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+ }
+
+ public void RemoveOutputPort( string name )
+ {
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_outputPorts[ i ].Name.Equals( name ) )
+ {
+ if( m_outputPorts[ i ].IsConnected )
+ {
+ m_containerGraph.DeleteConnection( false, m_uniqueId, m_outputPorts[ i ].PortId, false, true );
+ m_outputPortsDict.Remove( m_outputPorts[ i ].PortId );
+ m_outputPorts.RemoveAt( i );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+ }
+ }
+ }
+
+ public void RemoveOutputPort( int idx, bool isArrayIndex = true )
+ {
+ if( isArrayIndex )
+ {
+ // idx represents a position on the output port array
+ if( idx < m_outputPorts.Count )
+ {
+ if( m_outputPorts[ idx ].IsConnected )
+ {
+ m_containerGraph.DeleteConnection( false, m_uniqueId, m_outputPorts[ idx ].PortId, false, true );
+ }
+
+ m_outputPortsDict.Remove( m_outputPorts[ idx ].PortId );
+ m_outputPorts.RemoveAt( idx );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+ }
+ else
+ {
+ // idx represents a port unique id
+ int count = m_outputPorts.Count;
+ int arrIdx = -1;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_outputPorts[ i ].PortId == idx )
+ {
+ arrIdx = i;
+ break;
+ }
+ }
+
+ if( arrIdx >= 0 )
+ {
+ if( m_outputPorts[ arrIdx ].IsConnected )
+ {
+ m_containerGraph.DeleteConnection( false, m_uniqueId, idx, false, true );
+ }
+
+ m_outputPortsDict.Remove( idx );
+ m_outputPorts.RemoveAt( arrIdx );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+ }
+ }
+
+ // Manually add Ports
+ public InputPort AddInputPort( WirePortDataType type, bool typeLocked, string name, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 )
+ {
+ InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category );
+ m_inputPorts.Add( port );
+ m_inputPortsDict.Add( port.PortId, port );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ return port;
+ }
+
+ public InputPort AddInputPort( WirePortDataType type, bool typeLocked, string name, string dataName, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 )
+ {
+ InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, dataName, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category );
+ m_inputPorts.Add( port );
+ m_inputPortsDict.Add( port.PortId, port );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ return port;
+ }
+
+ public InputPort AddInputPortAt( int idx, WirePortDataType type, bool typeLocked, string name, int orderId = -1, MasterNodePortCategory category = MasterNodePortCategory.Fragment, int uniquePortId = -1 )
+ {
+ InputPort port = new InputPort( m_uniqueId, ( uniquePortId < 0 ? m_inputPorts.Count : uniquePortId ), type, name, typeLocked, ( orderId >= 0 ? orderId : m_inputPorts.Count ), category );
+ m_inputPorts.Insert( idx, port );
+ m_inputPortsDict.Add( port.PortId, port );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ RecalculateInputPortIdx();
+ return port;
+ }
+
+ public void AddOutputPort( WirePortDataType type, string name, int uniquePortId = -1 )
+ {
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, ( uniquePortId < 0 ? m_outputPorts.Count : uniquePortId ), type, name ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+
+ public void AddOutputPortAt( int idx, WirePortDataType type, string name, int uniquePortId = -1 )
+ {
+ OutputPort port = new OutputPort( this, m_uniqueId, ( uniquePortId < 0 ? m_outputPorts.Count : uniquePortId ), type, name );
+ m_outputPorts.Insert( idx, port );
+ m_outputPortsDict.Add( port.PortId, port );
+ SetSaveIsDirty();
+ m_sizeIsDirty = true;
+ }
+
+ public void AddOutputVectorPorts( WirePortDataType type, string name )
+ {
+ m_sizeIsDirty = true;
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, type, name ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+
+ switch( type )
+ {
+ case WirePortDataType.FLOAT2:
+ {
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ }
+ break;
+ case WirePortDataType.FLOAT3:
+ {
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Z" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ }
+ break;
+ case WirePortDataType.FLOAT4:
+ {
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "X" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Y" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "Z" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "W" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ }
+ break;
+ }
+ SetSaveIsDirty();
+ }
+
+ public void SetPreviewDirtyFromOutputs()
+ {
+ PreviewIsDirty = true;
+ }
+
+ public string GetOutputVectorItem( int vectorPortId, int currentPortId, string result )
+ {
+ if( m_outputPorts[ 0 ].DataType == WirePortDataType.COLOR )
+ {
+ switch( currentPortId - vectorPortId )
+ {
+ case 1: result += ".r"; break;
+ case 2: result += ".g"; break;
+ case 3: result += ".b"; break;
+ case 4: result += ".a"; break;
+ }
+ }
+ else
+ {
+ switch( currentPortId - vectorPortId )
+ {
+ case 1: result += ".x"; break;
+ case 2: result += ".y"; break;
+ case 3: result += ".z"; break;
+ case 4: result += ".w"; break;
+ }
+ }
+ return result;
+ }
+
+ public void AddOutputColorPorts( string name, bool addAlpha = true )
+ {
+ m_sizeIsDirty = true;
+ //Main port
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, addAlpha ? WirePortDataType.COLOR : WirePortDataType.FLOAT3, name ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+
+ //Color components port
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "R" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.red;
+
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "G" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.green;
+
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "B" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.blue;
+
+ if( addAlpha )
+ {
+ m_outputPorts.Add( new OutputPort( this, m_uniqueId, m_outputPorts.Count, WirePortDataType.FLOAT, "A" ) );
+ m_outputPortsDict.Add( m_outputPorts[ m_outputPorts.Count - 1 ].PortId, m_outputPorts[ m_outputPorts.Count - 1 ] );
+ m_outputPorts[ m_outputPorts.Count - 1 ].CustomColor = Color.white;
+ }
+ }
+
+ public void ConvertFromVectorToColorPorts()
+ {
+ m_outputPorts[ 0 ].ChangeType( WirePortDataType.COLOR, false );
+
+ m_outputPorts[ 1 ].Name = "R";
+ m_outputPorts[ 1 ].CustomColor = Color.red;
+
+ m_outputPorts[ 2 ].Name = "G";
+ m_outputPorts[ 2 ].CustomColor = Color.green;
+
+ m_outputPorts[ 3 ].Name = "B";
+ m_outputPorts[ 3 ].CustomColor = Color.blue;
+
+ m_outputPorts[ 4 ].Name = "A";
+ m_outputPorts[ 4 ].CustomColor = Color.white;
+ }
+
+
+ public string GetOutputColorItem( int vectorPortId, int currentPortId, string result )
+ {
+ switch( currentPortId - vectorPortId )
+ {
+ case 1: result += ".r"; break;
+ case 2: result += ".g"; break;
+ case 3: result += ".b"; break;
+ case 4: result += ".a"; break;
+ }
+ return result;
+ }
+
+ public void ChangeOutputType( WirePortDataType type, bool invalidateConnections )
+ {
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ m_outputPorts[ i ].ChangeType( type, invalidateConnections );
+ }
+ }
+
+ public void ChangeInputType( WirePortDataType type, bool invalidateConnections )
+ {
+ int inputCount = m_inputPorts.Count;
+ for( int i = 0; i < inputCount; i++ )
+ {
+ m_inputPorts[ i ].ChangeType( type, invalidateConnections );
+ }
+ }
+
+ public void ChangeOutputProperties( int outputID, string newName, WirePortDataType newType, bool invalidateConnections = true )
+ {
+ if( outputID < m_outputPorts.Count )
+ {
+ m_outputPorts[ outputID ].ChangeProperties( newName, newType, invalidateConnections );
+ IsDirty = true;
+ m_sizeIsDirty = true;
+ SetSaveIsDirty();
+ }
+ }
+
+ public void ChangeOutputName( int outputArrayIdx, string newName )
+ {
+ if( outputArrayIdx < m_outputPorts.Count )
+ {
+ m_outputPorts[ outputArrayIdx ].Name = newName;
+ IsDirty = true;
+ m_sizeIsDirty = true;
+ }
+ }
+
+ public InputPort CheckInputPortAt( Vector3 pos )
+ {
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_inputPorts[ i ].InsideActiveArea( pos ) )
+ return m_inputPorts[ i ];
+ }
+ return null;
+ }
+
+ public InputPort GetFirstInputPortOfType( WirePortDataType dataType, bool countObjectTypeAsValid )
+ {
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( ( m_inputPorts[ i ].CheckValidType( dataType ) ) || ( countObjectTypeAsValid && m_inputPorts[ i ].DataType == WirePortDataType.OBJECT ) )
+ return m_inputPorts[ i ];
+ }
+ return null;
+ }
+
+ public OutputPort CheckOutputPortAt( Vector3 pos )
+ {
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_outputPorts[ i ].InsideActiveArea( pos ) )
+ return m_outputPorts[ i ];
+ }
+ return null;
+ }
+
+ public OutputPort GetFirstOutputPortOfType( WirePortDataType dataType, bool checkForCasts )
+ {
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( ( m_outputPorts[ i ].CheckValidType( dataType ) ) || ( checkForCasts && UIUtils.CanCast( dataType, m_outputPorts[ i ].DataType ) ) )
+ return m_outputPorts[ i ];
+ }
+ return null;
+ }
+
+ virtual protected void ChangeSizeFinished() { m_firstPreviewDraw = true; /*MarkForPreviewUpdate();*/ }
+ protected void ChangeSize()
+ {
+ m_cachedPos = m_position;
+ //UIUtils.ResetMainSkin();
+
+ Vector2 inSize = Vector2.zero;
+ int inputCount = 0;
+ int inputSize = m_inputPorts.Count;
+ for( int i = 0; i < inputSize; i++ )
+ {
+ if( m_inputPorts[ i ].Visible )
+ {
+ if( m_inputPorts[ i ].DirtyLabelSize || m_inputPorts[ i ].LabelSize == Vector2.zero )
+ {
+ m_inputPorts[ i ].DirtyLabelSize = false;
+ m_sizeContentAux.text = m_inputPorts[ i ].Name;
+ m_inputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedInputPortStyle.CalcSize( m_sizeContentAux );
+ }
+
+ inSize.x = Mathf.Max( inSize.x, m_inputPorts[ i ].UnscaledLabelSize.x );
+ inSize.y = Mathf.Max( inSize.y, m_inputPorts[ i ].UnscaledLabelSize.y );
+ inputCount += 1;
+ }
+ }
+ if( inSize.x > 0 )
+ inSize.x += UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X * 2;
+ inSize.x += m_marginPreviewLeft;
+ inSize.y = Mathf.Max( inSize.y, UIUtils.PortsSize.y );
+
+
+ Vector2 outSize = Vector2.zero;
+ int outputCount = 0;
+ int outputSize = m_outputPorts.Count;
+ for( int i = 0; i < outputSize; i++ )
+ {
+ if( m_outputPorts[ i ].Visible )
+ {
+ if( m_outputPorts[ i ].DirtyLabelSize || m_outputPorts[ i ].LabelSize == Vector2.zero )
+ {
+ m_outputPorts[ i ].DirtyLabelSize = false;
+ m_sizeContentAux.text = m_outputPorts[ i ].Name;
+ m_outputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedOutputPortPortStyle.CalcSize( m_sizeContentAux );
+ }
+
+ outSize.x = Mathf.Max( outSize.x, m_outputPorts[ i ].UnscaledLabelSize.x );
+ outSize.y = Mathf.Max( outSize.y, m_outputPorts[ i ].UnscaledLabelSize.y );
+ outputCount += 1;
+ }
+ }
+ if( outSize.x > 0 )
+ outSize.x += UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X * 2;
+ outSize.y = Mathf.Max( outSize.y, UIUtils.PortsSize.y );
+
+ if( m_additionalContent.text.Length > 0 )
+ {
+ m_extraHeaderHeight = (int)Constants.NODE_HEADER_EXTRA_HEIGHT;
+ m_hasSubtitle = true && m_showSubtitle;
+ }
+ else
+ {
+ m_extraHeaderHeight = 0;
+ m_hasSubtitle = false;
+ }
+
+ float headerWidth = Mathf.Max( UIUtils.UnZoomedNodeTitleStyle.CalcSize( m_content ).x + m_paddingTitleLeft + m_paddingTitleRight, UIUtils.UnZoomedPropertyValuesTitleStyle.CalcSize( m_additionalContent ).x + m_paddingTitleLeft + m_paddingTitleRight );
+ m_position.width = Mathf.Max( headerWidth, Mathf.Max( MinInsideBoxWidth, m_insideSize.x ) + inSize.x + outSize.x ) + Constants.NODE_HEADER_LEFTRIGHT_MARGIN * 2;
+ //m_position.width += m_extraSize.x;
+
+ m_fontHeight = Mathf.Max( inSize.y, outSize.y );
+
+ m_position.height = Mathf.Max( inputCount, outputCount ) * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );// + Constants.INPUT_PORT_DELTA_Y;
+ m_position.height = Mathf.Max( m_position.height, Mathf.Max( MinInsideBoxHeight, m_insideSize.y ) );
+ m_position.height += UIUtils.HeaderMaxHeight + m_extraHeaderHeight + Constants.INPUT_PORT_DELTA_Y;// + m_extraSize.y;
+ if( m_showErrorMessage )
+ m_position.height += 24;
+
+ m_unpreviewedPosition = m_position;
+ //UIUtils.CurrentWindow.CameraDrawInfo.InvertedZoom = cachedZoom;
+ if( OnNodeChangeSizeEvent != null )
+ {
+ OnNodeChangeSizeEvent( this );
+ }
+ ChangeSizeFinished();
+ }
+
+ public virtual void Reset() { }
+ public virtual void OnOutputPortConnected( int portId, int otherNodeId, int otherPortId ) { }
+
+ public virtual void OnInputPortConnected( int portId, int otherNodeId, int otherPortId, bool activateNode = true )
+ {
+ InputPort port = GetInputPortByUniqueId( portId );
+ if( activateNode && m_connStatus == NodeConnectionStatus.Connected )
+ {
+ port.GetOutputNode().ActivateNode( m_activeNode, m_activePort, m_activeType );
+ }
+
+ PreviewIsDirty = true;
+ OnNodeChange();
+ SetSaveIsDirty();
+ }
+
+ public virtual void OnInputPortDisconnected( int portId ) { PreviewIsDirty = true; OnNodeChange(); }
+ public virtual void OnOutputPortDisconnected( int portId ) { }
+
+ public virtual void OnNodeChange()
+ {
+ CheckSpherePreview();
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_outputPorts[ i ].IsConnected )
+ {
+ for( int f = 0; f < m_outputPorts[ i ].ExternalReferences.Count; f++ )
+ {
+ ContainerGraph.GetNode( m_outputPorts[ i ].ExternalReferences[ f ].NodeId ).OnNodeChange();
+ }
+ }
+ }
+ }
+
+ public virtual void ActivateNode( int signalGenNodeId, int signalGenPortId, System.Type signalGenNodeType )
+ {
+ if( m_selfPowered )
+ return;
+
+ ConnStatus = m_restrictions.GetRestiction( signalGenNodeType, signalGenPortId ) ? NodeConnectionStatus.Error : NodeConnectionStatus.Connected;
+ m_activeConnections += 1;
+
+ if( m_activeConnections == 1 )
+ {
+ m_activeType = signalGenNodeType;
+ m_activeNode = signalGenNodeId;
+ m_activePort = signalGenPortId;
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ m_inputPorts[ i ].GetOutputNode().ActivateNode( signalGenNodeId, signalGenPortId, signalGenNodeType );
+ }
+ }
+ }
+ // saveisdirty might be needed, gonna leave this here for now
+ // SetSaveIsDirty();
+ }
+
+ public virtual void DeactivateInputPortNode( int deactivatedPort, bool forceComplete )
+ {
+ GetInputPortByUniqueId( deactivatedPort ).GetOutputNode().DeactivateNode( deactivatedPort, false );
+ }
+
+ public virtual void DeactivateNode( int deactivatedPort, bool forceComplete )
+ {
+ if( m_selfPowered )
+ return;
+
+ // saveisdirty might be needed, gonna leave this here for now
+ // SetSaveIsDirty();
+ m_activeConnections -= 1;
+ if( forceComplete || m_activeConnections <= 0 )
+ {
+ m_activeConnections = 0;
+ ConnStatus = NodeConnectionStatus.Not_Connected;
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ ParentNode node = m_inputPorts[ i ].GetOutputNode();
+ if( node != null )
+ node.DeactivateNode( deactivatedPort == -1 ? m_inputPorts[ i ].PortId : deactivatedPort, false );
+ }
+ }
+ }
+ }
+
+ public Rect GlobalToLocalPosition( DrawInfo drawInfo )
+ {
+ float width = m_globalPosition.width / drawInfo.InvertedZoom;
+ float height = m_globalPosition.height / drawInfo.InvertedZoom;
+
+ float x = m_globalPosition.x / drawInfo.InvertedZoom - drawInfo.CameraOffset.x;
+ float y = m_globalPosition.y / drawInfo.InvertedZoom - drawInfo.CameraOffset.y;
+ return new Rect( x, y, width, height );
+ }
+
+ protected void CalculatePositionAndVisibility( DrawInfo drawInfo )
+ {
+ //m_movingInFrame = false;
+ m_globalPosition = m_position;
+ m_globalPosition.x = drawInfo.InvertedZoom * ( m_globalPosition.x + drawInfo.CameraOffset.x );
+ m_globalPosition.y = drawInfo.InvertedZoom * ( m_globalPosition.y + drawInfo.CameraOffset.y );
+ m_globalPosition.width *= drawInfo.InvertedZoom;
+ m_globalPosition.height *= drawInfo.InvertedZoom;
+
+ m_isVisible = ( m_globalPosition.x + m_globalPosition.width > 0 ) &&
+ ( m_globalPosition.x < drawInfo.CameraArea.width ) &&
+ ( m_globalPosition.y + m_globalPosition.height > 0 ) &&
+ ( m_globalPosition.y < drawInfo.CameraArea.height );
+
+ if( m_isMoving > 0 && drawInfo.CurrentEventType != EventType.MouseDrag )
+ {
+ float deltaX = Mathf.Abs( m_lastPosition.x - m_position.x );
+ float deltaY = Mathf.Abs( m_lastPosition.y - m_position.y );
+ if( deltaX < 0.01f && deltaY < 0.01f )
+ {
+ m_isMoving -= 1;
+ if( m_isMoving == 0 )
+ {
+ OnSelfStoppedMovingEvent();
+ }
+ }
+ else
+ {
+ m_isMoving = MoveCountBuffer;
+ }
+ m_lastPosition = m_position;
+ }
+ }
+
+ public void FireStoppedMovingEvent( bool testOnlySelected, InteractionMode interactionMode )
+ {
+ if( OnNodeStoppedMovingEvent != null )
+ OnNodeStoppedMovingEvent( this, testOnlySelected, interactionMode );
+ }
+
+ public virtual void OnSelfStoppedMovingEvent()
+ {
+ FireStoppedMovingEvent( true, m_defaultInteractionMode );
+ }
+
+ protected void DrawPrecisionProperty( bool withInherit = true )
+ {
+ if( withInherit )
+ m_currentPrecisionType = (PrecisionType)EditorGUILayoutPopup( PrecisionContent.text, (int)m_currentPrecisionType, PrecisionLabelsExtra );
+ else
+ m_currentPrecisionType = (PrecisionType)EditorGUILayoutPopup( PrecisionContent.text, (int)m_currentPrecisionType, PrecisionLabels );
+ }
+
+ public virtual void DrawTitle( Rect titlePos )
+ {
+ if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
+ {
+ GUI.Label( titlePos, m_content, UIUtils.GetCustomStyle( CustomStyle.NodeTitle ) );
+ }
+ }
+
+ public virtual void DrawPreview( DrawInfo drawInfo, Rect rect )
+ {
+ //if ( !m_drawPreview )
+ // return;
+
+ if( m_cachedDrawSphereId == -1 )
+ m_cachedDrawSphereId = Shader.PropertyToID( "_DrawSphere" );
+
+ if( m_cachedInvertedZoomId == -1 )
+ m_cachedInvertedZoomId = Shader.PropertyToID( "_InvertedZoom" );
+
+ m_channelNumber = 0;
+ Vector4 mask = Vector4.one;
+ if( m_outputPorts.Count > 0 )
+ {
+ switch( m_outputPorts[ 0 ].DataType )
+ {
+ case WirePortDataType.FLOAT:
+ m_channelNumber = 1;
+ mask.Set( 1, 1, 1, 0 );
+ break;
+ case WirePortDataType.FLOAT2:
+ m_channelNumber = 2;
+ mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, 1, 0 );
+ break;
+ case WirePortDataType.COLOR:
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.SAMPLER1D:
+ case WirePortDataType.SAMPLER2D:
+ case WirePortDataType.SAMPLER3D:
+ case WirePortDataType.SAMPLERCUBE:
+ m_channelNumber = 4;
+ mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, m_previewChannels[ 2 ] ? 1 : 0, m_previewChannels[ 3 ] ? 1 : 0 );
+ break;
+ default:
+ m_channelNumber = 3;
+ mask.Set( m_previewChannels[ 0 ] ? 1 : 0, m_previewChannels[ 1 ] ? 1 : 0, m_previewChannels[ 2 ] ? 1 : 0, 0 );
+ break;
+ }
+ }
+
+ UIUtils.LinearMaterial.SetFloat( m_cachedDrawSphereId, ( SpherePreview ? 1 : 0 ) );
+ UIUtils.LinearMaterial.SetFloat( m_cachedInvertedZoomId, drawInfo.InvertedZoom );
+ UIUtils.LinearMaterial.SetVector( "_Mask", mask );
+
+ bool cached = GL.sRGBWrite;
+ GL.sRGBWrite = true;
+ //EditorGUI.DrawPreviewTexture( rect, PreviewTexture, UIUtils.LinearMaterial );
+ int pass = 0;
+ if( SpherePreview )
+ {
+ if( mask.w == 1 )
+ pass = 3;
+ else
+ pass = 1;
+ }
+ else if( mask.w == 1 )
+ pass = 2;
+
+ Graphics.DrawTexture( rect, PreviewTexture, UIUtils.LinearMaterial, pass );
+ GL.sRGBWrite = cached;
+ //Preview buttons
+ if( m_drawPreviewMaskButtons )
+ DrawPreviewMaskButtonsRepaint( drawInfo, rect );
+ }
+
+ protected void DrawPreviewMaskButtonsLayout( DrawInfo drawInfo, Rect rect )
+ {
+ if( rect.Contains( drawInfo.MousePosition ) && m_channelNumber > 1 && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 )
+ {
+ Rect buttonRect = rect;
+ buttonRect.height = 14 * drawInfo.InvertedZoom;
+ buttonRect.y = rect.yMax - buttonRect.height;
+ buttonRect.width = 14 * drawInfo.InvertedZoom;
+
+ if( m_channelNumber == 2 )
+ {
+ m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none );
+ }
+ else if( m_channelNumber == 3 )
+ {
+ m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 2 ] = GUI.Toggle( buttonRect, m_previewChannels[ 2 ], string.Empty, GUIStyle.none );
+ }
+ else if( m_channelNumber == 4 )
+ {
+ m_previewChannels[ 0 ] = GUI.Toggle( buttonRect, m_previewChannels[ 0 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 1 ] = GUI.Toggle( buttonRect, m_previewChannels[ 1 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 2 ] = GUI.Toggle( buttonRect, m_previewChannels[ 2 ], string.Empty, GUIStyle.none );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ m_previewChannels[ 3 ] = GUI.Toggle( buttonRect, m_previewChannels[ 3 ], string.Empty, GUIStyle.none );
+ }
+ }
+ }
+
+ protected void DrawPreviewMaskButtonsRepaint( DrawInfo drawInfo, Rect rect )
+ {
+ if( drawInfo.CurrentEventType == EventType.Repaint && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD2 && rect.Contains( drawInfo.MousePosition ) && m_channelNumber > 1 )
+ {
+ Rect buttonRect = rect;
+ buttonRect.height = 14 * drawInfo.InvertedZoom;
+ buttonRect.y = rect.yMax - buttonRect.height;
+ buttonRect.width = 14 * drawInfo.InvertedZoom;
+
+ if( m_channelNumber == 2 )
+ {
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopRight.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false );
+ }
+ else if( m_channelNumber == 3 )
+ {
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopRight.Draw( buttonRect, "B", false, false, m_previewChannels[ 2 ], false );
+ }
+ else if( m_channelNumber == 4 )
+ {
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "R", false, false, m_previewChannels[ 0 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "G", false, false, m_previewChannels[ 1 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopMid.Draw( buttonRect, "B", false, false, m_previewChannels[ 2 ], false );
+ buttonRect.x += 14 * drawInfo.InvertedZoom;
+ UIUtils.MiniButtonTopRight.Draw( buttonRect, "A", false, false, m_previewChannels[ 3 ], false );
+ }
+ }
+ }
+
+ public void SetTimedUpdate( double timerInterval )
+ {
+ m_timedUpdateInitialValue = EditorApplication.timeSinceStartup;
+ m_timedUpdateInterval = timerInterval;
+ m_fireTimedUpdateRequest = true;
+ }
+
+ public virtual void FireTimedUpdate() { }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="drawInfo"></param>
+ public virtual void OnNodeLogicUpdate( DrawInfo drawInfo )
+ {
+ if( m_fireTimedUpdateRequest && ( EditorApplication.timeSinceStartup - m_timedUpdateInitialValue ) > m_timedUpdateInterval )
+ {
+ m_fireTimedUpdateRequest = false;
+ FireTimedUpdate();
+ }
+
+ if( m_repopulateDictionaries )
+ {
+ m_repopulateDictionaries = false;
+
+ m_inputPortsDict.Clear();
+ int inputCount = m_inputPorts.Count;
+ for( int i = 0; i < inputCount; i++ )
+ {
+ m_inputPortsDict.Add( m_inputPorts[ i ].PortId, m_inputPorts[ i ] );
+ }
+
+ m_outputPortsDict.Clear();
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ m_outputPortsDict.Add( m_outputPorts[ i ].PortId, m_outputPorts[ i ] );
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method should only be called to calculate layouts of elements to be draw later, only runs once per frame and before wires are drawn
+ /// </summary>
+ /// <param name="drawInfo"></param>
+ public virtual void OnNodeLayout( DrawInfo drawInfo )
+ {
+
+ if( ContainerGraph.ChangedLightingModel )
+ {
+ m_sizeIsDirty = true;
+ m_firstPreviewDraw = true;
+ }
+
+ if( m_firstDraw )
+ {
+ m_firstDraw = false;
+ AfterCommonInit();
+ OnNodeChange();
+ }
+
+ if( m_previousErrorMessage != m_showErrorMessage )
+ {
+ m_sizeIsDirty = true;
+ }
+
+ if( m_sizeIsDirty )
+ {
+ m_sizeIsDirty = false;
+ ChangeSize();
+ }
+
+ CalculatePositionAndVisibility( drawInfo );
+
+ m_unscaledRemainingBox = m_position;
+ m_remainingBox = m_globalPosition;
+
+ m_lastInputBottomRight = m_position.position;
+ m_lastOutputBottomLeft = m_position.position;
+ m_lastOutputBottomLeft.x += m_position.width;
+
+ m_visibleInputs = 0;
+ m_visibleOutputs = 0;
+
+ if( m_hasSubtitle )
+ m_extraHeaderHeight = (int)Constants.NODE_HEADER_EXTRA_HEIGHT;
+ else
+ m_extraHeaderHeight = 0;
+
+ m_lastInputBottomRight.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight;
+ m_lastOutputBottomLeft.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight;
+ m_unscaledRemainingBox.y += UIUtils.HeaderMaxHeight + m_extraHeaderHeight;
+
+ if( m_isVisible )
+ {
+ // Header
+ m_headerPosition = m_globalPosition;
+ m_headerPosition.height = UIUtils.CurrentHeaderHeight + m_extraHeaderHeight * drawInfo.InvertedZoom;
+
+ // Title
+ m_titlePos = m_globalPosition;
+ m_titlePos.height = m_headerPosition.height;
+ if( m_hasSubtitle )
+ m_titlePos.yMin += ( 4 * drawInfo.InvertedZoom );
+ else
+ m_titlePos.yMin += ( 7 * drawInfo.InvertedZoom );
+ m_titlePos.width -= ( m_paddingTitleLeft + m_paddingTitleRight ) * drawInfo.InvertedZoom;
+ m_titlePos.x += m_paddingTitleLeft * drawInfo.InvertedZoom;
+
+ // Additional Title
+ if( m_hasSubtitle )
+ {
+ m_addTitlePos = m_titlePos;
+ m_addTitlePos.y = m_globalPosition.y;
+ m_addTitlePos.yMin += ( 19 * drawInfo.InvertedZoom );
+ }
+
+ // Left Dropdown
+ if( m_hasLeftDropdown && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ {
+ m_dropdownRect = m_headerPosition;
+ m_dropdownRect.width = Constants.NodeButtonSizeX * drawInfo.InvertedZoom;
+ m_dropdownRect.x = m_globalPosition.x + ( Constants.IconsLeftRightMargin + 1 ) * drawInfo.InvertedZoom;
+ m_dropdownRect.height = Constants.NodeButtonSizeY * drawInfo.InvertedZoom;
+ m_dropdownRect.y = m_globalPosition.y + m_headerPosition.height * 0.5f - 14 * drawInfo.InvertedZoom * 0.5f;
+ }
+
+ // Expander
+ if( m_drawPreviewExpander && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ {
+ m_expandRect = m_globalPosition;
+ m_expandRect.width = Constants.PreviewExpanderWidth * drawInfo.InvertedZoom;
+ m_expandRect.x = m_globalPosition.x + m_globalPosition.width - ( Constants.IconsLeftRightMargin + Constants.PreviewExpanderWidth ) * drawInfo.InvertedZoom; //titlePos.x + titlePos.width;
+ m_expandRect.height = Constants.PreviewExpanderHeight * drawInfo.InvertedZoom;
+ m_expandRect.y = m_globalPosition.y + m_headerPosition.height * 0.5f - Constants.PreviewExpanderHeight * drawInfo.InvertedZoom * 0.5f;
+ }
+ }
+
+ if( m_anchorAdjust < 0 )
+ {
+ m_anchorAdjust = UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon ).normal.background.width;
+ }
+
+ m_unscaledRemainingBox.y += Constants.INPUT_PORT_DELTA_Y;
+ m_lastOutputBottomLeft.y += Constants.INPUT_PORT_DELTA_Y;
+ m_lastInputBottomRight.y += Constants.INPUT_PORT_DELTA_Y;
+
+ // Input Ports
+ {
+ m_currInputPortPos = m_globalPosition;
+ m_currInputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x;
+ m_currInputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y;
+
+ m_currInputPortPos.x += drawInfo.InvertedZoom * Constants.PORT_INITIAL_X;
+ m_currInputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y + m_extraHeaderHeight * drawInfo.InvertedZoom;
+ int inputCount = m_inputPorts.Count;
+
+ float initialX = m_lastInputBottomRight.x;
+
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].Visible )
+ {
+ m_visibleInputs++;
+ // Button
+ m_inputPorts[ i ].Position = m_currInputPortPos;
+
+ // Label
+ m_inputPorts[ i ].LabelPosition = m_currInputPortPos;
+ float deltaX = 1f * drawInfo.InvertedZoom * ( UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X );
+ m_auxRect = m_inputPorts[ i ].LabelPosition;
+ m_auxRect.x += deltaX;
+ m_inputPorts[ i ].LabelPosition = m_auxRect;
+
+ //if( m_inputPorts[ i ].DirtyLabelSize || m_inputPorts[ i ].LabelSize == Vector2.zero )
+ //{
+ // m_inputPorts[ i ].DirtyLabelSize = false;
+ // m_sizeContentAux.text = m_inputPorts[ i ].Name;
+ // m_inputPorts[ i ].UnscaledLabelSize = UIUtils.UnZoomedInputPortStyle.CalcSize( m_sizeContentAux );
+ //}
+
+ m_inputPorts[ i ].LabelSize = m_inputPorts[ i ].UnscaledLabelSize * drawInfo.InvertedZoom;
+
+ m_lastInputBottomRight.x = Mathf.Max( m_lastInputBottomRight.x, initialX + m_inputPorts[ i ].UnscaledLabelSize.x + Constants.PORT_INITIAL_X + Constants.PORT_TO_LABEL_SPACE_X + UIUtils.PortsSize.x );
+
+ if( !m_inputPorts[ i ].Locked )
+ {
+ float overflow = 2;
+ float scaledOverflow = 4 * drawInfo.InvertedZoom;
+ m_auxRect = m_currInputPortPos;
+ m_auxRect.yMin -= scaledOverflow + overflow;
+ m_auxRect.yMax += scaledOverflow + overflow;
+ m_auxRect.xMin -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ if( m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid )
+ m_auxRect.xMax += m_inputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ else
+ m_auxRect.xMax += Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ m_inputPorts[ i ].ActivePortArea = m_auxRect;
+ }
+ m_currInputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );
+ //GUI.Label( m_inputPorts[ i ].ActivePortArea, string.Empty, UIUtils.Box );
+ }
+ }
+ if( m_visibleInputs > 0 )
+ m_lastInputBottomRight.y += m_fontHeight * m_visibleInputs + Constants.INPUT_PORT_DELTA_Y * ( m_visibleInputs - 1 );
+ }
+
+ // Output Ports
+ {
+ m_currOutputPortPos = m_globalPosition;
+ m_currOutputPortPos.width = drawInfo.InvertedZoom * UIUtils.PortsSize.x;
+ m_currOutputPortPos.height = drawInfo.InvertedZoom * UIUtils.PortsSize.y;
+
+ m_currOutputPortPos.x += ( m_globalPosition.width - drawInfo.InvertedZoom * ( Constants.PORT_INITIAL_X + m_anchorAdjust ) );
+ m_currOutputPortPos.y += drawInfo.InvertedZoom * Constants.PORT_INITIAL_Y + m_extraHeaderHeight * drawInfo.InvertedZoom;
+ int outputCount = m_outputPorts.Count;
+
+ float initialX = m_lastOutputBottomLeft.x;
+
+ for( int i = 0; i < outputCount; i++ )
+ {
+ if( m_outputPorts[ i ].Visible )
+ {
+ m_visibleOutputs++;
+ //Button
+ m_outputPorts[ i ].Position = m_currOutputPortPos;
+
+ // Label
+ m_outputPorts[ i ].LabelPosition = m_currOutputPortPos;
+ float deltaX = 1f * drawInfo.InvertedZoom * ( UIUtils.PortsSize.x + Constants.PORT_TO_LABEL_SPACE_X );
+ m_auxRect = m_outputPorts[ i ].LabelPosition;
+ m_auxRect.x -= deltaX;
+ m_outputPorts[ i ].LabelPosition = m_auxRect;
+
+ m_outputPorts[ i ].LabelSize = m_outputPorts[ i ].UnscaledLabelSize * drawInfo.InvertedZoom;
+
+ m_lastOutputBottomLeft.x = Mathf.Min( m_lastOutputBottomLeft.x, initialX - m_outputPorts[ i ].UnscaledLabelSize.x - Constants.PORT_INITIAL_X - Constants.PORT_TO_LABEL_SPACE_X - UIUtils.PortsSize.x );
+
+ if( !m_outputPorts[ i ].Locked )
+ {
+ float overflow = 2;
+ float scaledOverflow = 4 * drawInfo.InvertedZoom;
+ m_auxRect = m_currOutputPortPos;
+ m_auxRect.yMin -= scaledOverflow + overflow;
+ m_auxRect.yMax += scaledOverflow + overflow;
+ if( m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid )
+ m_auxRect.xMin -= m_outputPorts[ i ].LabelSize.x + Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ else
+ m_auxRect.xMin -= Constants.PORT_TO_LABEL_SPACE_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ m_auxRect.xMax += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom + scaledOverflow + overflow;
+ m_outputPorts[ i ].ActivePortArea = m_auxRect;
+ }
+ m_currOutputPortPos.y += drawInfo.InvertedZoom * ( m_fontHeight + Constants.INPUT_PORT_DELTA_Y );
+ //GUI.Label( m_outputPorts[ i ].ActivePortArea, string.Empty, UIUtils.Box );
+ }
+ }
+ if( m_visibleOutputs > 0 )
+ m_lastOutputBottomLeft.y += m_fontHeight * m_visibleOutputs + Constants.INPUT_PORT_DELTA_Y * ( m_visibleOutputs - 1 );
+ }
+
+ m_lastInputBottomRight.x += m_marginPreviewLeft;
+
+ //Vector2 scaledLastOutputBottomLeft = ( m_lastOutputBottomLeft + drawInfo.CameraOffset ) * drawInfo.InvertedZoom;
+ //GUI.Label( new Rect( scaledLastOutputBottomLeft, Vector2.one * 2 ), string.Empty, UIUtils.CurrentWindow.CustomStylesInstance.Box );
+
+ m_unscaledRemainingBox.xMin = m_lastInputBottomRight.x;
+ //m_unscaledRemainingBox.yMin = m_lastInputBottomRight.y;
+ m_unscaledRemainingBox.xMax = m_lastOutputBottomLeft.x;
+ m_unscaledRemainingBox.yMax = Mathf.Max( m_lastOutputBottomLeft.y, m_lastInputBottomRight.y );
+
+ m_remainingBox.position = ( m_unscaledRemainingBox.position + drawInfo.CameraOffset ) * drawInfo.InvertedZoom;
+ m_remainingBox.size = m_unscaledRemainingBox.size * drawInfo.InvertedZoom;
+
+ //GUI.Label( m_remainingBox, string.Empty, UIUtils.Box );
+
+ if( m_visibleInputs == 0 )
+ {
+ m_remainingBox.x += Constants.PORT_INITIAL_X * drawInfo.InvertedZoom;
+ m_remainingBox.width -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom;
+ }
+
+ if( m_visibleOutputs == 0 )
+ {
+ m_remainingBox.width -= Constants.PORT_INITIAL_X * drawInfo.InvertedZoom;
+ }
+
+ if( ContainerGraph.ParentWindow.GlobalPreview != m_globalShowPreview )
+ {
+ m_globalShowPreview = ContainerGraph.ParentWindow.GlobalPreview;
+ m_sizeIsDirty = true;
+ ContainerGraph.ParentWindow.RequestRepaint();
+ }
+
+ // Generate Proper Preview Rect
+ float marginAround = 10;
+ float scaledMarginAround = marginAround * drawInfo.InvertedZoom;
+ float previewSize = 128;
+ PreviewLocation m_autoLocation = m_selectedLocation;
+ if( m_selectedLocation == PreviewLocation.Auto )
+ {
+ if( m_visibleOutputs > m_visibleInputs )
+ {
+ m_autoLocation = PreviewLocation.Left;
+ }
+ else if( m_visibleOutputs < m_visibleInputs )
+ {
+ m_autoLocation = PreviewLocation.Right;
+ }
+ else if( m_unscaledRemainingBox.width > previewSize )
+ {
+ m_autoLocation = PreviewLocation.TopCenter;
+ }
+ else
+ {
+ m_autoLocation = PreviewLocation.BottomCenter;
+ }
+ }
+
+ if( m_canExpand && ( m_showPreview || m_globalShowPreview ) )
+ {
+ if( m_autoLocation == PreviewLocation.TopCenter )
+ {
+ m_unscaledPreviewRect.y = m_unscaledRemainingBox.y;
+ m_unscaledPreviewRect.x = m_unscaledRemainingBox.center.x - 0.5f * ( previewSize + 2 * marginAround );
+ }
+ else if( m_autoLocation == PreviewLocation.BottomCenter )
+ {
+ m_unscaledPreviewRect.y = Mathf.Max( m_lastOutputBottomLeft.y, m_lastInputBottomRight.y );
+ m_unscaledPreviewRect.x = m_position.x + 0.5f * m_position.width - 0.5f * ( previewSize + 2 * marginAround );
+ }
+ else if( m_autoLocation == PreviewLocation.Left )
+ {
+ m_unscaledPreviewRect.y = m_lastInputBottomRight.y;
+ m_unscaledPreviewRect.x = m_position.x;
+ }
+ else if( m_autoLocation == PreviewLocation.Right )
+ {
+ m_unscaledPreviewRect.y = m_lastOutputBottomLeft.y;
+ m_unscaledPreviewRect.x = m_lastInputBottomRight.x;
+ }
+ if( m_autoLocation == PreviewLocation.BottomCenter )
+ m_unscaledPreviewRect.height = previewSize + 2 * marginAround;
+ else if( m_autoLocation == PreviewLocation.TopCenter )
+ m_unscaledPreviewRect.height = previewSize + marginAround;
+ else
+ m_unscaledPreviewRect.height = previewSize + ( m_visibleInputs > 0 && m_visibleOutputs > 0 ? 2 * marginAround : marginAround );
+ m_unscaledPreviewRect.width = previewSize + 2 * marginAround;
+
+ m_previewRect = m_unscaledPreviewRect;
+ m_previewRect.position = ( m_previewRect.position + drawInfo.CameraOffset ) * drawInfo.InvertedZoom;
+ m_auxVector2.Set( previewSize * drawInfo.InvertedZoom, previewSize * drawInfo.InvertedZoom );
+ m_previewRect.size = m_auxVector2;
+
+ if( m_autoLocation == PreviewLocation.BottomCenter )
+ {
+ m_auxVector2.Set( m_previewRect.position.x + scaledMarginAround, m_previewRect.position.y + scaledMarginAround );
+ m_previewRect.position = m_auxVector2;
+ }
+ else if( m_autoLocation == PreviewLocation.TopCenter )
+ {
+ m_auxVector2.Set( m_previewRect.position.x + scaledMarginAround, m_previewRect.position.y );
+ m_previewRect.position = m_auxVector2;
+ }
+ else
+ {
+ m_previewRect.position += new Vector2( scaledMarginAround, ( m_visibleInputs > 0 && m_visibleOutputs > 0 ? scaledMarginAround : 0 ) );
+ }
+ }
+
+ // Adjust node rect after preview
+ if( m_firstPreviewDraw )
+ {
+ m_firstPreviewDraw = false;
+ ContainerGraph.ParentWindow.RequestRepaint();
+ if( m_canExpand && ( m_showPreview || m_globalShowPreview ) )
+ {
+ if( m_autoLocation == PreviewLocation.TopCenter )
+ {
+ float fillWidth = m_unscaledRemainingBox.width - m_unscaledPreviewRect.width;
+ m_extraSize.x = Mathf.Max( -fillWidth, 0 );
+ float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax;
+ m_extraSize.y = Mathf.Max( -fillHeight, 0 );
+ }
+ if( m_autoLocation == PreviewLocation.BottomCenter )
+ {
+ float fillWidth = m_position.width - m_unscaledPreviewRect.width;
+ m_extraSize.x = Mathf.Max( -fillWidth, 0 );
+ float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax;
+ m_extraSize.y = Mathf.Max( -fillHeight, 0 );
+ }
+ else if( m_autoLocation == PreviewLocation.Left )
+ {
+ float fillWidth = m_lastOutputBottomLeft.x - m_unscaledPreviewRect.xMax;
+ m_extraSize.x = Mathf.Max( -fillWidth, 0 );
+ float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax;
+ m_extraSize.y = Mathf.Max( -fillHeight, 0 );
+ }
+ else if( m_autoLocation == PreviewLocation.Right )
+ {
+ float fillWidth = m_position.xMax - m_unscaledPreviewRect.xMax;
+ m_extraSize.x = Mathf.Max( -fillWidth, 0 );
+ float fillHeight = m_position.yMax - m_unscaledPreviewRect.yMax;
+ m_extraSize.y = Mathf.Max( -fillHeight, 0 );
+ }
+
+ if( m_showErrorMessage )
+ m_extraSize.y += 24;
+ }
+ else if( m_canExpand )
+ {
+ m_extraSize.y = 0;
+ m_extraSize.x = 0;
+ }
+
+ m_position.width = m_unpreviewedPosition.width + m_extraSize.x;
+ m_position.height = m_unpreviewedPosition.height + m_extraSize.y;
+ }
+
+
+ if( m_showErrorMessage )
+ {
+ m_errorBox = m_globalPosition;
+ m_errorBox.y = ( m_globalPosition.yMax - 28 * drawInfo.InvertedZoom ) + 3 * drawInfo.InvertedZoom;
+ m_errorBox.height = 25 * drawInfo.InvertedZoom;
+ }
+
+ m_previousErrorMessage = m_showErrorMessage;
+ }
+
+ /// <summary>
+ /// This method should only be called to draw elements, runs once per frame and after wires are drawn
+ /// </summary>
+ /// <param name="drawInfo"></param>
+ public virtual void OnNodeRepaint( DrawInfo drawInfo )
+ {
+ if( !m_isVisible )
+ return;
+
+ m_colorBuffer = GUI.color;
+ // Background
+ GUI.color = m_infiniteLoopDetected ? Constants.InfiniteLoopColor : Constants.NodeBodyColor;
+ if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 )
+ GUI.Label( m_globalPosition, string.Empty, UIUtils.NodeWindowOffSquare );
+ else
+ GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOff ) );
+
+ // Header
+ //GUI
+ GUI.color = m_headerColor * m_headerColorModifier;
+ if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 )
+ GUI.Label( m_headerPosition, string.Empty, UIUtils.NodeHeaderSquare );
+ else
+ GUI.Label( m_headerPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeHeader ) );
+ GUI.color = m_colorBuffer;
+
+ // Title
+ DrawTitle( m_titlePos );
+
+ // Additional Tile
+ if( m_hasSubtitle && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
+ GUI.Label( m_addTitlePos, m_additionalContent, UIUtils.GetCustomStyle( CustomStyle.PropertyValuesTitle ) );
+
+ // Dropdown
+ if( m_hasLeftDropdown && !m_dropdownEditing && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ GUI.Label( m_dropdownRect, string.Empty, UIUtils.PropertyPopUp );
+
+ // Expander
+ if( m_drawPreviewExpander && ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ GUI.Label( m_expandRect, string.Empty, ( m_showPreview ? UIUtils.PreviewCollapser : UIUtils.PreviewExpander ) );
+
+ // Input Ports
+ int inputCount = m_inputPorts.Count;
+
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].Visible )
+ {
+ // Input Port Icon
+ if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ {
+ if( m_inputPorts[ i ].Locked )
+ GUI.color = Constants.LockedPortColor;
+ else if( ContainerGraph.ParentWindow.Options.ColoredPorts )
+ GUI.color = UIUtils.GetColorForDataType( m_inputPorts[ i ].DataType, false, true );
+ else
+ GUI.color = m_inputPorts[ i ].HasCustomColor ? m_inputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_inputPorts[ i ].DataType, true, true );
+
+ GUIStyle style = m_inputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon );
+ GUI.Label( m_inputPorts[ i ].Position, string.Empty, style );
+
+ GUI.color = m_colorBuffer;
+ }
+
+ // Input Port Label
+ if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
+ {
+ if( m_inputPorts[ i ].Locked )
+ {
+ GUI.color = Constants.PortLockedTextColor;
+ GUI.Label( m_inputPorts[ i ].LabelPosition, m_inputPorts[ i ].Name, UIUtils.InputPortLabel );
+ GUI.color = m_colorBuffer;
+ }
+ else
+ {
+ if( m_containerGraph.ParentWindow.GlobalShowInternalData && !m_inputPorts[ i ].IsConnected && UIUtils.InternalDataOnPort.fontSize > 1f && ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) ) && m_inputPorts[ i ].DisplayInternalData.Length > 4 && m_inputPorts[ i ].DataType != WirePortDataType.OBJECT )
+ {
+ GUI.color = Constants.NodeBodyColor/* * new Color( 1f, 1f, 1f, 0.75f )*/;
+ Rect internalBox = m_inputPorts[ i ].LabelPosition;
+ m_sizeContentAux.text = m_inputPorts[ i ].DisplayInternalData;
+ Vector2 portText = UIUtils.InternalDataOnPort.CalcSize( m_sizeContentAux );
+ internalBox.width = portText.x;
+ internalBox.height = portText.y;
+ internalBox.y = m_inputPorts[ i ].LabelPosition.center.y - internalBox.height * 0.5f;
+ internalBox.x = GlobalPosition.x - internalBox.width - 4 * drawInfo.InvertedZoom - 1;
+ Rect backBox = new Rect( internalBox );
+ backBox.xMin -= 4 * drawInfo.InvertedZoom;
+ backBox.xMax += 4 * drawInfo.InvertedZoom;
+ backBox.yMin -= 2 * drawInfo.InvertedZoom;
+ backBox.yMax += 2 * drawInfo.InvertedZoom;
+ GUI.Label( backBox, string.Empty, UIUtils.InternalDataBackground );
+ GUI.color *= new Color( 1f, 1f, 1f, 0.5f );
+ GUI.Label( internalBox, m_sizeContentAux, UIUtils.InternalDataOnPort );
+ GUI.color = m_colorBuffer;
+ }
+ GUI.Label( m_inputPorts[ i ].LabelPosition, m_inputPorts[ i ].Name, UIUtils.InputPortLabel );
+ }
+ }
+ }
+ }
+
+ // Output Ports
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ if( m_outputPorts[ i ].Visible )
+ {
+ // Output Port Icon
+ if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD4 )
+ {
+ if( m_outputPorts[ i ].Locked )
+ GUI.color = Constants.LockedPortColor;
+ else if( ContainerGraph.ParentWindow.Options.ColoredPorts )
+ GUI.color = UIUtils.GetColorForDataType( m_outputPorts[ i ].DataType, false, false );
+ else
+ GUI.color = m_outputPorts[ i ].HasCustomColor ? m_outputPorts[ i ].CustomColor : UIUtils.GetColorForDataType( m_outputPorts[ i ].DataType, true, false );
+
+ GUIStyle style = m_outputPorts[ i ].IsConnected ? UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) : UIUtils.GetCustomStyle( CustomStyle.PortEmptyIcon );
+ GUI.Label( m_outputPorts[ i ].Position, string.Empty, style );
+
+ GUI.color = m_colorBuffer;
+ }
+
+ // Output Port Label
+ if( ContainerGraph.LodLevel <= ParentGraph.NodeLOD.LOD3 )
+ {
+ if( m_outputPorts[ i ].Locked )
+ {
+ GUI.color = Constants.PortLockedTextColor;
+ GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel );
+ GUI.color = m_colorBuffer;
+ }
+ else
+ {
+ GUI.Label( m_outputPorts[ i ].LabelPosition, m_outputPorts[ i ].Name, UIUtils.OutputPortLabel );
+ }
+ }
+ }
+ }
+
+ // Preview
+ if( ( m_showPreview || m_globalShowPreview ) && m_drawPreview )
+ DrawPreview( drawInfo, m_previewRect );
+
+ // Error and Warning bottom message
+ if( m_showErrorMessage )
+ {
+ GUI.color = new Color( 0.0f, 0.0f, 0.0f, 0.5f );
+ GUI.Label( m_errorBox, string.Empty, UIUtils.Separator );
+ GUI.color = m_colorBuffer;
+
+ switch( m_errorMessageTypeIsError )
+ {
+ default:
+ case NodeMessageType.Error:
+ {
+ m_errorMessage.text = ErrorTitle;
+ m_errorIcon.image = UIUtils.SmallErrorIcon;
+ m_errorCurrentStyle = UIUtils.BoldErrorStyle;
+ }
+ break;
+ case NodeMessageType.Warning:
+ {
+ m_errorMessage.text = WarningTitle;
+ m_errorIcon.image = UIUtils.SmallWarningIcon;
+ m_errorCurrentStyle = UIUtils.BoldWarningStyle;
+ }
+ break;
+ case NodeMessageType.Info:
+ {
+ m_errorMessage.text = InfoTitle;
+ m_errorIcon.image = UIUtils.SmallInfoIcon;
+ m_errorCurrentStyle = UIUtils.BoldInfoStyle;
+ }
+ break;
+ }
+
+ Rect textBox = m_errorBox;
+ textBox.y += 1 * drawInfo.InvertedZoom;
+ textBox.height = 24 * drawInfo.InvertedZoom;
+
+ float textWidth = m_errorCurrentStyle.CalcSize( m_errorMessage ).x;
+
+ GUI.Label( textBox, m_errorMessage, m_errorCurrentStyle );
+ textBox.x -= textWidth * 0.5f + 12 * drawInfo.InvertedZoom;
+ GUI.Label( textBox, m_errorIcon, m_errorCurrentStyle );
+ textBox.x += textWidth + 24 * drawInfo.InvertedZoom;
+ GUI.Label( textBox, m_errorIcon, m_errorCurrentStyle );
+ }
+
+ // Selection Box
+ if( m_selected )
+ {
+ GUI.color = Constants.NodeSelectedColor;
+ if( m_useSquareNodeTitle || ContainerGraph.LodLevel >= ParentGraph.NodeLOD.LOD2 )
+ GUI.Label( m_globalPosition, string.Empty, UIUtils.NodeWindowOnSquare );
+ else
+ GUI.Label( m_globalPosition, string.Empty, UIUtils.GetCustomStyle( CustomStyle.NodeWindowOn ) );
+ GUI.color = m_colorBuffer;
+ }
+
+ // Debug Visualizers
+ //if( FinishPreviewRender || m_continuousPreviewRefresh )
+ //{
+ // GUI.color = new Color( 0, 1, 0.5f, 1f );
+ // Rect r = m_globalPosition;
+ // r.width = 8;
+ // r.height = 8;
+ // r.x -= 5 * drawInfo.InvertedZoom;
+ // r.y -= 5 * drawInfo.InvertedZoom;
+ // GUI.Label( r, string.Empty, UIUtils.GetCustomStyle( CustomStyle.PortFullIcon ) );
+ // GUI.color = m_colorBuffer;
+ // FinishPreviewRender = false;
+ //}
+ //GUI.Label( m_remainingBox, string.Empty, UIUtils.Box );
+ }
+
+ public bool DropdownEditing { get { return m_dropdownEditing; } set { m_dropdownEditing = value; PreviewIsDirty = true; } }
+ /// <summary>
+ /// Handles gui controls, runs before node layout
+ /// </summary>
+ /// <param name="drawInfo"></param>
+ public virtual void DrawGUIControls( DrawInfo drawInfo )
+ {
+ if( !m_initialized )
+ return;
+
+ if( !m_isVisible )
+ return;
+
+ if( drawInfo.CurrentEventType == EventType.MouseDown && drawInfo.LeftMouseButtonPressed )
+ {
+ if( m_expandRect.Contains( drawInfo.MousePosition ) )
+ {
+ m_showPreview = !m_showPreview;
+ m_sizeIsDirty = true;
+ ContainerGraph.ParentWindow.MouseInteracted = true;
+ }
+
+ if( m_hasLeftDropdown && m_dropdownRect.Contains( drawInfo.MousePosition ) )
+ {
+ m_dropdownEditing = true;
+ }
+ else if( m_dropdownEditing )
+ {
+ DropdownEditing = false;
+ }
+ }
+
+ DrawGuiPorts( drawInfo );
+ }
+
+ //public static bool MyRepeatButton( DrawInfo drawInfo, Rect position, string text, GUIStyle style )
+ //{
+ // if(/* drawInfo.CurrentEventType == EventType.MouseDown &&*/ position.Contains( drawInfo.MousePosition ) )
+ // {
+ // UIUtils.CurrentWindow.MouseInteracted = true;
+ // return true;
+ // }
+ // return false;
+ //}
+
+ public void DrawGuiPorts( DrawInfo drawInfo )
+ {
+ if( !m_initialized )
+ return;
+
+ if( !m_isVisible )
+ return;
+
+ if( drawInfo.CurrentEventType == EventType.MouseDown )
+ {
+ int inputCount = m_inputPorts.Count;
+ int outputCount = m_outputPorts.Count;
+
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].Visible && !m_inputPorts[ i ].Locked && m_isVisible && m_inputPorts[ i ].ActivePortArea.Contains( drawInfo.MousePosition ) && drawInfo.LeftMouseButtonPressed )
+ {
+ UIUtils.CurrentWindow.MouseInteracted = true;
+ m_inputPorts[ i ].Click();
+ // need to put the mouse button on a hot state so it will detect the Mouse Up event correctly on the Editor Window
+ int controlID = GUIUtility.GetControlID( FocusType.Passive );
+ //int controlID = GUIUtility.GetControlID( "repeatButton".GetHashCode(), FocusType.Passive, m_inputPorts[ i ].ActivePortArea );
+ GUIUtility.hotControl = controlID;
+
+ bool saveReference = true;
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ double doubleTapTime = EditorApplication.timeSinceStartup;
+ bool doubleTap = ( doubleTapTime - m_doubleClickTimestamp ) < DoubleClickTime;
+ m_doubleClickTimestamp = doubleTapTime;
+
+ if( doubleTap )
+ {
+ m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ i ].PortId, true, true );
+ Event.current.Use();
+ }
+ else
+ //if ( AppyModifierToPort( _inputPorts[ i ], true ) )
+ //{
+ //saveReference = false;
+ //}
+ if( !ApplyModifierToPort( m_inputPorts[ i ], true ) )
+ {
+ UIUtils.ShowContextOnPick = false;
+ PickInput( m_inputPorts[ i ] );
+ }
+ saveReference = false;
+ }
+
+ if( saveReference && !m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.IsValid )
+ //if ( !modifierApplied && !UIUtils.InputPortReference.IsValid )
+ {
+ m_containerGraph.ParentWindow.WireReferenceUtils.SetInputReference( m_uniqueId, m_inputPorts[ i ].PortId, m_inputPorts[ i ].DataType, m_inputPorts[ i ].TypeLocked );
+ }
+
+ IsDirty = true;
+ inputCount = m_inputPorts.Count;
+ }
+ }
+
+ for( int i = 0; i < outputCount; i++ )
+ {
+ if( m_outputPorts[ i ].Visible && m_outputPorts[ i ].ActivePortArea.Contains( drawInfo.MousePosition ) && drawInfo.LeftMouseButtonPressed )
+ {
+ UIUtils.CurrentWindow.MouseInteracted = true;
+ m_outputPorts[ i ].Click();
+ // need to put the mouse button on a hot state so it will detect the Mouse Up event correctly on the Editor Window
+ int controlID = GUIUtility.GetControlID( FocusType.Passive );
+ //int controlID = GUIUtility.GetControlID( "aseRepeatButton".GetHashCode(), FocusType.Passive, m_outputPorts[ i ].ActivePortArea );
+ GUIUtility.hotControl = controlID;
+
+ bool saveReference = true;
+ if( m_outputPorts[ i ].IsConnected )
+ {
+ if( ApplyModifierToPort( m_outputPorts[ i ], false ) )
+ {
+ saveReference = false;
+ }
+ }
+
+ if( saveReference && !m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.IsValid )
+ {
+ m_containerGraph.ParentWindow.WireReferenceUtils.SetOutputReference( m_uniqueId, m_outputPorts[ i ].PortId, m_outputPorts[ i ].DataType, false );
+ }
+
+ IsDirty = true;
+ outputCount = m_outputPorts.Count;
+ }
+ }
+ }
+
+ //Preview buttons
+ if( m_drawPreviewMaskButtons && ( drawInfo.CurrentEventType == EventType.MouseDown || drawInfo.CurrentEventType == EventType.MouseUp ) )
+ DrawPreviewMaskButtonsLayout( drawInfo, m_previewRect );
+ }
+
+ /// <summary>
+ /// Can be used to draw an entire node, runs after wires
+ /// </summary>
+ /// <param name="drawInfo"></param>
+ public virtual void Draw( DrawInfo drawInfo )
+ {
+ if( !m_initialized )
+ return;
+
+ if( drawInfo.CurrentEventType == EventType.Repaint )
+ OnNodeRepaint( drawInfo );
+ }
+
+ public virtual void SetPreviewInputs()
+ {
+ if( !HasPreviewShader || !m_initialized )
+ return;
+
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].InputNodeHasPreview( ContainerGraph ) )
+ {
+ m_inputPorts[ i ].SetPreviewInputTexture( ContainerGraph );
+ }
+ else
+ {
+ m_inputPorts[ i ].SetPreviewInputValue( ContainerGraph );
+ }
+ }
+ }
+
+
+ public bool SafeDraw( DrawInfo drawInfo )
+ {
+ EditorGUI.BeginChangeCheck();
+ Draw( drawInfo );
+ if( EditorGUI.EndChangeCheck() )
+ {
+ SaveIsDirty = true;
+ return true;
+ }
+ return false;
+ }
+
+ public bool ShowTooltip( DrawInfo drawInfo )
+ {
+ if( string.IsNullOrEmpty( m_tooltipText ) )
+ return false;
+
+ if( m_globalPosition.Contains( drawInfo.MousePosition ) || m_linkVisibility )
+ {
+ if( m_tooltipTimestamp + 0.6f < Time.realtimeSinceStartup || m_linkVisibility )
+ {
+ bool errorTooltip = false;
+ if( m_showErrorMessage && m_errorBox.Contains( drawInfo.MousePosition ) && !string.IsNullOrEmpty( m_errorMessageTooltip ) )
+ errorTooltip = true;
+
+ Rect globalTooltipPos = m_globalPosition;
+ GUIContent temp = new GUIContent( errorTooltip ? m_errorMessageTooltip : m_tooltipText );
+ UIUtils.TooltipBox.wordWrap = false;
+ Vector2 optimal = UIUtils.TooltipBox.CalcSize( temp );
+ if( optimal.x > 300f )
+ {
+ UIUtils.TooltipBox.wordWrap = true;
+ optimal.x = 300f;
+ optimal.y = UIUtils.TooltipBox.CalcHeight( temp, 300f );
+ }
+
+ globalTooltipPos.width = Mathf.Max( 120, optimal.x );
+ globalTooltipPos.height = optimal.y;
+ globalTooltipPos.center = m_globalPosition.center;
+
+ if( !errorTooltip && m_hasTooltipLink )
+ globalTooltipPos.height += 16;
+
+ if( errorTooltip )
+ globalTooltipPos.y = 10 + m_globalPosition.yMax;
+ else
+ globalTooltipPos.y = m_globalPosition.yMin - 10 - globalTooltipPos.height;
+
+ if ( globalTooltipPos.x < 10 )
+ globalTooltipPos.x = 10;
+
+ if( globalTooltipPos.x + globalTooltipPos.width > Screen.width - 10 )
+ globalTooltipPos.x = Screen.width - globalTooltipPos.width - 10;
+
+ //UNCOMMENT this for auto adjust tooltip to the top window box
+ //if( globalTooltipPos.y < 40 )
+ // globalTooltipPos.y = 40;
+
+ if( errorTooltip && globalTooltipPos.y + globalTooltipPos.height > Screen.height - 32 )
+ globalTooltipPos.y = Screen.height - 32 - globalTooltipPos.height;
+
+ GUI.Label( globalTooltipPos, temp, UIUtils.TooltipBox );
+
+ if( !errorTooltip && m_hasTooltipLink )
+ {
+ Rect link = globalTooltipPos;
+ link.y = globalTooltipPos.yMax - 16;
+ link.height = 16;
+ link.width = 86;
+ link.x = globalTooltipPos.center.x - 43;
+ Rect hover = globalTooltipPos;
+ hover.yMax += 15;// m_globalPosition.yMax;
+ m_linkVisibility = hover.Contains( drawInfo.MousePosition );
+ if( link.Contains( drawInfo.MousePosition ) )
+ {
+ if( drawInfo.CurrentEventType == EventType.MouseDown )
+ {
+ if( m_tooltipTimestamp + 1.25f < Time.realtimeSinceStartup )
+ {
+ Application.OpenURL( Attributes.NodeUrl );
+ }
+ }
+ else
+ {
+ UIUtils.MainSkin.customStyles[ 52 ].Draw( link, WikiLinkStr, true, false, false, false );
+ }
+ }
+ else
+ {
+ GUI.Label( link, WikiLinkStr, UIUtils.MainSkin.customStyles[ 52 ] );
+ }
+ }
+ ContainerGraph.ParentWindow.RequestRepaint();
+ return true;
+ }
+ }
+ else
+ {
+ if( !m_linkVisibility )
+ m_tooltipTimestamp = Time.realtimeSinceStartup;
+ }
+
+ return false;
+ }
+
+ public virtual bool SafeDrawProperties()
+ {
+ EditorGUI.BeginChangeCheck();
+ PreDrawProperties();
+ if( m_autoWrapProperties )
+ {
+ NodeUtils.DrawPropertyGroup( ref m_propertiesFoldout, Constants.ParameterLabelStr, DrawProperties );
+ }
+ else
+ {
+ DrawProperties();
+ }
+ if( EditorGUI.EndChangeCheck() )
+ {
+ PreviewIsDirty = true;
+ //UIUtils.RecordObject(this);
+ //MarkForPreviewUpdate();
+ return true;
+ }
+ return false;
+ }
+
+
+ public void PreDrawProperties()
+ {
+ if( m_useInternalPortData && m_autoDrawInternalPortData )
+ {
+ DrawInternalDataGroup();
+ }
+ }
+
+ virtual public void DrawProperties() { }
+
+ protected void DrawInternalDataGroup()
+ {
+ bool drawInternalDataUI = false;
+ int inputCount = m_inputPorts.Count;
+ if( inputCount > 0 )
+ {
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].Available && m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected /*&& ( m_inputPorts[ i ].AutoDrawInternalData || ( m_autoDrawInternalPortData && m_useInternalPortData ) )*/ /*&& m_inputPorts[ i ].AutoDrawInternalData*/ )
+ {
+ drawInternalDataUI = true;
+ break;
+ }
+ }
+ }
+
+ if( drawInternalDataUI )
+ NodeUtils.DrawPropertyGroup( ref m_internalDataFoldout, Constants.InternalDataLabelStr, () =>
+ {
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ if( m_inputPorts[ i ].ValidInternalData && !m_inputPorts[ i ].IsConnected && m_inputPorts[ i ].Visible /*&& m_inputPorts[ i ].AutoDrawInternalData*/ )
+ {
+ m_inputPorts[ i ].ShowInternalData( this );
+ }
+ }
+ } );
+ }
+
+ protected void PickInput( InputPort port )
+ {
+ WireReference connection = port.GetConnection( 0 );
+ OutputPort from = port.GetOutputConnection( 0 );
+
+ m_containerGraph.ParentWindow.WireReferenceUtils.OutputPortReference.SetReference( from.NodeId, from.PortId, from.DataType, connection.TypeLocked );
+ m_containerGraph.DeleteConnection( true, UniqueId, port.PortId, true, true );
+ //TODO: check if not necessary
+ Event.current.Use();
+ IsDirty = true;
+ SetSaveIsDirty();
+ }
+
+ protected bool ApplyModifierToPort( WirePort port, bool isInput )
+ {
+ bool modifierApplied = false;
+ switch( Event.current.modifiers )
+ {
+ case EventModifiers.Alt:
+ {
+ m_containerGraph.DeleteConnection( isInput, UniqueId, port.PortId, true, true );
+ modifierApplied = true;
+ m_containerGraph.ParentWindow.InvalidateAlt();
+ }
+ break;
+ case EventModifiers.Control:
+ {
+ //WireReference connection = port.GetConnection( 0 );
+ //if ( isInput )
+ //{
+ // UIUtils.OutputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked );
+ //}
+ //else
+ //{
+ // UIUtils.InputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked );
+ //}
+
+ //UIUtils.DeleteConnection( isInput, UniqueId, port.PortId, true );
+ //modifierApplied = true;
+
+ if( !isInput )
+ {
+ WireReference connection = port.GetConnection( 0 );
+ m_containerGraph.ParentWindow.WireReferenceUtils.InputPortReference.SetReference( connection.NodeId, connection.PortId, connection.DataType, connection.TypeLocked );
+ m_containerGraph.DeleteConnection( isInput, UniqueId, port.PortId, true, true );
+ modifierApplied = true;
+ }
+ }
+ break;
+ }
+
+ if( isInput )
+ m_containerGraph.ParentWindow.WireReferenceUtils.SwitchPortReference.SetReference( port.NodeId, port.PortId, port.DataType, false ); //always save last connection
+ else
+ m_containerGraph.ParentWindow.WireReferenceUtils.SwitchPortReference.SetReference( -1, -1, WirePortDataType.OBJECT, false ); //invalidate connection
+
+ if( modifierApplied )
+ {
+ Event.current.Use();
+ IsDirty = true;
+ SetSaveIsDirty();
+ }
+ return modifierApplied;
+ }
+
+ public void DeleteAllInputConnections( bool alsoDeletePorts , bool inhibitWireNodeAutoDel = false )
+ {
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ ParentNode connNode = null;
+ if( inhibitWireNodeAutoDel )
+ {
+ connNode = m_inputPorts[ i ].GetOutputNode();
+ connNode.Alive = false;
+ }
+ m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ i ].PortId, false, true );
+ if( inhibitWireNodeAutoDel )
+ {
+ connNode.Alive = true;
+ }
+ }
+
+ }
+ if( alsoDeletePorts )
+ {
+ m_inputPorts.Clear();
+ m_inputPortsDict.Clear();
+ }
+ SetSaveIsDirty();
+ }
+
+ public void DeleteAllOutputConnections( bool alsoDeletePorts )
+ {
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_outputPorts[ i ].IsConnected )
+ m_containerGraph.DeleteConnection( false, UniqueId, m_outputPorts[ i ].PortId, false, true );
+ }
+
+ if( alsoDeletePorts )
+ {
+ m_outputPorts.Clear();
+ m_outputPortsDict.Clear();
+ }
+ SetSaveIsDirty();
+ }
+
+ public void DeleteInputPortByArrayIdx( int arrayIdx )
+ {
+ if( arrayIdx >= m_inputPorts.Count )
+ return;
+
+ m_containerGraph.DeleteConnection( true, UniqueId, m_inputPorts[ arrayIdx ].PortId, false, true );
+ m_inputPortsDict.Remove( m_inputPorts[ arrayIdx ].PortId );
+ m_inputPorts.RemoveAt( arrayIdx );
+
+ m_sizeIsDirty = true;
+ SetSaveIsDirty();
+ RecalculateInputPortIdx();
+ }
+
+ public void DeleteOutputPortByArrayIdx( int portIdx )
+ {
+ if( portIdx >= m_outputPorts.Count )
+ return;
+
+ m_containerGraph.DeleteConnection( false, UniqueId, m_outputPorts[ portIdx ].PortId, false, true );
+ m_outputPortsDict.Remove( m_outputPorts[ portIdx ].PortId );
+ m_outputPorts.RemoveAt( portIdx );
+ m_sizeIsDirty = true;
+ }
+
+ public InputPort GetInputPortByArrayId( int id )
+ {
+ if( id < m_inputPorts.Count )
+ return m_inputPorts[ id ];
+
+ return null;
+ }
+
+ public OutputPort GetOutputPortByArrayId( int id )
+ {
+ if( id < m_outputPorts.Count )
+ return m_outputPorts[ id ];
+
+ return null;
+ }
+
+ public InputPort GetInputPortByUniqueId( int id )
+ {
+ if( m_inputPortsDict.ContainsKey( id ) )
+ return m_inputPortsDict[ id ];
+
+ if( m_inputPortsDict.Count != m_inputPorts.Count )
+ m_repopulateDictionaries = true;
+
+ int inputCount = m_inputPorts.Count;
+ for( int i = 0; i < inputCount; i++ )
+ {
+ if( m_inputPorts[ i ].PortId == id )
+ {
+ return m_inputPorts[ i ];
+ }
+ }
+ return null;
+ }
+
+ public OutputPort GetOutputPortByUniqueId( int id )
+ {
+ if( m_outputPortsDict.ContainsKey( id ) )
+ return m_outputPortsDict[ id ];
+
+ if( m_outputPortsDict.Count != m_outputPorts.Count )
+ m_repopulateDictionaries = true;
+
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ if( m_outputPorts[ i ].PortId == id )
+ return m_outputPorts[ i ];
+ }
+ return null;
+ }
+
+ public virtual void AfterDuplication(){}
+
+ public override string ToString()
+ {
+ string dump = "";
+ dump += ( "Type: " + GetType() );
+ dump += ( " Unique Id: " + UniqueId + "\n" );
+ dump += ( " Inputs: \n" );
+
+ int inputCount = m_inputPorts.Count;
+ int outputCount = m_outputPorts.Count;
+
+ for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ )
+ {
+ dump += ( m_inputPorts[ inputIdx ] + "\n" );
+ }
+ dump += ( "Outputs: \n" );
+ for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ )
+ {
+ dump += ( m_outputPorts[ outputIdx ] + "\n" );
+ }
+ return dump;
+ }
+
+ public string GetValueFromOutputStr( int outputId, WirePortDataType inputPortType, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( ignoreLocalvar )
+ {
+ return GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
+ }
+ OutputPort outPort = GetOutputPortByUniqueId( outputId );
+ if( outPort.IsLocalValue( dataCollector.PortCategory ) )
+ {
+ if( outPort.DataType != WirePortDataType.OBJECT && outPort.DataType != inputPortType )
+ {
+ return UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( m_uniqueId, outputId ), null, outPort.DataType, inputPortType, outPort.LocalValue( dataCollector.PortCategory ) );
+ }
+ else
+ {
+ return outPort.LocalValue( dataCollector.PortCategory );
+ }
+ }
+
+ string result = GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
+ result = CreateOutputLocalVariable( outputId, result, ref dataCollector );
+
+ if( outPort.DataType != WirePortDataType.OBJECT && outPort.DataType != inputPortType )
+ {
+ result = UIUtils.CastPortType( ref dataCollector, CurrentPrecisionType, new NodeCastInfo( m_uniqueId, outputId ), null, outPort.DataType, inputPortType, result );
+ }
+ return result;
+ }
+
+ public virtual string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
+ {
+ if( dataCollector.IsSRP )
+ {
+ switch( dataCollector.CurrentSRPType )
+ {
+ case TemplateSRPType.HD: if(OnHDAction!=null) OnHDAction( outputId, ref dataCollector ); break;
+ case TemplateSRPType.Lightweight:if(OnLightweightAction != null) OnLightweightAction( outputId, ref dataCollector ); break;
+ }
+ }
+ return string.Empty;
+ }
+
+ public string GenerateValueInVertex( ref MasterNodeDataCollector dataCollector, WirePortDataType dataType, string dataValue, string dataName, bool createInterpolator )
+ {
+
+ if( !dataCollector.IsFragmentCategory )
+ return dataValue;
+
+ //TEMPLATES
+ if( dataCollector.IsTemplate )
+ {
+ if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( dataName ) )
+ return dataName;
+
+ MasterNodePortCategory category = dataCollector.PortCategory;
+ dataCollector.PortCategory = MasterNodePortCategory.Vertex;
+
+ dataCollector.PortCategory = category;
+
+ if( createInterpolator )
+ {
+ dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( dataName, dataType, CurrentPrecisionType, dataValue );
+ }
+ else
+ {
+ dataCollector.AddToVertexLocalVariables( -1, CurrentPrecisionType, dataType, dataName, dataValue );
+ }
+
+ return dataName;
+ }
+
+ //SURFACE
+ {
+ if( dataCollector.TesselationActive )
+ {
+ UIUtils.ShowMessage( UniqueId, "Unable to use Vertex to Frag when Tessellation is active" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( createInterpolator )
+ dataCollector.AddToInput( UniqueId, dataName, dataType, CurrentPrecisionType );
+
+ MasterNodePortCategory portCategory = dataCollector.PortCategory;
+ dataCollector.PortCategory = MasterNodePortCategory.Vertex;
+ if( createInterpolator )
+ {
+ dataCollector.AddLocalVariable( UniqueId, Constants.VertexShaderOutputStr + "." + dataName, dataValue + ";" );
+ }
+ else
+ {
+ dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, dataType, dataName, dataValue );
+ }
+ dataCollector.PortCategory = portCategory;
+ return createInterpolator ? Constants.InputVarStr + "." + dataName : dataName;
+ }
+ }
+
+ public string GenerateInputInVertex( ref MasterNodeDataCollector dataCollector, int inputPortUniqueId, string varName, bool createInterpolator )
+ {
+ InputPort inputPort = GetInputPortByUniqueId( inputPortUniqueId );
+ if( !dataCollector.IsFragmentCategory)
+ return inputPort.GeneratePortInstructions( ref dataCollector );
+
+ //TEMPLATES
+ if( dataCollector.IsTemplate )
+ {
+ if( createInterpolator && dataCollector.TemplateDataCollectorInstance.HasCustomInterpolatedData( varName ) )
+ return varName;
+
+ MasterNodePortCategory category = dataCollector.PortCategory;
+ dataCollector.PortCategory = MasterNodePortCategory.Vertex;
+ //bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables;
+ //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex );
+
+ string data = inputPort.GeneratePortInstructions( ref dataCollector );
+
+ dataCollector.PortCategory = category;
+ //if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables )
+ //{
+ // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariablesFromList, UniqueId, false );
+ // dataCollector.ClearVertexLocalVariables();
+ // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex );
+ //}
+
+ //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment );
+
+ if( createInterpolator )
+ {
+ dataCollector.TemplateDataCollectorInstance.RegisterCustomInterpolatedData( varName, inputPort.DataType, CurrentPrecisionType, data );
+ }
+ else
+ {
+ dataCollector.AddToVertexLocalVariables( -1, CurrentPrecisionType, inputPort.DataType, varName, data );
+ }
+
+ return varName;
+ }
+
+ //SURFACE
+ {
+ if( dataCollector.TesselationActive )
+ {
+ UIUtils.ShowMessage( UniqueId, "Unable to use Vertex to Frag when Tessellation is active" );
+ return m_outputPorts[ 0 ].ErrorValue;
+ }
+
+ if( createInterpolator )
+ dataCollector.AddToInput( UniqueId, varName, inputPort.DataType, CurrentPrecisionType );
+
+ MasterNodePortCategory portCategory = dataCollector.PortCategory;
+ dataCollector.PortCategory = MasterNodePortCategory.Vertex;
+
+ //bool dirtyVertexVarsBefore = dataCollector.DirtyVertexVariables;
+
+ //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex );
+
+ string vertexVarValue = inputPort.GeneratePortInstructions( ref dataCollector );
+ if( createInterpolator )
+ {
+ dataCollector.AddLocalVariable( UniqueId, Constants.VertexShaderOutputStr + "." + varName, vertexVarValue + ";" );
+ }
+ else
+ {
+ dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, inputPort.DataType, varName, vertexVarValue );
+ }
+
+ dataCollector.PortCategory = portCategory;
+
+ //if( !dirtyVertexVarsBefore && dataCollector.DirtyVertexVariables )
+ //{
+ // dataCollector.AddVertexInstruction( dataCollector.VertexLocalVariables, UniqueId, false );
+ // dataCollector.ClearVertexLocalVariables();
+ // ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Vertex );
+ //}
+
+ //ContainerGraph.ResetNodesLocalVariablesIfNot( this, MasterNodePortCategory.Fragment );
+
+ return createInterpolator ? Constants.InputVarStr + "." + varName : varName;
+ }
+ }
+
+
+ protected virtual void OnUniqueIDAssigned() { }
+
+ public string CreateOutputLocalVariable( int outputArrayId, string value, ref MasterNodeDataCollector dataCollector )
+ {
+ OutputPort port = GetOutputPortByUniqueId( outputArrayId );
+
+ if( port.IsLocalValue( dataCollector.PortCategory ) )
+ return port.LocalValue( dataCollector.PortCategory );
+
+ if( port.ConnectionCount > 1 )
+ {
+ RegisterLocalVariable( outputArrayId, value, ref dataCollector );
+ return port.LocalValue( dataCollector.PortCategory );
+ }
+ else
+ {
+ // revisit later (break to components case)
+ port.SetLocalValue( value, dataCollector.PortCategory );
+ }
+
+ return value;
+ }
+
+ public void RegisterLocalVariable( int outputArrayId, string value, ref MasterNodeDataCollector dataCollector, string customName = null )
+ {
+ OutputPort port = GetOutputPortByUniqueId( outputArrayId );
+ if( (int)port.DataType >= (int)( 1 << 10 ) ) //10 is the flag start of sampler types
+ {
+ port.SetLocalValue( value, dataCollector.PortCategory );
+ return;
+ }
+
+ bool vertexMode = dataCollector.PortCategory == MasterNodePortCategory.Vertex || dataCollector.PortCategory == MasterNodePortCategory.Tessellation;
+ string localVar = port.ConfigOutputLocalValue( CurrentPrecisionType, value, customName, dataCollector.PortCategory );
+
+ if( vertexMode )
+ {
+ dataCollector.AddToVertexLocalVariables( m_uniqueId, localVar );
+ }
+ else
+ {
+ dataCollector.AddToLocalVariables( m_uniqueId, localVar );
+ }
+ }
+
+ public void InvalidateConnections()
+ {
+ int inputCount = m_inputPorts.Count;
+ int outputCount = m_outputPorts.Count;
+
+ for( int i = 0; i < inputCount; i++ )
+ {
+ m_inputPorts[ i ].InvalidateAllConnections();
+ }
+
+ for( int i = 0; i < outputCount; i++ )
+ {
+ m_outputPorts[ i ].InvalidateAllConnections();
+ }
+ }
+
+ public virtual bool OnClick( Vector2 currentMousePos2D )
+ {
+ bool singleClick = true;
+ if( ( EditorApplication.timeSinceStartup - m_lastTimeSelected ) < NodeClickTime )
+ {
+ OnNodeDoubleClicked( currentMousePos2D );
+ singleClick = false;
+ }
+
+ m_lastTimeSelected = EditorApplication.timeSinceStartup;
+ return singleClick;
+ }
+
+ public virtual void OnNodeDoubleClicked( Vector2 currentMousePos2D )
+ {
+ ContainerGraph.ParentWindow.ParametersWindow.IsMaximized = !ContainerGraph.ParentWindow.ParametersWindow.IsMaximized;
+ }
+
+ public virtual void OnNodeSelected( bool value )
+ {
+ if( !value )
+ {
+ if( m_inputPorts != null )
+ {
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_inputPorts[ i ].ResetEditing();
+ }
+ }
+
+ if( m_outputPorts != null )
+ {
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ m_outputPorts[ i ].ResetEditing();
+ }
+ }
+ }
+ }
+
+ public void ResetOutputLocals()
+ {
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ m_outputPorts[ i ].ResetLocalValue();
+ }
+ }
+
+
+ public void ResetOutputLocalsIfNot( MasterNodePortCategory category )
+ {
+ int outputCount = m_outputPorts.Count;
+ for( int i = 0; i < outputCount; i++ )
+ {
+ //if( !m_outputPorts[ i ].IsLocalOnCategory( category ) )
+ // m_outputPorts[ i ].ResetLocalValue();
+ m_outputPorts[ i ].ResetLocalValueIfNot( category );
+ }
+ }
+
+ public virtual void Rewire() { }
+
+ //public virtual List<int> NodeReferences { get { return null; } }
+
+ public int UniqueId
+ {
+ get { return m_uniqueId; }
+
+ set
+ {
+ m_uniqueId = value;
+
+ int inputCount = m_inputPorts.Count;
+ int outputCount = m_outputPorts.Count;
+
+ for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ )
+ {
+ m_inputPorts[ inputIdx ].NodeId = value;
+ }
+
+ for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ )
+ {
+ m_outputPorts[ outputIdx ].NodeId = value;
+ }
+ OnUniqueIDAssigned();
+ }
+ }
+ public void SetBaseUniqueId( int uniqueId, bool setOnPorts = false )
+ {
+ m_uniqueId = uniqueId;
+ if( setOnPorts )
+ {
+ int inputCount = m_inputPorts.Count;
+ int outputCount = m_outputPorts.Count;
+
+ for( int inputIdx = 0; inputIdx < inputCount; inputIdx++ )
+ {
+ m_inputPorts[ inputIdx ].NodeId = uniqueId;
+ }
+
+ for( int outputIdx = 0; outputIdx < outputCount; outputIdx++ )
+ {
+ m_outputPorts[ outputIdx ].NodeId = uniqueId;
+ }
+ }
+ }
+
+ public string OutputId
+ {
+ get
+ {
+ if( ContainerGraph.GraphId > 0 )
+ return UniqueId + "_g" + ContainerGraph.GraphId;
+ else
+ return UniqueId.ToString();
+ }
+ }
+
+
+ public virtual Rect Position { get { return m_position; } }
+ public Rect TruePosition { get { return m_position; } }
+
+ public Vector2 CenterPosition { get { return new Vector2( m_position.x + m_position.width * 0.5f, m_position.y + m_position.height * 0.5f ); ; } }
+
+ public Rect GlobalPosition { get { return m_globalPosition; } }
+
+ public Vector2 Corner { get { return new Vector2( m_position.x + m_position.width, m_position.y + m_position.height ); } }
+ public Vector2 Vec2Position
+ {
+ get { return new Vector2( m_position.x, m_position.y ); }
+
+ set
+ {
+ m_position.x = value.x;
+ m_position.y = value.y;
+ }
+ }
+
+ public Vector3 Vec3Position
+ {
+ get { return new Vector3( m_position.x, m_position.y, 0f ); }
+
+ set
+ {
+ m_position.x = value.x;
+ m_position.y = value.y;
+ }
+ }
+
+
+ public bool Selected
+ {
+ get { return m_selected; }
+ set
+ {
+ m_infiniteLoopDetected = false;
+ m_selected = value;
+ OnNodeSelected( value );
+ }
+ }
+
+ public List<InputPort> InputPorts { get { return m_inputPorts; } }
+
+ public List<OutputPort> OutputPorts
+ {
+ get { return m_outputPorts; }
+ }
+
+ public bool IsConnected { get { return m_connStatus == NodeConnectionStatus.Connected; } }
+ public NodeConnectionStatus ConnStatus
+ {
+ get { return m_connStatus; }
+ set
+ {
+ if( m_selfPowered )
+ {
+ m_connStatus = NodeConnectionStatus.Connected;
+ }
+ else
+ {
+ m_connStatus = value;
+ }
+
+ switch( m_connStatus )
+ {
+ case NodeConnectionStatus.Island:
+ case NodeConnectionStatus.Not_Connected: m_statusColor = Constants.NodeDefaultColor; break;
+ case NodeConnectionStatus.Connected: m_statusColor = Constants.NodeConnectedColor; break;
+ case NodeConnectionStatus.Error: m_statusColor = Constants.NodeErrorColor; break;
+ }
+
+ }
+ }
+
+ public bool SelfPowered
+ {
+ set
+ {
+ m_selfPowered = value;
+ if( value )
+ {
+ ConnStatus = NodeConnectionStatus.Connected;
+ }
+ }
+ }
+
+ // This is also called when recording on Undo
+ public virtual void OnBeforeSerialize() { }
+ public virtual void OnAfterDeserialize()
+ {
+ m_selected = false;
+ m_isOnGrid = false;
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ m_inputPorts[ i ].ResetWireReferenceStatus();
+ }
+ m_repopulateDictionaries = true;
+ m_sizeIsDirty = true;
+ }
+
+ public virtual void ReadFromDeprecated( ref string[] nodeParams, Type oldType = null ) { }
+
+ //Inherited classes must call this base method in order to setup id and position
+ public virtual void ReadFromString( ref string[] nodeParams )
+ {
+ ParentReadFromString( ref nodeParams );
+ }
+
+ public void ParentReadFromString( ref string[] nodeParams )
+ {
+ m_currentReadParamIdx = IOUtils.NodeTypeId + 1;
+
+ UniqueId = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] );
+
+ string[] posCoordinates = nodeParams[ m_currentReadParamIdx++ ].Split( IOUtils.VECTOR_SEPARATOR );
+
+ m_position.x = Convert.ToSingle( posCoordinates[ 0 ] );
+ m_position.y = Convert.ToSingle( posCoordinates[ 1 ] );
+
+ if( UIUtils.CurrentShaderVersion() > 22 )
+ {
+ string val = GetCurrentParam( ref nodeParams );
+ if( m_customPrecision )
+ {
+ if( val.Equals("Fixed") )
+ m_currentPrecisionType = PrecisionType.Half;
+ else
+ m_currentPrecisionType = (PrecisionType)Enum.Parse( typeof( PrecisionType ), val );
+ }
+ else
+ {
+ m_currentPrecisionType = PrecisionType.Inherit;
+ }
+ }
+
+ if( UIUtils.CurrentShaderVersion() > 5004 )
+ m_showPreview = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
+
+ }
+
+ //should be called after ReadFromString
+ public virtual void ReadInputDataFromString( ref string[] nodeParams )
+ {
+ 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_inputPorts[ newId ].DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] );
+ }
+
+ m_inputPorts[ newId ].InternalData = nodeParams[ m_currentReadParamIdx++ ];
+ if( m_inputPorts[ newId ].IsEditable && UIUtils.CurrentShaderVersion() >= 3100 && m_currentReadParamIdx < nodeParams.Length )
+ {
+ m_inputPorts[ newId ].Name = nodeParams[ m_currentReadParamIdx++ ];
+ }
+ m_inputPorts[ newId ].UpdatePreviewInternalData();
+ }
+ else
+ {
+ string portIdStr = nodeParams[ m_currentReadParamIdx++ ];
+ int portId = -1;
+ try
+ {
+ portId = Convert.ToInt32( portIdStr );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+
+ WirePortDataType DataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] );
+ string InternalData = nodeParams[ m_currentReadParamIdx++ ];
+ bool isEditable = Convert.ToBoolean( nodeParams[ m_currentReadParamIdx++ ] );
+ string Name = string.Empty;
+ if( isEditable && m_currentReadParamIdx < nodeParams.Length )
+ {
+ Name = nodeParams[ m_currentReadParamIdx++ ];
+ }
+
+ InputPort inputPort = GetInputPortByUniqueId( portId );
+ if( inputPort != null )
+ {
+ if( UIUtils.IsValidType( DataType ) )
+ inputPort.DataType = DataType;
+
+ inputPort.InternalData = InternalData;
+ if( !string.IsNullOrEmpty( Name ) )
+ {
+ inputPort.Name = Name;
+ }
+ inputPort.UpdatePreviewInternalData();
+ }
+ }
+ }
+ }
+
+ public virtual void ReadOutputDataFromString( ref string[] nodeParams )
+ {
+ int count = 0;
+ if( UIUtils.CurrentShaderVersion() > 7003 )
+ {
+ count = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] );
+ }
+ else
+ {
+ count = m_outputPorts.Count;
+ }
+
+ for( int i = 0; i < count && i < nodeParams.Length && m_currentReadParamIdx < nodeParams.Length; i++ )
+ {
+ try
+ {
+ WirePortDataType dataType = (WirePortDataType)Enum.Parse( typeof( WirePortDataType ), nodeParams[ m_currentReadParamIdx++ ] );
+ int portId = -1;
+ if( UIUtils.CurrentShaderVersion() > 13903 )
+ {
+ portId = Convert.ToInt32( nodeParams[ m_currentReadParamIdx++ ] ); ;
+ }
+ else
+ {
+ portId = i;
+ }
+
+ OutputPort port = GetOutputPortByUniqueId( portId );
+ if( port != null && UIUtils.IsValidType( dataType ) )
+ {
+ port.DataType = dataType;
+ }
+
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+ }
+
+ public virtual void ReadAdditionalClipboardData( ref string[] nodeParams ) { }
+
+ protected string GetCurrentParam( ref string[] nodeParams )
+ {
+ if( m_currentReadParamIdx < nodeParams.Length )
+ {
+ return nodeParams[ m_currentReadParamIdx++ ];
+ }
+
+ UIUtils.ShowMessage( UniqueId, "Invalid params number in node " + m_uniqueId + " of type " + GetType(), MessageSeverity.Error );
+ return string.Empty;
+ }
+
+ protected string GetCurrentParam( int index, ref string[] nodeParams )
+ {
+ if( m_currentReadParamIdx < nodeParams.Length )
+ {
+ return nodeParams[ index ];
+ }
+
+ UIUtils.ShowMessage( UniqueId, "Invalid params number in node " + m_uniqueId + " of type " + GetType(), MessageSeverity.Error );
+ return string.Empty;
+ }
+
+
+ public virtual void WriteToString( ref string nodeInfo, ref string connectionsInfo )
+ {
+ IOUtils.AddTypeToString( ref nodeInfo, IOUtils.NodeParam );
+ IOUtils.AddFieldValueToString( ref nodeInfo, GetType() );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_uniqueId );
+ IOUtils.AddFieldValueToString( ref nodeInfo, ( m_position.x.ToString() + IOUtils.VECTOR_SEPARATOR + m_position.y.ToString() ) );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_currentPrecisionType );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_showPreview );
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ m_inputPorts[ i ].WriteToString( ref connectionsInfo );
+ }
+ }
+
+ public virtual void WriteInputDataToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts.Count );
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].PortId );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].DataType );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].InternalData );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].IsEditable );
+ if( m_inputPorts[ i ].IsEditable )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_inputPorts[ i ].Name );
+ }
+ }
+ }
+
+ public void WriteOutputDataToString( ref string nodeInfo )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts.Count );
+ for( int i = 0; i < m_outputPorts.Count; i++ )
+ {
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts[ i ].DataType );
+ IOUtils.AddFieldValueToString( ref nodeInfo, m_outputPorts[ i ].PortId );
+ }
+ }
+
+ public virtual void WriteAdditionalClipboardData( ref string nodeInfo ) { }
+
+ public virtual string GetIncludes() { return string.Empty; }
+ public virtual void OnObjectDropped( UnityEngine.Object obj ) { }
+ public virtual void SetupFromCastObject( UnityEngine.Object obj ) { }
+ public virtual bool OnNodeInteraction( ParentNode node ) { return false; }
+ public virtual void OnConnectedOutputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) { }
+ public virtual void OnConnectedInputNodeChanges( int portId, int otherNodeId, int otherPortId, string name, WirePortDataType type ) { }
+
+ public Rect CachedPos { get { return m_cachedPos; } }
+
+ public bool IsOnGrid
+ {
+ set { m_isOnGrid = value; }
+ get { return m_isOnGrid; }
+ }
+
+ public uint CurrentReadParamIdx
+ {
+ get { return m_currentReadParamIdx++; }
+ set { m_currentReadParamIdx = value; }
+ }
+
+ public Dictionary<string, InputPort> InputPortsDict
+ {
+ get
+ {
+ Dictionary<string, InputPort> dict = new Dictionary<string, InputPort>();
+ for( int i = 0; i < m_inputPorts.Count; i++ )
+ {
+ dict.Add( m_inputPorts[ i ].Name, m_inputPorts[ i ] );
+ }
+ return dict;
+ }
+ }
+
+ public bool IsDirty
+ {
+ set { m_isDirty = value && UIUtils.DirtyMask; }
+ get
+ {
+ bool value = m_isDirty;
+ m_isDirty = false;
+ return value;
+ }
+ }
+
+ public virtual void ResetNodeData()
+ {
+ m_category = 0;
+ m_graphDepth = 0;
+ }
+
+ public virtual void PropagateNodeData( NodeData nodeData, ref MasterNodeDataCollector dataCollector )
+ {
+ UIUtils.SetCategoryInBitArray( ref m_category, nodeData.Category );
+ nodeData.GraphDepth += 1;
+ if( nodeData.GraphDepth > m_graphDepth )
+ {
+ m_graphDepth = nodeData.GraphDepth;
+ }
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( m_inputPorts[ i ].IsConnected )
+ {
+ m_inputPorts[ i ].GetOutputNode().PropagateNodeData( nodeData, ref dataCollector );
+ }
+ }
+ }
+
+ public void SetTitleTextOnCallback( string compareTitle, Action<ParentNode, string> callback )
+ {
+ if( !m_previousTitle.Equals( compareTitle ) )
+ {
+ m_previousTitle = compareTitle;
+ m_sizeIsDirty = true;
+ callback( this, compareTitle );
+ }
+ }
+
+ public void SetAdditonalTitleTextOnCallback( string compareTitle, Action<ParentNode, string> callback )
+ {
+ if( !m_previousAdditonalTitle.Equals( compareTitle ) )
+ {
+ m_previousAdditonalTitle = compareTitle;
+ m_sizeIsDirty = true;
+ callback( this, compareTitle );
+ }
+ }
+
+ public virtual void SetClippedTitle( string newText, int maxSize = 170, string endString = "..." )
+ {
+ m_content.text = GenerateClippedTitle( newText,maxSize,endString );
+ m_sizeIsDirty = true;
+ }
+
+ public virtual void SetClippedAdditionalTitle( string newText, int maxSize = 170, string endString = "..." )
+ {
+ m_additionalContent.text = GenerateClippedTitle( newText, maxSize, endString );
+ m_sizeIsDirty = true;
+ }
+
+
+ public void SetTitleText( string newText )
+ {
+ if( !newText.Equals( m_content.text ) )
+ {
+ m_content.text = newText;
+ m_sizeIsDirty = true;
+ }
+ }
+
+ public void SetAdditonalTitleText( string newText )
+ {
+ if( !newText.Equals( m_additionalContent.text ) )
+ {
+ m_additionalContent.text = newText;
+ m_sizeIsDirty = true;
+ }
+ }
+
+ public string GenerateErrorValue( int outputIdx = 0 )
+ {
+ switch( m_outputPorts[ outputIdx ].DataType )
+ {
+ case WirePortDataType.FLOAT2:
+ {
+ return "(0).xx";
+ }
+ case WirePortDataType.FLOAT3:
+ {
+ return "(0).xxx";
+ }
+ case WirePortDataType.FLOAT4:
+ case WirePortDataType.COLOR:
+ {
+ return "(0).xxxx";
+ }
+ }
+ return "0";
+ }
+
+ //Methods created to take into account new ports added on nodes newer versions
+ //This way we can convert connections from previous versions to newer ones and not brake shader graph
+ public virtual int VersionConvertInputPortId( int portId ) { return portId; }
+ public virtual int VersionConvertOutputPortId( int portId ) { return portId; }
+
+ public virtual string DataToArray { get { return string.Empty; } }
+
+ public bool SaveIsDirty
+ {
+ set { m_saveIsDirty = value && UIUtils.DirtyMask; }
+ get
+ {
+ bool value = m_saveIsDirty;
+ m_saveIsDirty = false;
+ return value;
+ }
+ }
+
+ public GUIContent TitleContent { get { return m_content; } }
+ public GUIContent AdditonalTitleContent { get { return m_additionalContent; } }
+ public bool IsVisible { get { return m_isVisible; } }
+ public NodeAttributes Attributes { get { return m_nodeAttribs; } }
+ public bool ReorderLocked { get { return m_reorderLocked; } }
+ public bool RequireMaterialUpdate { get { return m_requireMaterialUpdate; } }
+ public bool RMBIgnore { get { return m_rmbIgnore; } }
+ public float TextLabelWidth { get { return m_textLabelWidth; } }
+ public bool IsMoving { get { return m_isMoving > 0; } }
+ public bool MovingInFrame { get { return m_movingInFrame; } set { m_movingInFrame = value; } }
+ public bool SizeIsDirty { get { return m_sizeIsDirty; } set { m_sizeIsDirty = value; } }
+ public int Category { get { return m_category; } }
+ public int CommentaryParent
+ {
+ get { return m_commentaryParent; }
+ set { m_commentaryParent = value; }
+ }
+
+ public int Depth
+ {
+ get { return m_depth; }
+ set { m_depth = value; }
+ }
+
+ public int MatrixId
+ {
+ get { return m_matrixId; }
+ set { m_matrixId = value; }
+ }
+
+ public float PaddingTitleRight
+ {
+ get { return m_paddingTitleRight; }
+ set { m_paddingTitleRight += value; }
+ }
+
+ public float PaddingTitleLeft
+ {
+ get { return m_paddingTitleLeft; }
+ set { m_paddingTitleLeft += value; }
+ }
+
+ public int CachedPortsId
+ {
+ get
+ {
+ return m_cachedPortsId;
+ }
+ }
+
+ public virtual bool RecursivePreviewUpdate( Dictionary<string,bool> duplicatesDict = null )
+ {
+ if( duplicatesDict == null )
+ {
+ duplicatesDict = ContainerGraph.ParentWindow.VisitedChanged;
+ }
+
+ for( int i = 0; i < InputPorts.Count; i++ )
+ {
+ ParentNode outNode = null;
+ if( InputPorts[ i ].ExternalReferences.Count > 0 )
+ {
+ outNode = ContainerGraph.GetNode( InputPorts[ i ].ExternalReferences[ 0 ].NodeId );
+ }
+ if( outNode != null )
+ {
+ if( !duplicatesDict.ContainsKey( outNode.OutputId ) )
+ {
+ bool result = outNode.RecursivePreviewUpdate();
+ if( result )
+ PreviewIsDirty = true;
+ } else if( duplicatesDict[ outNode.OutputId ] )
+ {
+ PreviewIsDirty = true;
+ }
+ }
+ }
+
+ bool needsUpdate = PreviewIsDirty;
+ RenderNodePreview();
+ if( !duplicatesDict.ContainsKey( OutputId ) )
+ duplicatesDict.Add( OutputId, needsUpdate );
+ return needsUpdate;
+ }
+
+ public virtual void RenderNodePreview()
+ {
+ //Runs at least one time
+ if( !HasPreviewShader || !m_initialized )
+ {
+ // nodes with no preview don't update at all
+ PreviewIsDirty = false;
+ return;
+ }
+
+ if( !PreviewIsDirty && !m_continuousPreviewRefresh )
+ return;
+
+ //Debug.Log( "PREVIEW " + this );
+
+ SetPreviewInputs();
+
+ if( m_cachedMainTexId == -1 )
+ m_cachedMainTexId = Shader.PropertyToID( "_MainTex" );
+
+ if( m_cachedMaskTexId == -1 )
+ m_cachedMaskTexId = Shader.PropertyToID( "_MaskTex" );
+
+ if( m_cachedPortsId == -1 )
+ m_cachedPortsId = Shader.PropertyToID( "_Ports" );
+
+ if( m_cachedPortId == -1 )
+ m_cachedPortId = Shader.PropertyToID( "_Port" );
+
+ int count = m_outputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ if( i == 0 )
+ {
+ RenderTexture temp = RenderTexture.active;
+ RenderTexture beforeMask = RenderTexture.GetTemporary( PreviewWidth, PreviewHeight, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear );
+ RenderTexture.active = beforeMask;
+ Graphics.Blit( null, beforeMask, PreviewMaterial, m_previewMaterialPassId );
+
+ m_portMask.Set( 0, 0, 0, 0 );
+
+ switch( m_outputPorts[ i ].DataType )
+ {
+ case WirePortDataType.INT:
+ case WirePortDataType.FLOAT:
+ m_portMask.Set( 1, 1, 1, 1 );
+ break;
+ case WirePortDataType.FLOAT2:
+ m_portMask.Set( 1, 1, 0, 0 );
+ break;
+ case WirePortDataType.FLOAT3:
+ m_portMask.Set( 1, 1, 1, 0 );
+ break;
+ case WirePortDataType.COLOR:
+ case WirePortDataType.FLOAT4:
+ m_portMask.Set( 1, 1, 1, 1 );
+ break;
+ default:
+ m_portMask.Set( 1, 1, 1, 1 );
+ break;
+ }
+
+ if( m_outputPorts[ i ].DataType == WirePortDataType.FLOAT3x3 || m_outputPorts[ i ].DataType == WirePortDataType.FLOAT4x4 )
+ {
+ m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMainTexId, EditorGUIUtility.whiteTexture );
+ }
+ else
+ {
+ m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMainTexId, beforeMask );
+ }
+ m_outputPorts[ i ].MaskingMaterial.SetVector( m_cachedPortsId, m_portMask );
+ RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture;
+ Graphics.Blit( null, m_outputPorts[ i ].OutputPreviewTexture, m_outputPorts[ i ].MaskingMaterial, 0 );
+
+ RenderTexture.ReleaseTemporary( beforeMask );
+ RenderTexture.active = temp;
+ }
+ else
+ {
+ RenderTexture temp = RenderTexture.active;
+ m_outputPorts[ i ].MaskingMaterial.SetTexture( m_cachedMaskTexId, PreviewTexture );
+ m_outputPorts[ i ].MaskingMaterial.SetFloat( m_cachedPortId, i );
+
+ RenderTexture.active = m_outputPorts[ i ].OutputPreviewTexture;
+ Graphics.Blit( null, m_outputPorts[ i ].OutputPreviewTexture, m_outputPorts[ i ].MaskingMaterial, 1 );
+ RenderTexture.active = temp;
+ }
+ }
+
+ PreviewIsDirty = m_continuousPreviewRefresh;
+
+ FinishPreviewRender = true;
+ }
+
+ protected void ShowTab( NodeMessageType type, string tooltip )
+ {
+ m_showErrorMessage = true;
+ m_errorMessageTypeIsError = type;
+ m_errorMessageTooltip = tooltip;
+ }
+
+ protected void ShowTab()
+ {
+ m_showErrorMessage = true;
+ }
+
+ protected void HideTab()
+ {
+ m_showErrorMessage = false;
+ }
+
+ public virtual RenderTexture PreviewTexture
+ {
+ get
+ {
+ if( m_outputPorts.Count > 0 )
+ return m_outputPorts[ 0 ].OutputPreviewTexture;
+ else
+ return null;
+ }
+ }
+
+ public void FullWriteToString( ref string nodesInfo, ref string connectionsInfo )
+ {
+ WriteToString( ref nodesInfo, ref connectionsInfo );
+ WriteInputDataToString( ref nodesInfo );
+ WriteOutputDataToString( ref nodesInfo );
+ }
+
+ public void ClipboardFullWriteToString( ref string nodesInfo, ref string connectionsInfo )
+ {
+ FullWriteToString( ref nodesInfo, ref connectionsInfo );
+ WriteAdditionalClipboardData( ref nodesInfo );
+ }
+
+ public void FullReadFromString( ref string[] parameters )
+ {
+ try
+ {
+ ReadFromString( ref parameters );
+ ReadInputDataFromString( ref parameters );
+ ReadOutputDataFromString( ref parameters );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ public void ClipboardFullReadFromString( ref string[] parameters )
+ {
+ try
+ {
+ FullReadFromString( ref parameters );
+ ReadAdditionalClipboardData( ref parameters );
+ }
+ catch( Exception e )
+ {
+ Debug.LogException( e );
+ }
+ }
+
+ public string GenerateClippedTitle( string original , int maxSize = 170, string endString = "..." )
+ {
+ if( UIUtils.UnZoomedNodeTitleStyle == null )
+ return original;
+
+ GUIContent content = new GUIContent( original );
+
+ string finalTitle = string.Empty;
+ bool addEllipsis = false;
+ for( int i = 1; i <= original.Length; i++ )
+ {
+ content.text = original.Substring( 0, i );
+ Vector2 titleSize = UIUtils.UnZoomedNodeTitleStyle.CalcSize( content );
+ if( titleSize.x > maxSize )
+ {
+ addEllipsis = true;
+ break;
+ }
+ else
+ {
+ finalTitle = content.text;
+ }
+ }
+ if( addEllipsis )
+ finalTitle += endString;
+
+ return finalTitle;
+ }
+
+ public virtual void RefreshOnUndo() { }
+ public virtual void CalculateCustomGraphDepth() { }
+ public int GraphDepth { get { return m_graphDepth; } }
+
+ public PrecisionType CurrentPrecisionType { get { return m_currentPrecisionType == PrecisionType.Inherit ? ContainerGraph.CurrentPrecision : m_currentPrecisionType; } }
+
+
+ public Material PreviewMaterial
+ {
+ get
+ {
+ if( m_previewMaterial == null )
+ {
+ m_previewMaterial = new Material( PreviewShader );
+ }
+ return m_previewMaterial;
+ }
+ }
+
+ public Shader PreviewShader
+ {
+ get
+ {
+ if( m_previewShader == null )
+ {
+ m_previewShader = AssetDatabase.LoadAssetAtPath<Shader>( AssetDatabase.GUIDToAssetPath( m_previewShaderGUID ) );
+ }
+
+ if( m_previewShader == null )
+ {
+ m_previewShader = AssetDatabase.LoadAssetAtPath<Shader>( AssetDatabase.GUIDToAssetPath( "d9ca47581ac157145bff6f72ac5dd73e" ) ); //ranged float guid
+ }
+
+ if( m_previewShader == null )
+ m_previewShader = Shader.Find( "Unlit/Colored Transparent" );
+
+ return m_previewShader;
+ }
+ }
+
+ public bool HasPreviewShader
+ {
+ get { return !string.IsNullOrEmpty( m_previewShaderGUID ); }
+ }
+
+ public void CheckSpherePreview()
+ {
+ bool oneIsSphere = false;
+
+ if( m_drawPreviewAsSphere )
+ oneIsSphere = true;
+ int count = m_inputPorts.Count;
+ for( int i = 0; i < count; i++ )
+ {
+ ParentNode node = null;
+ if( m_inputPorts[ i ].ExternalReferences.Count > 0)
+ {
+ node = ContainerGraph.GetNode( m_inputPorts[ i ].ExternalReferences[ 0 ].NodeId );
+ }
+ if( node != null && node.SpherePreview )
+ oneIsSphere = true;
+ }
+
+ if( m_forceDrawPreviewAsPlane )
+ oneIsSphere = false;
+
+ SpherePreview = oneIsSphere;
+ }
+
+ public bool SpherePreview
+ {
+ get { return m_spherePreview; }
+ set { m_spherePreview = value; }
+ }
+
+ public bool ShowPreview
+ {
+ get { return m_showPreview; }
+ set { m_showPreview = value; }
+ }
+
+ public int VisiblePorts
+ {
+ get { return m_visiblePorts; }
+ set { m_visiblePorts = value; }
+ }
+
+ public bool Docking
+ {
+ get { return m_docking; }
+ set { m_docking = value; }
+ }
+
+ public bool UseSquareNodeTitle
+ {
+ get { return m_useSquareNodeTitle; }
+ set { m_useSquareNodeTitle = value; }
+ }
+
+ public bool InsideShaderFunction
+ {
+ get { return ContainerGraph != ContainerGraph.ParentWindow.CurrentGraph; }
+ }
+
+ public virtual void SetContainerGraph( ParentGraph newgraph )
+ {
+ m_containerGraph = newgraph;
+ }
+ public virtual void OnMasterNodeReplaced( MasterNode newMasterNode ) { }
+ public virtual void RefreshExternalReferences() { }
+
+ public Rect DropdownRect { get { return m_dropdownRect; } }
+
+ public virtual bool Contains( Vector2 pos ) { return m_globalPosition.Contains( pos ); }
+ public virtual bool Contains( Vector3 pos ) { return m_globalPosition.Contains( pos ); }
+ public bool IsNodeBeingCopied { get { return m_isNodeBeingCopied; } set { m_isNodeBeingCopied = value; } }
+
+ public virtual WirePortDataType GetInputPortVisualDataTypeByArrayIdx( int portArrayIdx )
+ {
+ return m_inputPorts[ portArrayIdx ].DataType;
+ }
+
+ public virtual WirePortDataType GetOutputPortVisualDataTypeById( int portId )
+ {
+ return GetOutputPortByUniqueId( portId ).DataType;
+ }
+
+
+ public virtual bool CheckFindText( string text )
+ {
+ return TitleContent.text.IndexOf( text, StringComparison.CurrentCultureIgnoreCase ) >= 0;
+ }
+
+ public virtual float HeightEstimate
+ {
+ get
+ {
+ float heightEstimate = 0;
+ heightEstimate = 32 + Constants.INPUT_PORT_DELTA_Y;
+ for( int i = 0; i < InputPorts.Count; i++ )
+ {
+ if( InputPorts[ i ].Visible )
+ heightEstimate += 18 + Constants.INPUT_PORT_DELTA_Y;
+ }
+
+ return heightEstimate;
+ // Magic number 18 represents m_fontHeight that might not be set yet
+ //return Constants.NODE_HEADER_EXTRA_HEIGHT + Mathf.Max( 18 + m_inputPorts.Count, m_outputPorts.Count ) * Constants.INPUT_PORT_DELTA_Y;
+ }
+ }
+ public bool Alive { get { return m_alive;} set { m_alive = value; } }
+ public string TypeName { get { if( m_nodeAttribs != null ) return m_nodeAttribs.Name;return GetType().ToString(); } }
+ public bool PreviewIsDirty { set { m_previewIsDirty = value; } get { return m_previewIsDirty; } }
+ protected bool FinishPreviewRender { get { return m_finishPreviewRender; } set { m_finishPreviewRender = value; } }
+ }
+}