// 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; } }
|
|
}
|
|
}
|