//$ Copyright 2015-22, Code Respawn Technologies Pvt Ltd - All Rights Reserved $//
using UnityEngine;
using System.Collections.Generic;
namespace DungeonArchitect.Graphs
{
///
/// Represents a graph node in the theme graph. This is the base class for all graph nodes
///
[System.Serializable]
public class GraphNode : ScriptableObject
{
[SerializeField]
[HideInInspector]
protected string id;
///
/// The ID of the graph node
///
public string Id
{
get
{
return id;
}
set { id = value; }
}
[SerializeField]
[HideInInspector]
protected string caption;
///
/// The caption label of the node. It is up to the implementation to draw this label, if needed
///
public string Caption
{
get
{
return caption;
}
set
{
caption = value;
}
}
[SerializeField]
[HideInInspector]
protected Rect bounds = new Rect(10, 10, 120, 120);
///
/// The bounds of the node
///
public Rect Bounds
{
get
{
return bounds;
}
set
{
bounds = value;
}
}
[SerializeField]
[HideInInspector]
protected bool canBeDeleted = true;
public bool CanBeDeleted
{
get { return canBeDeleted; }
}
[SerializeField]
[HideInInspector]
protected bool canBeSelected = true;
public bool CanBeSelected
{
get { return canBeSelected; }
}
[SerializeField]
[HideInInspector]
protected bool canBeMoved = true;
public bool CanBeMoved
{
get { return canBeMoved; }
}
[SerializeField]
[HideInInspector]
protected bool selected = false;
///
/// Flag to indicate if the node has been selected
///
public bool Selected
{
get
{
return selected;
}
set
{
if (canBeSelected)
{
selected = value;
}
else
{
selected = false;
}
}
}
///
/// The size of the node
///
public Vector2 Size
{
get { return bounds.size; }
set
{
bounds.size = value;
}
}
///
/// The position of the node
///
public Vector2 Position
{
get { return bounds.position; }
set
{
bounds.position = value;
}
}
[SerializeField]
[HideInInspector]
protected int zIndex;
///
/// The Z-index of the node. It determines if the node is on top of other nodes
///
public int ZIndex
{
get
{
return zIndex;
}
set
{
zIndex = value;
}
}
[SerializeField]
[HideInInspector]
protected List inputPins;
///
/// List of input pins owned by this node
///
public GraphPin[] InputPins
{
get
{
return inputPins != null ? inputPins.ToArray() : new GraphPin[0];
}
}
[SerializeField]
[HideInInspector]
protected List outputPins;
///
/// List of output pins owned by this node
///
public GraphPin[] OutputPins
{
get
{
return outputPins != null ? outputPins.ToArray() : new GraphPin[0];
}
}
///
/// Gets the first output pin. Returns null if no output pins are defined
///
public GraphPin OutputPin
{
get
{
if (outputPins == null || outputPins.Count == 0) return null;
return outputPins[0];
}
}
///
/// Gets the first input pin. Returns null if no input pins are defined
///
public GraphPin InputPin
{
get
{
if (inputPins == null || inputPins.Count == 0) return null;
return inputPins[0];
}
}
[SerializeField]
[HideInInspector]
protected Graph graph;
///
/// The graph that owns this node
///
public Graph Graph
{
get
{
return graph;
}
}
public virtual void OnEnable()
{
hideFlags = HideFlags.HideInHierarchy;
}
public virtual void Initialize(string id, Graph graph)
{
this.id = id;
this.graph = graph;
}
///
/// Called when the node is copied.
/// The implementations should implement copy here (e.g. deep / shallow copy depending on implementation)
///
///
public virtual void CopyFrom(GraphNode node)
{
if (node != null)
{
caption = node.Caption;
this.bounds = node.Bounds;
}
}
protected void UpdateName(string prefix)
{
this.name = prefix + id;
}
private bool dragging = false;
public bool Dragging
{
get { return dragging; }
set { dragging = value; }
}
///
/// Creates a pin with the specified configuration
///
/// The type of pin (input / output)
/// The position of the pin, relative to the node bounds
/// The bounds of the pin, relative to the position
/// The tangent of the pin. Links connected to the pin would come out from this direction
protected GraphPin CreatePin(GraphPinType pinType, Vector2 position, Rect boundsOffset, Vector2 tangent)
{
return CreatePinOfType(pinType, position, boundsOffset, tangent);
}
protected T CreatePinOfType(GraphPinType pinType, Vector2 position, Rect boundsOffset, Vector2 tangent) where T : GraphPin
{
var pin = CreateInstance();
pin.PinType = pinType;
pin.Node = this;
pin.Position = position;
pin.BoundsOffset = boundsOffset;
pin.Tangent = tangent;
if (pinType == GraphPinType.Input)
{
pin.name = this.name + "_InputPin";
if (inputPins == null)
{
inputPins = new List();
}
inputPins.Add(pin);
}
else
{
pin.name = this.name + "_OutputPin";
if (outputPins == null)
{
outputPins = new List();
}
outputPins.Add(pin);
}
return pin;
}
///
/// Gets the list of parent graph nodes
///
/// List of parent graph nodes
public GraphNode[] GetParentNodes()
{
var parents = new List();
if (InputPins.Length > 0)
{
foreach (var link in InputPins[0].GetConntectedLinks())
{
if (link != null && link.Output != null && link.Output.Node != null)
{
parents.Add(link.Output.Node);
}
}
}
return parents.ToArray();
}
///
/// Gets the list of child nodes
///
/// List of child nodes
public GraphNode[] GetChildNodes()
{
var children = new List();
if (OutputPins.Length > 0)
{
foreach (var link in OutputPins[0].GetConntectedLinks())
{
if (link != null && link.Input != null && link.Input.Node != null)
{
children.Add(link.Input.Node);
}
}
}
return children.ToArray();
}
///
/// Moves the node by the specified delta
///
/// The delta offset to move the node by
public void DragNode(Vector2 delta)
{
Position += delta;
}
}
}