diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
index 7de90f743..e7568f439 100644
--- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
@@ -225,8 +225,7 @@ namespace FlaxEditor.Surface.Archetypes
///
public override void OnDestroy()
{
- if (Surface != null)
- Surface.RemoveContext(this);
+ Surface?.RemoveContext(this);
_maxTransitionsPerUpdate = null;
_reinitializeOnBecomingRelevant = null;
@@ -717,9 +716,12 @@ namespace FlaxEditor.Surface.Archetypes
LoadTransitions();
- // Register for surface mouse events to handle transition arrows interactions
- Surface.CustomMouseUp += OnSurfaceMouseUp;
- Surface.CustomMouseDoubleClick += OnSurfaceMouseDoubleClick;
+ if (Surface != null)
+ {
+ // Register for surface mouse events to handle transition arrows interactions
+ Surface.CustomMouseUp += OnSurfaceMouseUp;
+ Surface.CustomMouseDoubleClick += OnSurfaceMouseDoubleClick;
+ }
}
private void OnSurfaceMouseUp(ref Float2 mouse, MouseButton buttons, ref bool handled)
@@ -1398,7 +1400,8 @@ namespace FlaxEditor.Surface.Archetypes
if (context.FindNode(9, 21) == null)
{
var wasEnabled = true;
- if (Surface.Undo != null)
+ var undo = Surface?.Undo;
+ if (undo != null)
{
wasEnabled = Surface.Undo.Enabled;
Surface.Undo.Enabled = false;
@@ -1406,7 +1409,7 @@ namespace FlaxEditor.Surface.Archetypes
context.SpawnNode(9, 21, new Float2(100.0f));
- if (Surface.Undo != null)
+ if (undo != null)
{
Surface.Undo.Enabled = wasEnabled;
}
@@ -1492,7 +1495,7 @@ namespace FlaxEditor.Surface.Archetypes
///
public override void OnDestroy()
{
- Surface.RemoveContext(this);
+ Surface?.RemoveContext(this);
base.OnDestroy();
}
@@ -1886,7 +1889,7 @@ namespace FlaxEditor.Surface.Archetypes
if (context.FindNode(9, 22) == null)
{
var wasEnabled = true;
- var undo = SourceState.Surface.Undo;
+ var undo = SourceState.Surface?.Undo;
if (undo != null)
{
wasEnabled = undo.Enabled;
diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs
index d072ee28e..94e7c21ba 100644
--- a/Source/Editor/Surface/SurfaceComment.cs
+++ b/Source/Editor/Surface/SurfaceComment.cs
@@ -87,7 +87,7 @@ namespace FlaxEditor.Surface
Title = TitleValue;
Color = ColorValue;
var size = SizeValue;
- if (Surface.GridSnappingEnabled)
+ if (Surface != null && Surface.GridSnappingEnabled)
size = Surface.SnapToGrid(size, true);
Size = size;
diff --git a/Source/Editor/Surface/VisjectSurface.Context.cs b/Source/Editor/Surface/VisjectSurface.Context.cs
index 1197b387b..3fe29adaa 100644
--- a/Source/Editor/Surface/VisjectSurface.Context.cs
+++ b/Source/Editor/Surface/VisjectSurface.Context.cs
@@ -2,8 +2,8 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.Surface.Undo;
-using FlaxEngine;
namespace FlaxEditor.Surface
{
@@ -57,6 +57,28 @@ namespace FlaxEditor.Surface
return null;
}
+ ///
+ /// Opens the surface context with the given owning nodes IDs path.
+ ///
+ /// The node ids path.
+ /// Found context or null if cannot.
+ public VisjectSurfaceContext OpenContext(Span nodePath)
+ {
+ OpenContext(RootContext.Context);
+ if (nodePath != null && nodePath.Length != 0)
+ {
+ for (int i = 0; i < nodePath.Length; i++)
+ {
+ var node = Context.FindNode(nodePath[i]);
+ if (node is ISurfaceContext context)
+ OpenContext(context);
+ else
+ return null;
+ }
+ }
+ return Context;
+ }
+
///
/// Creates the Visject surface context for the given surface data source context.
///
@@ -101,7 +123,12 @@ namespace FlaxEditor.Surface
if (_root == null)
_root = surfaceContext;
else if (ContextStack.Contains(surfaceContext))
- throw new ArgumentException("Context has been already added to the stack.");
+ {
+ // Go up until the given context
+ while (ContextStack.First() != surfaceContext)
+ CloseContext();
+ return;
+ }
// Change stack
ContextStack.Push(surfaceContext);
diff --git a/Source/Editor/Windows/Search/ContentSearchWindow.cs b/Source/Editor/Windows/Search/ContentSearchWindow.cs
index 0e3d1efdc..dd506a849 100644
--- a/Source/Editor/Windows/Search/ContentSearchWindow.cs
+++ b/Source/Editor/Windows/Search/ContentSearchWindow.cs
@@ -13,7 +13,6 @@ using FlaxEditor.GUI.Docking;
using FlaxEditor.GUI.Input;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Options;
-using FlaxEditor.Scripting;
using FlaxEditor.Surface;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
@@ -496,6 +495,7 @@ namespace FlaxEngine.Windows.Search
// Iterate over all assets
var tempFolder = StringUtils.NormalizePath(Path.GetDirectoryName(Globals.TemporaryFolder));
+ var nodePath = new List();
for (var i = 0; i < assets.Length && !_token.IsCancellationRequested; i++)
{
var id = assets[i];
@@ -512,20 +512,21 @@ namespace FlaxEngine.Windows.Search
continue;
// Search asset contents
+ nodePath.Clear();
if (asset is VisualScript visualScript)
- SearchAsyncInnerVisject(asset, visualScript.LoadSurface());
+ SearchAsyncInnerVisject(asset, visualScript.LoadSurface(), nodePath);
else if (asset is Material material)
- SearchAsyncInnerVisject(asset, material.LoadSurface(false));
+ SearchAsyncInnerVisject(asset, material.LoadSurface(false), nodePath);
else if (asset is MaterialFunction materialFunction)
- SearchAsyncInnerVisject(asset, materialFunction.LoadSurface());
+ SearchAsyncInnerVisject(asset, materialFunction.LoadSurface(), nodePath);
else if (asset is AnimationGraph animationGraph)
- SearchAsyncInnerVisject(asset, animationGraph.LoadSurface());
+ SearchAsyncInnerVisject(asset, animationGraph.LoadSurface(), nodePath);
else if (asset is AnimationGraphFunction animationGraphFunction)
- SearchAsyncInnerVisject(asset, animationGraphFunction.LoadSurface());
+ SearchAsyncInnerVisject(asset, animationGraphFunction.LoadSurface(), nodePath);
else if (asset is ParticleEmitter particleEmitter)
- SearchAsyncInnerVisject(asset, particleEmitter.LoadSurface(false));
+ SearchAsyncInnerVisject(asset, particleEmitter.LoadSurface(false), nodePath);
else if (asset is ParticleEmitterFunction particleEmitterFunction)
- SearchAsyncInnerVisject(asset, particleEmitterFunction.LoadSurface());
+ SearchAsyncInnerVisject(asset, particleEmitterFunction.LoadSurface(), nodePath);
// Don't eat whole performance
Thread.Sleep(15);
@@ -551,7 +552,7 @@ namespace FlaxEngine.Windows.Search
};
}
- private void SearchAsyncInnerVisject(Asset asset, byte[] surfaceData)
+ private void SearchAsyncInnerVisject(Asset asset, byte[] surfaceData, List nodePath)
{
// Load Visject surface from data
if (surfaceData == null || surfaceData.Length == 0)
@@ -566,7 +567,6 @@ namespace FlaxEngine.Windows.Search
if (_visjectSurfaceStyle == null)
_visjectSurfaceStyle = SurfaceStyle.CreateDefault(Editor);
SearchResultTreeNode assetTreeNode = null;
- // TODO: support nested surfaces (eg. in Anim Graph)
// Search parameters
foreach (var parameter in _visjectSurfaceContext.Parameters)
@@ -592,7 +592,8 @@ namespace FlaxEngine.Windows.Search
// Search nodes
var newTreeNodes = new List();
- foreach (var node in _visjectSurfaceContext.Nodes)
+ var nodes = _visjectSurfaceContext.Nodes.ToArray();
+ foreach (var node in nodes)
{
newTreeNodes.Clear();
if (node.Values != null)
@@ -602,12 +603,18 @@ namespace FlaxEngine.Windows.Search
SearchVisjectMatch(value, (matchedValue, matchedText) =>
{
var valueTreeNode = AddVisjectSearchResult(matchedValue, matchedText, node.Archetype.ConnectionsHints);
- valueTreeNode.Tag = node.ID;
+ valueTreeNode.Tag = new VisjectNodeTag { NodeId = node.ID, NodePath = nodePath.ToArray() };
valueTreeNode.Navigate = OnNavigateVisjectNode;
newTreeNodes.Add(valueTreeNode);
});
}
}
+ if (node is ISurfaceContext context)
+ {
+ nodePath.Add(node.ID);
+ SearchAsyncInnerVisject(asset, context.SurfaceData, nodePath);
+ nodePath.RemoveAt(nodePath.Count - 1);
+ }
var nodeSearchText = node.ContentSearchText;
if (newTreeNodes.Count != 0 || (nodeSearchText != null && IsSearchMatch(ref nodeSearchText)))
@@ -617,7 +624,7 @@ namespace FlaxEngine.Windows.Search
{
Text = node.Title,
TooltipText = node.TooltipText,
- Tag = node.ID,
+ Tag = new VisjectNodeTag { NodeId = node.ID, NodePath = nodePath.ToArray() },
Navigate = OnNavigateVisjectNode,
Parent = assetTreeNode,
};
@@ -723,9 +730,15 @@ namespace FlaxEngine.Windows.Search
Editor.ContentEditing.Open(contentItem);
}
+ private struct VisjectNodeTag
+ {
+ public uint NodeId;
+ public uint[] NodePath;
+ }
+
private void OnNavigateVisjectNode(SearchResultTreeNode treeNode)
{
- var nodeId = (uint)treeNode.Tag;
+ var tag = (VisjectNodeTag)treeNode.Tag;
var assetId = Guid.Empty;
var assetTreeNode = treeNode.Parent;
while (!(assetTreeNode.Tag is Guid))
@@ -734,7 +747,8 @@ namespace FlaxEngine.Windows.Search
var contentItem = Editor.ContentDatabase.FindAsset(assetId);
if (Editor.ContentEditing.Open(contentItem) is IVisjectSurfaceWindow window)
{
- var node = window.VisjectSurface.FindNode(nodeId);
+ var context = window.VisjectSurface.OpenContext(tag.NodePath) ?? window.VisjectSurface.Context;
+ var node = context.FindNode(tag.NodeId);
if (node != null)
{
// Focus this node