Add support for loading Visject surfaces without Surface UI

This commit is contained in:
Wojtek Figat
2022-05-06 18:45:12 +02:00
parent 78d6fe6b50
commit 1acac3845e
16 changed files with 171 additions and 88 deletions

View File

@@ -227,7 +227,8 @@ namespace FlaxEditor.Surface.Archetypes
/// <inheritdoc />
public override void OnDestroy()
{
Surface.RemoveContext(this);
if (Surface != null)
Surface.RemoveContext(this);
_maxTransitionsPerUpdate = null;
_reinitializeOnBecomingRelevant = null;

View File

@@ -53,7 +53,8 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded();
UpdateTitle();
if (Surface != null)
UpdateTitle();
}
private void UpdateTitle()

View File

@@ -309,6 +309,8 @@ namespace FlaxEditor.Surface.Archetypes
_output.CurrentType = dictionaryType;
_isUpdatingUI = false;
if (Surface == null)
return;
var canEdit = Surface.CanEdit;
_keyTypePicker.Enabled = canEdit;
_valueTypePicker.Enabled = canEdit;

View File

@@ -380,16 +380,19 @@ namespace FlaxEditor.Surface.Archetypes
public FunctionInputNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
: base(id, context, nodeArch, groupArch)
{
_types = ((IFunctionSurface)Surface).FunctionTypes;
_typePicker = new ComboBox
if (Surface is IFunctionSurface surface)
{
Location = new Vector2(4, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
_typePicker.AddItem(Surface.GetTypeName(new ScriptType(_types[i])));
_nameField.Location = new Vector2(_typePicker.Right + 2.0f, _typePicker.Y);
_types = surface.FunctionTypes;
_typePicker = new ComboBox
{
Location = new Vector2(4, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
_typePicker.AddItem(Surface.GetTypeName(new ScriptType(_types[i])));
_nameField.Location = new Vector2(_typePicker.Right + 2.0f, _typePicker.Y);
}
}
/// <inheritdoc />
@@ -401,8 +404,11 @@ namespace FlaxEditor.Surface.Archetypes
_outputBox.CurrentType = SignatureType;
_defaultValueBox = GetBox(1);
_defaultValueBox.CurrentType = _outputBox.CurrentType;
_typePicker.SelectedIndex = Array.IndexOf(_types, _outputBox.CurrentType.Type);
_typePicker.SelectedIndexChanged += OnTypePickerSelectedIndexChanged;
if (_typePicker != null)
{
_typePicker.SelectedIndex = Array.IndexOf(_types, _outputBox.CurrentType.Type);
_typePicker.SelectedIndexChanged += OnTypePickerSelectedIndexChanged;
}
}
private void OnTypePickerSelectedIndexChanged(ComboBox picker)
@@ -417,7 +423,8 @@ namespace FlaxEditor.Surface.Archetypes
_outputBox.CurrentType = SignatureType;
_defaultValueBox.CurrentType = _outputBox.CurrentType;
_typePicker.SelectedIndex = Array.IndexOf(_types, _outputBox.CurrentType.Type);
if (_typePicker != null)
_typePicker.SelectedIndex = Array.IndexOf(_types, _outputBox.CurrentType.Type);
}
/// <inheritdoc />
@@ -442,16 +449,19 @@ namespace FlaxEditor.Surface.Archetypes
public FunctionOutputNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
: base(id, context, nodeArch, groupArch)
{
_types = ((IFunctionSurface)Surface).FunctionTypes;
_typePicker = new ComboBox
if (Surface is IFunctionSurface surface)
{
Location = new Vector2(24, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
_typePicker.AddItem(Surface.GetTypeName(new ScriptType(_types[i])));
_nameField.Location = new Vector2(_typePicker.Right + 2.0f, _typePicker.Y);
_types = surface.FunctionTypes;
_typePicker = new ComboBox
{
Location = new Vector2(24, 32),
Width = 80.0f,
Parent = this,
};
for (int i = 0; i < _types.Length; i++)
_typePicker.AddItem(Surface.GetTypeName(new ScriptType(_types[i])));
_nameField.Location = new Vector2(_typePicker.Right + 2.0f, _typePicker.Y);
}
}
/// <inheritdoc />
@@ -461,8 +471,11 @@ namespace FlaxEditor.Surface.Archetypes
_inputBox = GetBox(0);
_inputBox.CurrentType = SignatureType;
_typePicker.SelectedIndex = Array.IndexOf(_types, _inputBox.CurrentType.Type);
_typePicker.SelectedIndexChanged += OnTypePickerSelectedIndexChanged;
if (_typePicker != null)
{
_typePicker.SelectedIndex = Array.IndexOf(_types, _inputBox.CurrentType.Type);
_typePicker.SelectedIndexChanged += OnTypePickerSelectedIndexChanged;
}
}
private void OnTypePickerSelectedIndexChanged(ComboBox picker)
@@ -476,7 +489,8 @@ namespace FlaxEditor.Surface.Archetypes
base.OnValuesChanged();
_inputBox.CurrentType = SignatureType;
_typePicker.SelectedIndex = Array.IndexOf(_types, _inputBox.CurrentType.Type);
if (_typePicker != null)
_typePicker.SelectedIndex = Array.IndexOf(_types, _inputBox.CurrentType.Type);
}
/// <inheritdoc />
@@ -505,8 +519,8 @@ namespace FlaxEditor.Surface.Archetypes
{
_parameters = null;
var methodInfo = ScriptMemberInfo.Null;
var surface = (VisualScriptSurface)Surface;
if (surface.Script && !surface.Script.WaitForLoaded(100))
var surface = Surface as VisualScriptSurface;
if (surface != null && surface.Script && !surface.Script.WaitForLoaded(100))
{
var scriptMeta = surface.Script.Meta;
var scriptType = TypeUtils.GetType(scriptMeta.BaseTypename);
@@ -520,7 +534,7 @@ namespace FlaxEditor.Surface.Archetypes
}
}
}
if (!_isTypesChangedEventRegistered)
if (!_isTypesChangedEventRegistered && surface != null)
{
_isTypesChangedEventRegistered = true;
Editor.Instance.CodeEditing.TypesChanged += UpdateSignature;
@@ -976,7 +990,8 @@ namespace FlaxEditor.Surface.Archetypes
if (method)
{
TooltipText = SurfaceUtils.GetVisualScriptMemberInfoDescription(method);
SetValue(4, GetSignatureData(method, parameters));
if (Surface != null)
SetValue(4, GetSignatureData(method, parameters));
}
ResizeAuto();
@@ -1656,9 +1671,9 @@ namespace FlaxEditor.Surface.Archetypes
LoadSignature();
// Send event
for (int i = 0; i < Surface.Nodes.Count; i++)
for (int i = 0; i < Context.Nodes.Count; i++)
{
if (Surface.Nodes[i] is IFunctionsDependantNode node)
if (Context.Nodes[i] is IFunctionsDependantNode node)
node.OnFunctionCreated(this);
}
}
@@ -1754,7 +1769,7 @@ namespace FlaxEditor.Surface.Archetypes
}
}
}
if (!_isTypesChangedEventRegistered)
if (!_isTypesChangedEventRegistered && Surface != null)
{
_isTypesChangedEventRegistered = true;
Editor.Instance.CodeEditing.TypesChanged += UpdateSignature;
@@ -1765,8 +1780,11 @@ namespace FlaxEditor.Surface.Archetypes
{
type = fieldInfo.ValueType;
isStatic = fieldInfo.IsStatic;
SetValue(2, type.TypeName);
SetValue(3, isStatic);
if (Surface != null)
{
SetValue(2, type.TypeName);
SetValue(3, isStatic);
}
}
else
{

View File

@@ -65,7 +65,7 @@ namespace FlaxEditor.Surface.Archetypes
{
// Try get parent material window
// Maybe too hacky :D
if (!(Surface.Owner is MaterialWindow materialWindow) || materialWindow.Item == null)
if (!(Surface?.Owner is MaterialWindow materialWindow) || materialWindow.Item == null)
return;
// Layered material

View File

@@ -312,8 +312,11 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
UpdateCombo();
UpdateLayout();
if (Surface != null)
{
UpdateCombo();
UpdateLayout();
}
}
/// <inheritdoc />
@@ -321,7 +324,10 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded();
UpdateTitle();
if (Surface != null)
{
UpdateTitle();
}
}
/// <inheritdoc />
@@ -601,8 +607,11 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
UpdateCombo();
UpdateUI();
if (Surface != null)
{
UpdateCombo();
UpdateUI();
}
}
/// <inheritdoc />
@@ -610,7 +619,10 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded();
UpdateUI();
if (Surface != null)
{
UpdateUI();
}
}
/// <inheritdoc />

View File

@@ -275,7 +275,7 @@ namespace FlaxEditor.Surface.Archetypes
base.OnSurfaceLoaded();
ParticleSurface.ArrangeModulesNodes();
ParticleSurface?.ArrangeModulesNodes();
}
/// <inheritdoc />

View File

@@ -218,6 +218,9 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnSurfaceLoaded();
if (Surface == null)
return;
// Always keep root node in the back (modules with lay on top of it)
IndexInParent = 0;
@@ -231,7 +234,7 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLocationChanged();
if (Surface != null && ParticleSurface._rootNode == this)
if (ParticleSurface != null && ParticleSurface._rootNode == this)
{
// Update modules to match root node location
ParticleSurface.ArrangeModulesNodes();
@@ -242,7 +245,8 @@ namespace FlaxEditor.Surface.Archetypes
public override void OnDestroy()
{
// Unlink
ParticleSurface._rootNode = null;
if (ParticleSurface != null)
ParticleSurface._rootNode = null;
base.OnDestroy();
}

View File

@@ -685,10 +685,10 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
var surface = (VisualScriptSurface)Context.Surface;
var type = TypeUtils.GetType(surface.Script.ScriptTypeName);
var box = (OutputBox)GetBox(0);
box.CurrentType = type ? type : new ScriptType(typeof(VisualScript));
var type = ScriptType.Null;
if (Context.Surface is VisualScriptSurface visjectSurface)
type = TypeUtils.GetType(visjectSurface.Script.ScriptTypeName);
GetBox(0).CurrentType = type ? type : new ScriptType(typeof(VisualScript));
}
}
@@ -825,7 +825,8 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
_picker.ValueTypeName = (string)Values[0];
if (Surface != null)
_picker.ValueTypeName = (string)Values[0];
UpdateOutputBox();
}
@@ -883,7 +884,8 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
_picker.ValueTypeName = (string)Values[0];
if (Surface != null)
_picker.ValueTypeName = (string)Values[0];
}
/// <inheritdoc />
@@ -933,7 +935,8 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
_picker.ValueTypeName = (string)Values[0];
if (Surface != null)
_picker.ValueTypeName = (string)Values[0];
}
/// <inheritdoc />
@@ -984,7 +987,8 @@ namespace FlaxEditor.Surface.Archetypes
{
base.OnLoaded();
_picker.ValueTypeName = (string)Values[0];
if (Surface != null)
_picker.ValueTypeName = (string)Values[0];
UpdateOutputBox();
}

View File

@@ -91,7 +91,7 @@ namespace FlaxEditor.Surface.Elements
_currentType = value;
// Check if will need to update box connections due to type change
if (Surface._isUpdatingBoxTypes == 0 && HasAnyConnection && !CanCast(prev, _currentType))
if ((Surface == null || Surface._isUpdatingBoxTypes == 0) && HasAnyConnection && !CanCast(prev, _currentType))
{
// Remove all invalid connections and update those which still can be valid
var connections = Connections.ToArray();
@@ -181,9 +181,12 @@ namespace FlaxEditor.Surface.Elements
{
_currentType = DefaultType;
Text = Archetype.Text;
var hints = parentNode.Archetype.ConnectionsHints;
Surface.Style.GetConnectionColor(_currentType, hints, out _currentTypeColor);
TooltipText = Surface.GetTypeName(CurrentType) ?? GetConnectionHintTypeName(hints);
if (Surface != null)
{
var hints = parentNode.Archetype.ConnectionsHints;
Surface.Style.GetConnectionColor(_currentType, hints, out _currentTypeColor);
TooltipText = Surface.GetTypeName(CurrentType) ?? GetConnectionHintTypeName(hints);
}
}
private static string GetConnectionHintTypeName(ConnectionsHint hint)
@@ -215,9 +218,15 @@ namespace FlaxEditor.Surface.Elements
public bool CanUseType(ScriptType type)
{
// Check direct connection
if (Surface.CanUseDirectCast(type, _currentType))
if (Surface != null)
{
return true;
if (Surface.CanUseDirectCast(type, _currentType))
return true;
}
else
{
if (VisjectSurface.CanUseDirectCastStatic(type, _currentType))
return true;
}
// Check using connection hints
@@ -464,9 +473,12 @@ namespace FlaxEditor.Surface.Elements
/// </summary>
protected virtual void OnCurrentTypeChanged()
{
var hints = ParentNode.Archetype.ConnectionsHints;
Surface.Style.GetConnectionColor(_currentType, hints, out _currentTypeColor);
TooltipText = Surface.GetTypeName(CurrentType) ?? GetConnectionHintTypeName(hints);
if (Surface != null)
{
var hints = ParentNode.Archetype.ConnectionsHints;
Surface.Style.GetConnectionColor(_currentType, hints, out _currentTypeColor);
TooltipText = Surface.GetTypeName(CurrentType) ?? GetConnectionHintTypeName(hints);
}
CurrentTypeChanged?.Invoke(this);
}

View File

@@ -18,6 +18,8 @@ namespace FlaxEditor.Surface.Elements
{
_isAutoSelect = true;
if (Surface == null)
return;
UpdateComboBox();
// Select saved value

View File

@@ -45,6 +45,8 @@ namespace FlaxEditor.Surface.Elements
{
_isAutoSelect = true;
if (Surface == null)
return;
UpdateComboBox();
// Select saved value

View File

@@ -158,6 +158,8 @@ namespace FlaxEditor.Surface
/// <param name="height">The height.</param>
public void Resize(float width, float height)
{
if (Surface == null)
return;
Size = CalculateNodeSize(width, height);
// Update boxes on width change
@@ -178,6 +180,8 @@ namespace FlaxEditor.Surface
/// </summary>
public void ResizeAuto()
{
if (Surface == null)
return;
var width = 0.0f;
var height = 0.0f;
var leftHeight = 0.0f;
@@ -462,10 +466,21 @@ namespace FlaxEditor.Surface
}
// Check if that type if part of default type
if (Surface.CanUseDirectCast(type, b.Connections[0].DefaultType))
if (Surface != null)
{
type = b.Connections[0].CurrentType;
break;
if (Surface.CanUseDirectCast(type, b.Connections[0].DefaultType))
{
type = b.Connections[0].CurrentType;
break;
}
}
else
{
if (VisjectSurface.CanUseDirectCastStatic(type, b.Connections[0].DefaultType))
{
type = b.Connections[0].CurrentType;
break;
}
}
}
}
@@ -891,7 +906,7 @@ namespace FlaxEditor.Surface
/// <param name="graphEdited">True if graph has been edited (nodes structure or parameter value).</param>
public virtual void SetValue(int index, object value, bool graphEdited = true)
{
if (_isDuringValuesEditing || !Surface.CanEdit)
if (_isDuringValuesEditing || (Surface != null && !Surface.CanEdit))
return;
if (FlaxEngine.Json.JsonSerializer.ValueEquals(value, Values[index]))
return;
@@ -900,13 +915,13 @@ namespace FlaxEditor.Surface
_isDuringValuesEditing = true;
var before = Surface.Undo != null ? (object[])Values.Clone() : null;
var before = Surface?.Undo != null ? (object[])Values.Clone() : null;
Values[index] = value;
OnValuesChanged();
Surface.MarkAsEdited(graphEdited);
Surface?.MarkAsEdited(graphEdited);
Surface.Undo?.AddAction(new EditNodeValuesAction(this, before, graphEdited));
Surface?.Undo?.AddAction(new EditNodeValuesAction(this, before, graphEdited));
_isDuringValuesEditing = false;
}
@@ -948,7 +963,7 @@ namespace FlaxEditor.Surface
public virtual void OnValuesChanged()
{
ValuesChanged?.Invoke();
Surface.OnNodeValuesEdited(this);
Surface?.OnNodeValuesEdited(this);
}
/// <summary>

View File

@@ -47,13 +47,7 @@ namespace FlaxEditor.Surface
public partial class VisjectSurface
{
/// <summary>
/// Checks if can use direct conversion from one type to another.
/// </summary>
/// <param name="from">Source type.</param>
/// <param name="to">Target type.</param>
/// <returns>True if can use direct conversion, otherwise false.</returns>
public bool CanUseDirectCast(ScriptType from, ScriptType to)
internal static bool CanUseDirectCastStatic(ScriptType from, ScriptType to, bool supportsImplicitCastFromObjectToBoolean = true)
{
if (from == ScriptType.Null || to == ScriptType.Null)
return false;
@@ -76,7 +70,7 @@ namespace FlaxEditor.Surface
// Implicit casting is supported for object reference to test whenever it is valid
var toType = to.Type;
if (_supportsImplicitCastFromObjectToBoolean && toType == typeof(bool) && ScriptType.FlaxObject.IsAssignableFrom(from))
if (supportsImplicitCastFromObjectToBoolean && toType == typeof(bool) && ScriptType.FlaxObject.IsAssignableFrom(from))
{
return true;
}
@@ -124,6 +118,17 @@ namespace FlaxEditor.Surface
return result;
}
/// <summary>
/// Checks if can use direct conversion from one type to another.
/// </summary>
/// <param name="from">Source type.</param>
/// <param name="to">Target type.</param>
/// <returns>True if can use direct conversion, otherwise false.</returns>
public bool CanUseDirectCast(ScriptType from, ScriptType to)
{
return CanUseDirectCastStatic(from, to, _supportsImplicitCastFromObjectToBoolean);
}
/// <summary>
/// Begins connecting surface objects action.
/// </summary>

View File

@@ -77,7 +77,8 @@ namespace FlaxEditor.Surface
/// <returns>True if failed, otherwise false.</returns>
public bool Load()
{
Surface._isUpdatingBoxTypes++;
if (_surface != null)
_surface._isUpdatingBoxTypes++;
try
{
@@ -178,7 +179,8 @@ namespace FlaxEditor.Surface
}
finally
{
Surface._isUpdatingBoxTypes--;
if (_surface != null)
_surface._isUpdatingBoxTypes--;
}
return false;
@@ -445,6 +447,9 @@ namespace FlaxEditor.Surface
{
// IMPORTANT! This must match C++ Graph format
var nodeArchetypes = _surface?.NodeArchetypes ?? NodeFactory.DefaultGroups;
var customNodes = _surface?.GetCustomNodes();
// Magic Code
int tmp = stream.ReadInt32();
if (tmp != 1963542358)
@@ -489,7 +494,7 @@ namespace FlaxEditor.Surface
if (groupId == Archetypes.Custom.GroupID)
node = new DummyCustomNode(id, this);
else
node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
node = NodeFactory.CreateNode(nodeArchetypes, id, this, groupId, typeId);
if (node == null)
node = new MissingNode(id, this, groupId, typeId);
Nodes.Add(node);
@@ -550,7 +555,6 @@ namespace FlaxEditor.Surface
string typeName = typeNameValue as string ?? string.Empty;
// Find custom node archetype that matches this node type (it must be unique)
var customNodes = _surface.GetCustomNodes();
if (customNodes?.Archetypes != null && typeName.Length != 0)
{
NodeArchetype arch = null;
@@ -674,7 +678,7 @@ namespace FlaxEditor.Surface
if (groupId == Archetypes.Custom.GroupID)
node = new DummyCustomNode(id, this);
else
node = NodeFactory.CreateNode(_surface.NodeArchetypes, id, this, groupId, typeId);
node = NodeFactory.CreateNode(nodeArchetypes, id, this, groupId, typeId);
if (node == null)
node = new MissingNode(id, this, groupId, typeId);
Nodes.Add(node);
@@ -722,7 +726,6 @@ namespace FlaxEditor.Surface
string typeName = typeNameValue as string ?? string.Empty;
// Find custom node archetype that matches this node type (it must be unique)
var customNodes = _surface.GetCustomNodes();
if (customNodes?.Archetypes != null && typeName.Length != 0)
{
NodeArchetype arch = null;
@@ -856,7 +859,7 @@ namespace FlaxEditor.Surface
{
control.OnSpawned();
ControlSpawned?.Invoke(control);
if (control is SurfaceNode node)
if (Surface != null && control is SurfaceNode node)
Surface.OnNodeSpawned(node);
}

View File

@@ -335,7 +335,8 @@ namespace FlaxEditor.Surface
/// <returns>Created node.</returns>
public SurfaceNode SpawnNode(ushort groupID, ushort typeID, Vector2 location, object[] customValues = null, Action<SurfaceNode> beforeSpawned = null)
{
if (NodeFactory.GetArchetype(_surface.NodeArchetypes, groupID, typeID, out var groupArchetype, out var nodeArchetype))
var nodeArchetypes = _surface?.NodeArchetypes ?? NodeFactory.DefaultGroups;
if (NodeFactory.GetArchetype(nodeArchetypes, groupID, typeID, out var groupArchetype, out var nodeArchetype))
{
return SpawnNode(groupArchetype, nodeArchetype, location, customValues, beforeSpawned);
}
@@ -360,7 +361,7 @@ namespace FlaxEditor.Surface
var flags = nodeArchetype.Flags;
nodeArchetype.Flags &= ~NodeFlags.NoSpawnViaGUI;
nodeArchetype.Flags &= ~NodeFlags.NoSpawnViaPaste;
if (!_surface.CanUseNodeType(nodeArchetype))
if (_surface != null && !_surface.CanUseNodeType(nodeArchetype))
{
nodeArchetype.Flags = flags;
Editor.LogWarning("Cannot spawn given node type. Title: " + nodeArchetype.Title);
@@ -394,7 +395,8 @@ namespace FlaxEditor.Surface
OnControlSpawned(node);
// Undo action
Surface.Undo?.AddAction(new AddRemoveNodeAction(node, true));
if (Surface != null && Surface.Undo != null)
Surface.Undo.AddAction(new AddRemoveNodeAction(node, true));
MarkAsModified();