Files
BITFALL/Assets/Plugins/FImpossible Creations/Shared Tools/Node FGraph/Node Base/FGraph_NodeBase.cs
CortexCore ba342d6627 1
2023-11-30 00:23:23 +08:00

292 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace FIMSpace.Graph
{
public abstract partial class FGraph_NodeBase : ScriptableObject
{
[HideInInspector] public int IndividualID = -1;
/// <summary> Custom name </summary>
[HideInInspector] public string NameID = "";
/// <summary> Mostly used for header title for search bar </summary>
[HideInInspector][SerializeField] protected bool wasCreated = false;
/// <summary>
/// You can call it when you create node on any graph
/// </summary>
public virtual void OnCreated() { wasCreated = true; }
/// <summary> Refreshing node position changes </summary>
public virtual void OnEndDrag()
{
#if UNITY_EDITOR
if (baseSerializedObject == null) return;
baseSerializedObject.ApplyModifiedProperties();
baseSerializedObject.Update();
#endif
}
public virtual void OnCursorExitNode()
{
#region Just disabling default wires draw on node cursor exit
for (int p = 0; p < inputPorts.Count; p++)
{
NodePortBase prt = inputPorts[p] as NodePortBase;
if (prt != null) prt._EditorForceDrawDefaultWires = false;
}
for (int p = 0; p < outputPorts.Count; p++)
{
NodePortBase prt = outputPorts[p] as NodePortBase;
if (prt != null) prt._EditorForceDrawDefaultWires = false;
}
#if UNITY_EDITOR
_editorForceDrawDefaultTriggerWires = false;
#endif
#endregion
}
public virtual void OnCursorEnterOnNode()
{
}
/// <summary> Can be used for displaying debugging progress on node from 0 to 1 for example </summary>
public float DebuggingProgress { get; set; } = -1f;
[HideInInspector] /*[SerializeReference]*/ public List<FGraph_TriggerNodeConnection> OutputConnections = new List<FGraph_TriggerNodeConnection>();
[HideInInspector] /*[SerializeReference]*/ public List<FGraph_TriggerNodeConnection> InputConnections = new List<FGraph_TriggerNodeConnection>();
public FGraph_NodeBase FirstOutputConnection
{
get
{
if (OutputConnections.Count < 1) return null;
if (AllowedOutputConnectionIndex < -1) return null;
if (AllowedOutputConnectionIndex == -1) return OutputConnections[0].GetOther(this);
//if (OutputConnections[0] == null) return null;
if (AllowedOutputConnectionIndex >= OutputConnections.Count)
{
for (int i = 0; i < OutputConnections.Count; i++)
{
if (OutputConnections[i].ConnectionFrom_AlternativeID == AllowedOutputConnectionIndex)
return OutputConnections[i].GetOther(this);
}
}
if (AllowedOutputConnectionIndex < OutputConnections.Count)
return OutputConnections[AllowedOutputConnectionIndex].GetOther(this);
else
return null;
}
}
/// <summary> If you want to call only on one of the outputs, return value greater than -1 </summary>
public virtual int AllowedOutputConnectionIndex { get { return -1; } }
/// <summary> Used just for auto-connecting trigger nodes </summary>
public virtual int HotOutputConnectionIndex { get { return -1; } }
/// <summary> By default is false </summary>
public virtual bool DrawInputConnector { get { return false; } }
/// <summary> By default is true </summary>
public virtual bool DrawOutputConnector { get { return true; } }
#region Multiple connectors to support custom implementations
/// <summary> Used only with custom implementations for multiple connectors </summary>
public virtual int InputConnectorsCount { get { return 1; } }
/// <summary> Used only with custom implementations for multiple connectors </summary>
public virtual string GetInputHelperText(int outputId = 0) { return ""; }
/// <summary> Used only with custom implementations for multiple connectors </summary>
public virtual int OutputConnectorsCount { get { return 1; } }
/// <summary> Used only with custom implementations for multiple connectors </summary>
public virtual string GetOutputHelperText(int outputId = 0) { return ""; }
#endregion
#region Node Related (Graph+Playmode)
/// <summary> (base is empty) Triggered after adding node to graph display </summary>
public virtual void RefreshNodeParams() { }
/// <summary> Clear connections of other ports with this node </summary>
public virtual void OnRemoving()
{
MarkConnnectedNodesForRefresh(inputPorts);
MarkConnnectedNodesForRefresh(outputPorts);
}
/// <summary> Marking connected nodes for ports refresh </summary>
void MarkConnnectedNodesForRefresh(List<IFGraphPort> ports)
{
for (int i = 0; i < ports.Count; i++)
{
NodePortBase port = NodePortBase.ToNodePortBase(ports[i]);
if (port == null) continue;
for (int c = 0; c < port.Connections.Count; c++)
{
var conn = port.Connections[c];
if (conn.NodeReference) conn.NodeReference.forceRefreshPorts = true;
}
}
}
/// <summary> Connected nodes using ports / connectors </summary>
//public List<FGraph_NodeBase> GetConnectedNodes()
//{
// List<FGraph_NodeBase> nodes = new List<FGraph_NodeBase>();
// for (int i = 0; i < inputPorts.Count; i++)
// {
// NodePortBase port = NodePortBase.ToNodePortBase( inputPorts[i]);
// if (port == null) continue;
// }
//}
#endregion
#region Editor Draw Node Bases
public Rect _E_LatestRect { get; set; }
public virtual Vector2 NodeSize { get { return new Vector2(200, 100); } }
public Vector2 _EditorNodeSize { get { if ( _EditorCollapse) return new Vector2(CompressedNodeSizeX, 62); else return NodeSize; } }
public float CompressedNodeSizeX
{
get
{
int nameLen = GetDisplayName().Length;
if (nameLen > 14) return NodeSize.x;
else return 60 + nameLen * 10;
}
}
[HideInInspector] public Vector2 NodePosition = Vector2.zero;
[HideInInspector] public Vector2 NodeDrawOffset = new Vector2(0, 0);
#endregion
#region Styling Utilities
public static void CheckForNulls<T>(List<T> classes)
{
for (int i = classes.Count - 1; i >= 0; i--)
{
if (classes[i] == null) classes.RemoveAt(i);
}
}
public virtual string GetNodeSubName { get { return NameID; } }
public virtual Texture GetNodeIcon { get { return null; } }
public virtual string GetNodeTooltipDescription { get { return string.Empty; } }
/// <summary> By default is false </summary>
public virtual bool IsFoldable { get { return false; } }
/// <summary> Drawing resize handle in right bottom corner and implementing resizing feature </summary>
public virtual bool IsResizable { get { return false; } }
/// <summary> Resize scale of node using IsResizable handle </summary>
[HideInInspector] public Vector2 ResizedScale = new Vector2(200, 140);
/// <summary> Different handling inputs for the node if is containable </summary>
public virtual bool IsContainable { get { return false; } }
#if UNITY_EDITOR
/// <summary> Containable node is holding reference data about nodes inside it </summary>
[HideInInspector] public List<FGraph_NodeBase> _EditorInContainedRange = new List<FGraph_NodeBase>();
/// <summary> If node is contained inside some containable node </summary>
[HideInInspector] public FGraph_NodeBase IsContainedBy = null;
/// <summary> If node was drawn on the graph or was culled / hidden by some other node </summary>
[NonSerialized] public bool _EditorWasDrawn = false;
#endif
/// <summary> Used on comment node, for some reason unity is not saving some serialization changes when folding/unfolding </summary>
public virtual bool IsFoldableFix { get { return false; } }
/// <summary> Helper variable for editor use </summary>
[HideInInspector]/*[NonSerialized]*/ public bool _EditorFoldout = false;
[HideInInspector]/*[NonSerialized]*/ public bool _EditorCollapse = false;
public bool IsDrawingGUIInNodeMode { get; set; }
public virtual Color GetNodeColor() { return Color.white; }
/// <summary> Executed when node is started to be draw by graph drawer </summary>
public virtual void OnCreatedDrawer() { RefreshNodeParams(); }
public virtual string GetDisplayName(float maxWidth = 120)
{
#if UNITY_EDITOR
Vector2 size = UnityEditor.EditorStyles.largeLabel.CalcSize(new GUIContent(NameID));
string dName = NameID;
if (dName.Length > 2)
if (size.x > maxWidth)
dName = dName.Substring(0, Mathf.Min(11, dName.Length - 1)) + "...";
return dName;
#else
return NameID;
#endif
}
#endregion
#region ID Handling
public virtual void GenerateID(List<FGraph_NodeBase> allNodes)
{
#if UNITY_EDITOR
if (baseSerializedObject.targetObject == null) return;
baseSerializedObject.Update();
#endif
int targetId = int.MinValue + allNodes.Count;
bool unique = false;
while (!unique)
{
if (targetId == -1) targetId = 0;
bool found = false;
for (int i = 0; i < allNodes.Count; i++)
{
if ((allNodes[i] is null)) continue;
if (allNodes[i].IndividualID == targetId) { found = true; break; }
}
if (found == false) { unique = true; break; }
targetId += 1;
}
IndividualID = targetId;
#if UNITY_EDITOR
RefreshPorts();
baseSerializedObject.ApplyModifiedProperties();
#endif
_E_SetDirty();
}
#endregion
}
}