Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

Commit

Permalink
Added second cache system that does not directly work on an asset but…
Browse files Browse the repository at this point in the history
… instead saves the canvas at a specified interval and at NodeEditor shutdown

This enables future undo support (Undo does not work on assets) and is significantly faster, especially when creating nodes.
But is not completely safe when Unity crashes, as it will revert to the last cache save, depending on the set cache interval (default 1min).
A small stutter occurs when caching, so it should not be too frequent, but caching is prohibited while user performs an action (dragging,...) so it's not always noticeable.

It is possible to revert back to the old cache system if desired by uncommenting the first line '#define EDITOR_CACHE_ASSET' in NodeEditorUserCache.cs
  • Loading branch information
Seneral committed Jan 9, 2017
1 parent a4e8a3e commit 50b28a3
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 30 deletions.
7 changes: 2 additions & 5 deletions Editor/Node_Editor/NodeEditorWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ private void NormalReInit()

private void OnDestroy()
{
EditorUtility.SetDirty(canvasCache.nodeCanvas);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();

NodeEditor.ClientRepaints -= Repaint;

EditorLoadingControl.justLeftPlayMode -= NormalReInit;
Expand Down Expand Up @@ -256,7 +252,8 @@ private void DrawSideWindow()
NodeEditor.ReInit (true);

NodeEditorGUI.knobSize = EditorGUILayout.IntSlider (new GUIContent ("Handle Size", "The size of the Node Input/Output handles"), NodeEditorGUI.knobSize, 12, 20);
canvasCache.editorState.zoom = EditorGUILayout.Slider (new GUIContent ("Zoom", "Use the Mousewheel. Seriously."), canvasCache.editorState.zoom, 0.6f, 4);
//canvasCache.editorState.zoom = EditorGUILayout.Slider (new GUIContent ("Zoom", "Use the Mousewheel. Seriously."), canvasCache.editorState.zoom, 0.6f, 4);
NodeEditorUserCache.cacheIntervalSec = EditorGUILayout.IntSlider (new GUIContent ("Cache Interval (Sec)", "The interval in seconds the canvas is temporarily saved into the cache as a precaution for crashes."), NodeEditorUserCache.cacheIntervalSec, 30, 300);

// NodeEditorGUI.curveBaseDirection = EditorGUILayout.FloatField ("Curve Base Dir", NodeEditorGUI.curveBaseDirection);
// NodeEditorGUI.curveBaseStart = EditorGUILayout.FloatField ("Curve Base Start", NodeEditorGUI.curveBaseStart);
Expand Down
4 changes: 2 additions & 2 deletions Node_Editor/Framework/NodeEditorSaveManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ public static void SaveNodeCanvas (string path, NodeCanvas nodeCanvas, bool crea
}
}

UnityEditor.AssetDatabase.SaveAssets ();
UnityEditor.AssetDatabase.Refresh ();
//UnityEditor.AssetDatabase.SaveAssets ();
//UnityEditor.AssetDatabase.Refresh ();
#else
// TODO: Node Editor: Need to implement ingame-saving (Resources, AsssetBundles, ... won't work)
#endif
Expand Down
97 changes: 74 additions & 23 deletions Node_Editor/Framework/NodeEditorUserCache.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
//#define EDITOR_CACHE_ASSET

using System;
using System.IO;
using System.Collections.Generic;

Expand All @@ -17,10 +19,16 @@ public class NodeEditorUserCache

public NodeCanvasTypeData typeData;

private string cachePath;
#if EDITOR_CACHE_ASSET
private const bool cacheWorkingCopy = false;
#else
private const bool cacheWorkingCopy = true;
public static int cacheIntervalSec = 60;
private double lastCacheTime;
#endif
private bool useCache;
private string cachePath;
private const string MainEditorStateIdentifier = "MainEditorState";

private string lastSessionPath { get { return cachePath + "/LastSession.asset"; } }

public string openedCanvasPath = "";
Expand Down Expand Up @@ -55,27 +63,56 @@ public NodeEditorUserCache (string CachePath)

public void SetupCacheEvents ()
{
#if UNITY_EDITOR
if (!useCache)
return;

#if EDITOR_CACHE_ASSET
// Add new objects to the cache save file
NodeEditorCallbacks.OnAddNode -= SaveNewNode;
NodeEditorCallbacks.OnAddNode += SaveNewNode;
NodeEditorCallbacks.OnAddNodeKnob -= SaveNewNodeKnob;
NodeEditorCallbacks.OnAddNodeKnob += SaveNewNodeKnob;
#else
UnityEditor.EditorApplication.update -= CheckCacheUpdate;
UnityEditor.EditorApplication.update += CheckCacheUpdate;
lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup;
#endif

LoadCache ();
#endif
}

public void ClearCacheEvents ()
{
#if UNITY_EDITOR && EDITOR_CACHE_ASSET
NodeEditorCallbacks.OnAddNode -= SaveNewNode;
NodeEditorCallbacks.OnAddNodeKnob -= SaveNewNodeKnob;
#elif UNITY_EDITOR
RecreateCache ();
UnityEditor.EditorApplication.update -= CheckCacheUpdate;
#endif
}

#if UNITY_EDITOR && !EDITOR_CACHE_ASSET
private void CheckCacheUpdate ()
{
//Debug.Log ("Checking for cache save!");
if (UnityEditor.EditorApplication.timeSinceStartup-lastCacheTime > cacheIntervalSec)
{
if (editorState.dragUserID == "" && editorState.connectOutput == null && GUIUtility.hotControl <= 0 && !OverlayGUI.HasPopupControl ())
{ // Only save when the user currently does not perform an action that could be interrupted by the save
lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup;
RecreateCache ();
}
}
}
#endif

#if UNITY_EDITOR && EDITOR_CACHE_ASSET

private void SaveNewNode (Node node)
{
#if UNITY_EDITOR
if (!useCache)
return;
CheckCurrentCache ();
Expand All @@ -97,12 +134,10 @@ private void SaveNewNode (Node node)
}

UpdateCacheFile ();
#endif
}

private void SaveNewNodeKnob (NodeKnob knob)
{
#if UNITY_EDITOR
if (!useCache)
return;
CheckCurrentCache ();
Expand All @@ -117,19 +152,22 @@ private void SaveNewNodeKnob (NodeKnob knob)
NodeEditorSaveManager.AddSubAsset (so, knob);

UpdateCacheFile ();
#endif
}

#endif

/// <summary>
/// Creates a new cache save file for the currently loaded canvas
/// Only called when a new canvas is created or loaded
/// </summary>
private void RecreateCache ()
{
#if UNITY_EDITOR
if (!useCache)
return;
DeleteCache ();
SaveCache ();
#endif
}

/// <summary>
Expand All @@ -138,17 +176,23 @@ private void RecreateCache ()
/// </summary>
private void SaveCache ()
{
#if UNITY_EDITOR
if (!useCache)
return;
UnityEditor.EditorUtility.SetDirty (nodeCanvas);
if (editorState != null)
UnityEditor.EditorUtility.SetDirty (editorState);
#if !EDITOR_CACHE_ASSET
lastCacheTime = UnityEditor.EditorApplication.timeSinceStartup;
#endif
nodeCanvas.editorStates = new NodeEditorState[] { editorState };
if (nodeCanvas.livesInScene)
NodeEditorSaveManager.SaveSceneNodeCanvas ("lastSession", ref nodeCanvas, false);
#if UNITY_EDITOR
NodeEditorSaveManager.SaveSceneNodeCanvas ("lastSession", ref nodeCanvas, cacheWorkingCopy);
else
NodeEditorSaveManager.SaveNodeCanvas (lastSessionPath, nodeCanvas, false, false);
#endif
NodeEditorSaveManager.SaveNodeCanvas (lastSessionPath, nodeCanvas, cacheWorkingCopy, false);

CheckCurrentCache ();
#endif
}

/// <summary>
Expand All @@ -157,67 +201,74 @@ private void SaveCache ()
/// </summary>
private void LoadCache ()
{
#if UNITY_EDITOR
if (!useCache)
{
NewNodeCanvas ();
return;
}
// Try to load the NodeCanvas
if (
#if UNITY_EDITOR
(!File.Exists (lastSessionPath) || (nodeCanvas = NodeEditorSaveManager.LoadNodeCanvas (lastSessionPath, false)) == null) && // Check for asset cache
#endif
(nodeCanvas = NodeEditorSaveManager.LoadSceneNodeCanvas ("lastSession", false)) == null) // Check for scene cache
(!File.Exists (lastSessionPath) || (nodeCanvas = NodeEditorSaveManager.LoadNodeCanvas (lastSessionPath, cacheWorkingCopy)) == null) && // Check for asset cache
(nodeCanvas = NodeEditorSaveManager.LoadSceneNodeCanvas ("lastSession", cacheWorkingCopy)) == null) // Check for scene cache
{
NewNodeCanvas ();
return;
}

// Fetch the associated MainEditorState
editorState = NodeEditorSaveManager.ExtractEditorState (nodeCanvas, MainEditorStateIdentifier);
#if UNITY_EDITOR
if (!nodeCanvas.livesInScene && !UnityEditor.AssetDatabase.Contains (editorState))
NodeEditorSaveManager.AddSubAsset (editorState, lastSessionPath);
#endif

CheckCurrentCache ();
UpdateCanvasInfo ();
NodeEditor.Calculator.RecalculateAll (nodeCanvas);
NodeEditor.RepaintClients ();
NodeEditor.RepaintClients ();
#endif
}

private void CheckCurrentCache ()
{
#if UNITY_EDITOR && EDITOR_CACHE_ASSET
if (!useCache)
return;
if (nodeCanvas.livesInScene)
{
if (NodeEditorSaveManager.FindOrCreateSceneSave ("lastSession").savedNodeCanvas != nodeCanvas)
throw new UnityException ("Cache system error: Current scene canvas is not saved as the temporary cache scene save!");
}
#if UNITY_EDITOR
else if (UnityEditor.AssetDatabase.GetAssetPath (nodeCanvas) != lastSessionPath)
throw new UnityException ("Cache system error: Current asset canvas is not saved as the temporary cache asset!");
#elif UNITY_EDITOR
if (!useCache)
return;
if (nodeCanvas.livesInScene)
{
if (NodeEditorSaveManager.FindOrCreateSceneSave ("lastSession").savedNodeCanvas == null)
RecreateCache ();
}
else if (UnityEditor.AssetDatabase.LoadAssetAtPath<NodeCanvas> (lastSessionPath) == null)
RecreateCache ();
#endif
}

private void DeleteCache ()
{
#if UNITY_EDITOR
if (!useCache)
return;
#if UNITY_EDITOR
UnityEditor.AssetDatabase.DeleteAsset (lastSessionPath);
UnityEditor.AssetDatabase.Refresh ();
//UnityEditor.EditorPrefs.DeleteKey ("NodeEditorLastSession");
#endif
NodeEditorSaveManager.DeleteSceneNodeCanvas ("lastSession");
#endif
}

private void UpdateCacheFile ()
{
#if UNITY_EDITOR
if (!useCache)
return;
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty (nodeCanvas);
UnityEditor.AssetDatabase.SaveAssets ();
UnityEditor.AssetDatabase.Refresh ();
Expand Down

0 comments on commit 50b28a3

Please sign in to comment.