1
0
mirror of https://github.com/Siccity/xNode.git synced 2025-12-20 17:26:02 +08:00

RuntimeMathGraph functional

This commit is contained in:
Thor Brigsted 2018-05-12 14:39:49 +02:00
parent e1109e4a0a
commit 42bb9a927a
26 changed files with 489 additions and 109 deletions

View File

@ -4,12 +4,12 @@ using UnityEngine;
using UnityEngine.EventSystems;
namespace XNode.Examples.RuntimeMathNodes {
public class NodeDrag : MonoBehaviour, IPointerDownHandler, IDragHandler {
public class NodeDrag : MonoBehaviour, IPointerDownHandler, IDragHandler, IEndDragHandler {
private Vector3 offset;
private RuntimeMathNodes node;
private UGUIMathBaseNode node;
private void Awake() {
node = GetComponentInParent<RuntimeMathNodes>();
node = GetComponentInParent<UGUIMathBaseNode>();
}
public void OnDrag(PointerEventData eventData) {
@ -21,5 +21,12 @@ namespace XNode.Examples.RuntimeMathNodes {
Vector2 pos = node.transform.localPosition;
offset = pointer - pos;
}
public void OnEndDrag(PointerEventData eventData) {
node.transform.localPosition = node.graph.scrollRect.content.InverseTransformPoint(eventData.position) - offset;
Vector2 pos = node.transform.localPosition;
pos.y = -pos.y;
node.node.position = pos;
}
}
}

View File

@ -2,38 +2,58 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class RuntimeMathGraph : MonoBehaviour {
public class RuntimeMathGraph : MonoBehaviour, IPointerClickHandler {
[Header("Graph")]
public MathGraph graph;
[Header("Prefabs")]
public XNode.Examples.RuntimeMathNodes.MathNode runtimeMathNodePrefab;
public XNode.Examples.RuntimeMathNodes.Vector runtimeVectorPrefab;
public XNode.Examples.RuntimeMathNodes.DisplayValue runtimeDisplayValuePrefab;
public XNode.Examples.RuntimeMathNodes.UGUIMathNode runtimeMathNodePrefab;
public XNode.Examples.RuntimeMathNodes.UGUIVector runtimeVectorPrefab;
public XNode.Examples.RuntimeMathNodes.UGUIDisplayValue runtimeDisplayValuePrefab;
public XNode.Examples.RuntimeMathNodes.Connection runtimeConnectionPrefab;
[Header("References")]
public UGUIContextMenu contextMenu;
public UGUITooltip tooltip;
public ScrollRect scrollRect { get; private set; }
private List<RuntimeMathNodes> nodes;
private List<UGUIMathBaseNode> nodes;
private void Awake() {
// Create a clone so we don't modify the original asset
graph = graph.Copy() as MathGraph;
scrollRect = GetComponentInChildren<ScrollRect>();
contextMenu.onClickSpawn -= SpawnNode;
contextMenu.onClickSpawn += SpawnNode;
}
private void Start() {
SpawnGraph();
}
public void Refresh() {
Clear();
SpawnGraph();
}
public void Clear() {
for (int i = nodes.Count - 1; i >= 0; i--) {
Destroy(nodes[i].gameObject);
}
nodes.Clear();
}
public void SpawnGraph() {
if (nodes != null) nodes.Clear();
else nodes = new List<RuntimeMathNodes>();
else nodes = new List<UGUIMathBaseNode>();
for (int i = 0; i < graph.nodes.Count; i++) {
Node node = graph.nodes[i];
RuntimeMathNodes runtimeNode = null;
UGUIMathBaseNode runtimeNode = null;
if (node is XNode.Examples.MathNodes.MathNode) {
runtimeNode = Instantiate(runtimeMathNodePrefab);
} else if (node is XNode.Examples.MathNodes.Vector) {
@ -48,14 +68,27 @@ namespace XNode.Examples.RuntimeMathNodes {
}
}
public RuntimeMathNodes GetRuntimeNode(Node node) {
public UGUIMathBaseNode GetRuntimeNode(Node node) {
for (int i = 0; i < nodes.Count; i++) {
if (nodes[i].node == node) {
return nodes[i];
} else {
}
} else { }
}
return null;
}
public void SpawnNode(Type type, Vector2 position) {
Node node = graph.AddNode(type);
node.name = type.Name;
node.position = position;
Refresh();
}
public void OnPointerClick(PointerEventData eventData) {
if (eventData.button != PointerEventData.InputButton.Right)
return;
contextMenu.OpenAt(eventData.position);
}
}
}

View File

@ -1,8 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class DisplayValue : RuntimeMathNodes { }
}

View File

@ -1,8 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class MathNode : RuntimeMathNodes { }
}

View File

@ -1,72 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class RuntimeMathNodes : MonoBehaviour, IDragHandler {
[HideInInspector] public Node node;
[HideInInspector] public RuntimeMathGraph graph;
public Text header;
public List<Transform> ports;
private List<Connection> connections = new List<Connection>();
private void Start() {
header.text = node.name;
SetPosition(node.position);
foreach (NodePort port in node.Outputs) {
if (port.IsConnected) {
for (int i = 0; i < port.ConnectionCount; i++) {
Connection connection = Instantiate(graph.runtimeConnectionPrefab);
connection.transform.SetParent(graph.scrollRect.content);
connections.Add(connection);
}
}
}
}
void LateUpdate() {
UpdateConnectionTransforms();
}
public void UpdateConnectionTransforms() {
int c = 0;
foreach (NodePort port in node.Outputs) {
Transform port1 = GetPort(port.fieldName);
if (!port1) Debug.LogWarning(port.fieldName + " not found", this);
for (int i = 0; i < port.ConnectionCount; i++) {
NodePort other = port.GetConnection(i);
Connection connection = connections[c++];
RuntimeMathNodes otherNode = graph.GetRuntimeNode(other.node);
if (!otherNode) Debug.LogWarning(other.node.name + " node not found", this);
Transform port2 = otherNode.GetPort(other.fieldName);
if (!port2) Debug.LogWarning(other.fieldName + " not found", this);
connection.SetPosition(port1.position, port2.position);
}
}
}
public Transform GetPort(string name) {
for (int i = 0; i < ports.Count; i++) {
if (ports[i].name == name) return ports[i];
}
return null;
}
public void SetPosition(Vector2 pos) {
pos.y = -pos.y;
transform.localPosition = pos;
}
public void SetName(string name) {
header.text = name;
}
public void OnDrag(PointerEventData eventData) {
}
}
}

View File

@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIDisplayValue : UGUIMathBaseNode {
public Text label;
void Update() {
DisplayValue displayValue = node as DisplayValue;
object obj = displayValue.GetInputValue<object>("input");
if (obj != null) label.text = obj.ToString();
else label.text = "n/a";
}
}
}

View File

@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIMathBaseNode : MonoBehaviour, IDragHandler {
[HideInInspector] public Node node;
[HideInInspector] public RuntimeMathGraph graph;
public Text header;
private UGUIPort[] ports;
public virtual void Start() {
ports = GetComponentsInChildren<UGUIPort>();
foreach (UGUIPort port in ports) port.node = node;
header.text = node.name;
SetPosition(node.position);
}
public virtual void UpdateGUI() { }
private void LateUpdate() {
foreach (UGUIPort port in ports) port.UpdateConnectionTransforms();
}
public UGUIPort GetPort(string name) {
for (int i = 0; i < ports.Length; i++) {
if (ports[i].name == name) return ports[i];
}
return null;
}
public void SetPosition(Vector2 pos) {
pos.y = -pos.y;
transform.localPosition = pos;
}
public void SetName(string name) {
header.text = name;
}
public void OnDrag(PointerEventData eventData) {
}
}
}

View File

@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIMathNode : UGUIMathBaseNode {
public InputField valA;
public InputField valB;
public Dropdown dropDown;
private MathNode mathNode;
public override void Start() {
base.Start();
mathNode = node as MathNode;
valA.onValueChanged.AddListener(OnChangeValA);
valB.onValueChanged.AddListener(OnChangeValB);
dropDown.onValueChanged.AddListener(OnChangeDropdown);
UpdateGUI();
}
public override void UpdateGUI() {
NodePort portA = node.GetInputPort("a");
NodePort portB = node.GetInputPort("b");
valA.gameObject.SetActive(!portA.IsConnected);
valB.gameObject.SetActive(!portB.IsConnected);
valA.text = mathNode.a.ToString();
valB.text = mathNode.b.ToString();
dropDown.value = (int) mathNode.mathType;
}
private void OnChangeValA(string val) {
mathNode.a = float.Parse(valA.text);
}
private void OnChangeValB(string val) {
mathNode.b = float.Parse(valB.text);
}
private void OnChangeDropdown(int val) {
mathNode.mathType = (MathNode.MathType) val;
}
}
}

View File

@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIVector : UGUIMathBaseNode {
public InputField valX;
public InputField valY;
public InputField valZ;
private Vector vectorNode;
public override void Start() {
base.Start();
vectorNode = node as Vector;
valX.onValueChanged.AddListener(OnChangeValX);
valY.onValueChanged.AddListener(OnChangeValY);
valZ.onValueChanged.AddListener(OnChangeValZ);
UpdateGUI();
}
public override void UpdateGUI() {
NodePort portX = node.GetInputPort("x");
NodePort portY = node.GetInputPort("y");
NodePort portZ = node.GetInputPort("z");
valX.gameObject.SetActive(!portX.IsConnected);
valY.gameObject.SetActive(!portY.IsConnected);
valZ.gameObject.SetActive(!portZ.IsConnected);
Vector vectorNode = node as Vector;
valX.text = vectorNode.x.ToString();
valY.text = vectorNode.y.ToString();
valZ.text = vectorNode.z.ToString();
}
private void OnChangeValX(string val) {
vectorNode.x = float.Parse(valX.text);
}
private void OnChangeValY(string val) {
vectorNode.y = float.Parse(valY.text);
}
private void OnChangeValZ(string val) {
vectorNode.z = float.Parse(valZ.text);
}
}
}

View File

@ -1,8 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XNode.Examples.MathNodes;
namespace XNode.Examples.RuntimeMathNodes {
public class Vector : RuntimeMathNodes { }
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIContextMenu : MonoBehaviour, IPointerExitHandler {
public Action<Type, Vector2> onClickSpawn;
public CanvasGroup group;
private Vector2 pos;
private void Start() {
Close();
}
public void OpenAt(Vector2 pos) {
transform.position = pos;
group.alpha = 1;
group.interactable = true;
group.blocksRaycasts = true;
transform.SetAsLastSibling();
}
public void Close() {
group.alpha = 0;
group.interactable = false;
group.blocksRaycasts = false;
}
public void SpawnMathNode() {
SpawnNode(typeof(XNode.Examples.MathNodes.MathNode));
}
public void SpawnDisplayNode() {
SpawnNode(typeof(XNode.Examples.MathNodes.DisplayValue));
}
public void SpawnVectorNode() {
SpawnNode(typeof(XNode.Examples.MathNodes.Vector));
}
private void SpawnNode(Type nodeType) {
Vector2 pos = new Vector2(transform.localPosition.x, -transform.localPosition.y);
onClickSpawn(nodeType, pos);
}
public void OnPointerExit(PointerEventData eventData) {
Close();
}
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 402b5de5d75c05445994c83bba07d273
timeCreated: 1526035634
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,132 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XNode;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUIPort : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler {
public string fieldName;
[HideInInspector] public XNode.Node node;
private NodePort port;
private Connection tempConnection;
private NodePort startPort;
private UGUIPort tempHovered;
private RuntimeMathGraph graph;
private Vector2 startPos;
private List<Connection> connections = new List<Connection>();
void Start() {
port = node.GetPort(fieldName);
graph = GetComponentInParent<RuntimeMathGraph>();
if (port.IsOutput && port.IsConnected) {
for (int i = 0; i < port.ConnectionCount; i++) {
AddConnection();
}
}
}
void Reset() {
fieldName = name;
}
private void OnDestroy() {
// Also destroy connections
for (int i = connections.Count - 1; i >= 0; i--) {
Destroy(connections[i].gameObject);
}
connections.Clear();
}
public void UpdateConnectionTransforms() {
if (port.IsInput) return;
while (connections.Count < port.ConnectionCount) AddConnection();
while (connections.Count > port.ConnectionCount) {
Destroy(connections[0].gameObject);
connections.RemoveAt(0);
}
// Loop through connections
for (int i = 0; i < port.ConnectionCount; i++) {
NodePort other = port.GetConnection(i);
UGUIMathBaseNode otherNode = graph.GetRuntimeNode(other.node);
if (!otherNode) Debug.LogWarning(other.node.name + " node not found", this);
Transform port2 = otherNode.GetPort(other.fieldName).transform;
if (!port2) Debug.LogWarning(other.fieldName + " not found", this);
connections[i].SetPosition(transform.position, port2.position);
}
}
private void AddConnection() {
Connection connection = Instantiate(graph.runtimeConnectionPrefab);
connection.transform.SetParent(graph.scrollRect.content);
connections.Add(connection);
}
public void OnBeginDrag(PointerEventData eventData) {
if (port.IsOutput) {
tempConnection = Instantiate(graph.runtimeConnectionPrefab);
tempConnection.transform.SetParent(graph.scrollRect.content);
tempConnection.SetPosition(transform.position, eventData.position);
startPos = transform.position;
startPort = port;
} else {
if (port.IsConnected) {
NodePort output = port.Connection;
Debug.Log("has " + port.ConnectionCount + " connections");
Debug.Log(port.GetConnection(0));
UGUIMathBaseNode otherNode = graph.GetRuntimeNode(output.node);
UGUIPort otherUGUIPort = otherNode.GetPort(output.fieldName);
Debug.Log("Disconnect");
output.Disconnect(port);
tempConnection = Instantiate(graph.runtimeConnectionPrefab);
tempConnection.transform.SetParent(graph.scrollRect.content);
tempConnection.SetPosition(otherUGUIPort.transform.position, eventData.position);
startPos = otherUGUIPort.transform.position;
startPort = otherUGUIPort.port;
graph.GetRuntimeNode(node).UpdateGUI();
}
}
}
public void OnDrag(PointerEventData eventData) {
if (tempConnection == null) return;
UGUIPort otherPort = FindPortInStack(eventData.hovered);
tempHovered = otherPort;
tempConnection.SetPosition(startPos, eventData.position);
}
public void OnEndDrag(PointerEventData eventData) {
if (tempConnection == null) return;
if (tempHovered) {
startPort.Connect(tempHovered.port);
graph.GetRuntimeNode(tempHovered.node).UpdateGUI();
}
Destroy(tempConnection.gameObject);
}
public UGUIPort FindPortInStack(List<GameObject> stack) {
for (int i = 0; i < stack.Count; i++) {
UGUIPort port = stack[i].GetComponent<UGUIPort>();
if (port) return port;
}
return null;
}
public void OnPointerEnter(PointerEventData eventData) {
graph.tooltip.Show();
object obj = node.GetInputValue<object>(port.fieldName, null);
if (obj != null) graph.tooltip.label.text = obj.ToString();
else graph.tooltip.label.text = "n/a";
}
public void OnPointerExit(PointerEventData eventData) {
graph.tooltip.Hide();
}
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 76c005fc401e40f42b1e76d5ffc80292
timeCreated: 1526084889
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,45 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XNode.Examples.RuntimeMathNodes {
public class UGUITooltip : MonoBehaviour {
public CanvasGroup group;
public Text label;
private bool show;
private RuntimeMathGraph graph;
private void Awake() {
graph = GetComponentInParent<RuntimeMathGraph>();
}
private void Start() {
Hide();
}
private void Update() {
if (show) UpdatePosition();
}
public void Show() {
show = true;
group.alpha = 1;
UpdatePosition();
transform.SetAsLastSibling();
}
public void Hide() {
show = false;
group.alpha = 0;
}
private void UpdatePosition() {
Vector2 pos;
RectTransform rect = graph.scrollRect.content.transform as RectTransform;
Camera cam = graph.gameObject.GetComponentInParent<Canvas>().worldCamera;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, Input.mousePosition, cam, out pos);
transform.localPosition = pos;
}
}
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 6ea6060c58096cd4d8c959a427a9b059
timeCreated: 1526123957
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: