using System.Linq;
using System;
using System.Xml.Linq;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
namespace GraphProcessor
{
[System.Serializable]
public abstract class BaseGraphWindow : EditorWindow
{
protected VisualElement rootView;
protected BaseGraphView graphView;
[SerializeField]
protected BaseGraph graph;
readonly string graphWindowStyle = "GraphProcessorStyles/BaseGraphView";
public bool isGraphLoaded
{
get { return graphView != null && graphView.graph != null; }
}
bool reloadWorkaround = false;
public event Action< BaseGraph > graphLoaded;
public event Action< BaseGraph > graphUnloaded;
///
/// Called by Unity when the window is enabled / opened
///
protected virtual void OnEnable()
{
InitializeRootView();
if (graph != null)
LoadGraph();
else
reloadWorkaround = true;
}
protected virtual void Update()
{
// Workaround for the Refresh option of the editor window:
// When Refresh is clicked, OnEnable is called before the serialized data in the
// editor window is deserialized, causing the graph view to not be loaded
if (reloadWorkaround && graph != null)
{
LoadGraph();
reloadWorkaround = false;
}
}
void LoadGraph()
{
// We wait for the graph to be initialized
if (graph.isEnabled)
InitializeGraph(graph);
else
graph.onEnabled += () => InitializeGraph(graph);
}
///
/// Called by Unity when the window is disabled (happens on domain reload)
///
protected virtual void OnDisable()
{
if (graph != null && graphView != null)
graphView.SaveGraphToDisk();
}
///
/// Called by Unity when the window is closed
///
protected virtual void OnDestroy() { }
void InitializeRootView()
{
rootView = base.rootVisualElement;
rootView.name = "graphRootView";
rootView.styleSheets.Add(Resources.Load(graphWindowStyle));
}
public void InitializeGraph(BaseGraph graph)
{
if (this.graph != null && graph != this.graph)
{
// Save the graph to the disk
EditorUtility.SetDirty(this.graph);
AssetDatabase.SaveAssets();
// Unload the graph
graphUnloaded?.Invoke(this.graph);
}
graphLoaded?.Invoke(graph);
this.graph = graph;
if (graphView != null)
rootView.Remove(graphView);
//Initialize will provide the BaseGraphView
InitializeWindow(graph);
graphView = rootView.Children().FirstOrDefault(e => e is BaseGraphView) as BaseGraphView;
if (graphView == null)
{
Debug.LogError("GraphView has not been added to the BaseGraph root view !");
return ;
}
graphView.Initialize(graph);
InitializeGraphView(graphView);
// TOOD: onSceneLinked...
if (graph.IsLinkedToScene())
LinkGraphWindowToScene(graph.GetLinkedScene());
else
graph.onSceneLinked += LinkGraphWindowToScene;
}
void LinkGraphWindowToScene(Scene scene)
{
EditorSceneManager.sceneClosed += CloseWindowWhenSceneIsClosed;
void CloseWindowWhenSceneIsClosed(Scene closedScene)
{
if (scene == closedScene)
{
Close();
EditorSceneManager.sceneClosed -= CloseWindowWhenSceneIsClosed;
}
}
}
public virtual void OnGraphDeleted()
{
if (graph != null && graphView != null)
rootView.Remove(graphView);
graphView = null;
}
protected abstract void InitializeWindow(BaseGraph graph);
protected virtual void InitializeGraphView(BaseGraphView view) {}
}
}