using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using System;
using Object = UnityEngine.Object;
namespace XNodeEditor {
[InitializeOnLoad]
public partial class NodeEditorWindow : EditorWindow {
public static NodeEditorWindow current;
/// Stores node positions for all nodePorts.
public Dictionary portConnectionPoints { get { return _portConnectionPoints; } }
private Dictionary _portConnectionPoints = new Dictionary();
[SerializeField] private NodePortReference[] _references = new NodePortReference[0];
[SerializeField] private Rect[] _rects = new Rect[0];
private Func isDocked {
get {
if (_isDocked == null) _isDocked = this.GetIsDockedDelegate();
return _isDocked;
}
}
private Func _isDocked;
[System.Serializable] private class NodePortReference {
[SerializeField] private XNode.Node _node;
[SerializeField] private string _name;
public NodePortReference(XNode.NodePort nodePort) {
_node = nodePort.node;
_name = nodePort.fieldName;
}
public XNode.NodePort GetNodePort() {
if (_node == null) {
return null;
}
return _node.GetPort(_name);
}
}
private void OnDisable() {
// Cache portConnectionPoints before serialization starts
int count = portConnectionPoints.Count;
_references = new NodePortReference[count];
_rects = new Rect[count];
int index = 0;
foreach (var portConnectionPoint in portConnectionPoints) {
_references[index] = new NodePortReference(portConnectionPoint.Key);
_rects[index] = portConnectionPoint.Value;
index++;
}
}
private void OnEnable() {
// Reload portConnectionPoints if there are any
int length = _references.Length;
if (length == _rects.Length) {
for (int i = 0; i < length; i++) {
XNode.NodePort nodePort = _references[i].GetNodePort();
if (nodePort != null)
_portConnectionPoints.Add(nodePort, _rects[i]);
}
}
}
public Dictionary nodeSizes { get { return _nodeSizes; } }
private Dictionary _nodeSizes = new Dictionary();
public XNode.NodeGraph graph;
public Vector2 panOffset { get { return _panOffset; } set { _panOffset = value; Repaint(); } }
private Vector2 _panOffset;
public float zoom { get { return _zoom; } set { _zoom = Mathf.Clamp(value, NodeEditorPreferences.GetSettings().minZoom, NodeEditorPreferences.GetSettings().maxZoom); Repaint(); } }
private float _zoom = 1;
void OnFocus() {
current = this;
ValidateGraphEditor();
if (graphEditor != null) {
graphEditor.OnWindowFocus();
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
}
dragThreshold = Math.Max(1f, Screen.width / 1000f);
}
void OnLostFocus() {
if (graphEditor != null) graphEditor.OnWindowFocusLost();
}
[InitializeOnLoadMethod]
private static void OnLoad() {
Selection.selectionChanged -= OnSelectionChanged;
Selection.selectionChanged += OnSelectionChanged;
}
/// Handle Selection Change events
private static void OnSelectionChanged() {
XNode.NodeGraph nodeGraph = Selection.activeObject as XNode.NodeGraph;
if (nodeGraph && !AssetDatabase.Contains(nodeGraph)) {
Open(nodeGraph);
}
}
/// Make sure the graph editor is assigned and to the right object
private void ValidateGraphEditor() {
NodeGraphEditor graphEditor = NodeGraphEditor.GetEditor(graph, this);
if (this.graphEditor != graphEditor && graphEditor != null) {
this.graphEditor = graphEditor;
graphEditor.OnOpen();
}
}
/// Create editor window
public static NodeEditorWindow Init() {
NodeEditorWindow w = CreateInstance();
w.titleContent = new GUIContent("xNode");
w.wantsMouseMove = true;
w.Show();
return w;
}
public void Save() {
if (AssetDatabase.Contains(graph)) {
EditorUtility.SetDirty(graph);
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
} else SaveAs();
}
public void SaveAs() {
string path = EditorUtility.SaveFilePanelInProject("Save NodeGraph", "NewNodeGraph", "asset", "");
if (string.IsNullOrEmpty(path)) return;
else {
XNode.NodeGraph existingGraph = AssetDatabase.LoadAssetAtPath(path);
if (existingGraph != null) AssetDatabase.DeleteAsset(path);
AssetDatabase.CreateAsset(graph, path);
EditorUtility.SetDirty(graph);
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
}
}
private void DraggableWindow(int windowID) {
GUI.DragWindow();
}
public Vector2 WindowToGridPosition(Vector2 windowPosition) {
return (windowPosition - (position.size * 0.5f) - (panOffset / zoom)) * zoom;
}
public Vector2 GridToWindowPosition(Vector2 gridPosition) {
return (position.size * 0.5f) + (panOffset / zoom) + (gridPosition / zoom);
}
public Rect GridToWindowRectNoClipped(Rect gridRect) {
gridRect.position = GridToWindowPositionNoClipped(gridRect.position);
return gridRect;
}
public Rect GridToWindowRect(Rect gridRect) {
gridRect.position = GridToWindowPosition(gridRect.position);
gridRect.size /= zoom;
return gridRect;
}
public Vector2 GridToWindowPositionNoClipped(Vector2 gridPosition) {
Vector2 center = position.size * 0.5f;
// UI Sharpness complete fix - Round final offset not panOffset
float xOffset = Mathf.Round(center.x * zoom + (panOffset.x + gridPosition.x));
float yOffset = Mathf.Round(center.y * zoom + (panOffset.y + gridPosition.y));
return new Vector2(xOffset, yOffset);
}
public void SelectNode(XNode.Node node, bool add) {
if (add) {
List