using System; using System.Collections.Generic; using UnityEngine; namespace FIMSpace.Graph { public abstract partial class FGraph_NodeBase : ScriptableObject { [HideInInspector] public int IndividualID = -1; /// Custom name [HideInInspector] public string NameID = ""; /// Mostly used for header title for search bar [HideInInspector][SerializeField] protected bool wasCreated = false; /// /// You can call it when you create node on any graph /// public virtual void OnCreated() { wasCreated = true; } /// Refreshing node position changes 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() { } /// Can be used for displaying debugging progress on node from 0 to 1 for example public float DebuggingProgress { get; set; } = -1f; [HideInInspector] /*[SerializeReference]*/ public List OutputConnections = new List(); [HideInInspector] /*[SerializeReference]*/ public List InputConnections = new List(); 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; } } /// If you want to call only on one of the outputs, return value greater than -1 public virtual int AllowedOutputConnectionIndex { get { return -1; } } /// Used just for auto-connecting trigger nodes public virtual int HotOutputConnectionIndex { get { return -1; } } /// By default is false public virtual bool DrawInputConnector { get { return false; } } /// By default is true public virtual bool DrawOutputConnector { get { return true; } } #region Multiple connectors to support custom implementations /// Used only with custom implementations for multiple connectors public virtual int InputConnectorsCount { get { return 1; } } /// Used only with custom implementations for multiple connectors public virtual string GetInputHelperText(int outputId = 0) { return ""; } /// Used only with custom implementations for multiple connectors public virtual int OutputConnectorsCount { get { return 1; } } /// Used only with custom implementations for multiple connectors public virtual string GetOutputHelperText(int outputId = 0) { return ""; } #endregion #region Node Related (Graph+Playmode) /// (base is empty) Triggered after adding node to graph display public virtual void RefreshNodeParams() { } /// Clear connections of other ports with this node public virtual void OnRemoving() { MarkConnnectedNodesForRefresh(inputPorts); MarkConnnectedNodesForRefresh(outputPorts); } /// Marking connected nodes for ports refresh void MarkConnnectedNodesForRefresh(List 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; } } } /// Connected nodes using ports / connectors //public List GetConnectedNodes() //{ // List nodes = new List(); // 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); } } [HideInInspector] public Vector2 NodePosition = Vector2.zero; [HideInInspector] public Vector2 NodeDrawOffset = new Vector2(0, 0); #endregion #region Styling Utilities public static void CheckForNulls(List 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; } } /// By default is false public virtual bool IsFoldable { get { return false; } } /// Drawing resize handle in right bottom corner and implementing resizing feature public virtual bool IsResizable { get { return false; } } /// Resize scale of node using IsResizable handle [HideInInspector] public Vector2 ResizedScale = new Vector2(200, 140); /// Different handling inputs for the node if is containable public virtual bool IsContainable { get { return false; } } #if UNITY_EDITOR /// Containable node is holding reference data about nodes inside it [HideInInspector] public List _EditorInContainedRange = new List(); /// If node is contained inside some containable node [HideInInspector] public FGraph_NodeBase IsContainedBy = null; /// If node was drawn on the graph or was culled / hidden by some other node [NonSerialized] public bool _EditorWasDrawn = false; #endif /// Used on comment node, for some reason unity is not saving some serialization changes when folding/unfolding public virtual bool IsFoldableFix { get { return false; } } /// Helper variable for editor use [HideInInspector]/*[NonSerialized]*/ public bool _EditorFoldout = false; public bool IsDrawingGUIInNodeMode { get; set; } public virtual Color GetNodeColor() { return Color.white; } /// Executed when node is started to be draw by graph drawer 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 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 } }