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

3786 lines
118 KiB

// 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 bool m_wasDeprecated = false;
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:
case WirePortDataType.SAMPLER2DARRAY:
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.FLOAT && m_inputPorts[ i ].DataType <= WirePortDataType.INT ) || m_inputPorts[ i ].DataType == WirePortDataType.UINT ) )
{
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 ) || port.DataType == WirePortDataType.OBJECT ) //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 int InputIdFromDeprecated( int oldInputId ) { return oldInputId; }
public virtual int OutputIdFromDeprecated( int oldOutputId ) { return oldOutputId; }
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 WasDeprecated { get { return m_wasDeprecated; } set { m_wasDeprecated = value; } }
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; } }
}
}