Code/UI/Spatial/Node.Recreation.cs
namespace Nodebox.UI.Spatial;
public partial class Node {
public Action OnRecreated { get; set; }
public void Recreate() {
if (RecreationSuppressed > 0) { return; }
if (!Enabled) { return; }
TypeLastHashCode = Type?.GetHashCode();
PolymorphSuppressed++;
IReadOnlyList<IReadOnlySet<Nodebox.Wire>> oldInputWires = [];
IReadOnlyList<IReadOnlySet<Nodebox.Wire>> oldOutputWires = [];
if (_inner.IsValid()) {
oldInputWires = _inner.OutputWires;
oldOutputWires = _inner.InputWires;
_inner?.Destroy();
NodePanelRoot.Node = null;
_inner = null;
foreach (var wireSet in oldInputWires) {
foreach (var wire in wireSet) {
using var _ = new SuppressPolymorph(wire.Source.Spatial);
var spatialWire = wire.Spatial;
wire.Spatial.Disconnect();
}
}
foreach (var wireSet in oldOutputWires) {
foreach (var wire in wireSet) {
using var _ = new SuppressPolymorph(wire.Destination.Spatial);
var spatialWire = wire.Spatial;
wire.Spatial.Disconnect();
}
}
}
var type = _serializableNode.Type;
if (type == null) {
return;
}
if (!type.IsAssignableTo(typeof(Nodebox.Node))) {
return;
}
if (type.IsGenericType && !TypeLibrary.IsConstructedGenericType(type)) {
return;
}
_inner = _serializableNode.Create();
if (!_inner.IsValid()) {
Log.Warning($"Couldn't create node {_serializableNode}..?");
return;
}
_inner.Spatial = this;
NodePanelRoot.Node = _inner;
_inner.PinsChanged += OnInnerPinsChanged;
_inner.InputsChanged += OnInnerInputsChanged;
_inner.OnPolymorph += OnInnerPolymorph;
RegisterInner();
// foreach (var wireSet in oldInputWires) {
// foreach (var wire in wireSet) {
// wire.Spatial.Connect();
// }
// }
// foreach (var wireSet in oldOutputWires) {
// foreach (var wire in wireSet) {
// wire.Spatial.Connect();
// }
// }
OnRecreated?.Invoke();
PolymorphSuppressed--;
}
private void RecreateSerializableNode() {
_serializableNode = new Nodebox.Node.Serializable() {
SerializableType = Type,
Inputs = Inputs?.Select(x => new SerializableObject(x)).ToList() ?? [],
Properties = Properties?.Select(x => (x.Key, new SerializableObject(x.Value))).ToDictionary() ?? []
};
if (OverridePins) {
_serializableNode.Pins = (InputPins?.ToList() ?? [], OutputPins?.ToList() ?? []);
}
Recreate();
}
private void OnInnerPinsChanged() {
using var _ = new SuppressRecreation(this);
OverridePins = true;
InputPins.Clear();
foreach (var pin in _inner.InputPins) {
InputPins.Add(pin);
}
OutputPins.Clear();
foreach (var pin in _inner.OutputPins) {
OutputPins.Add(pin);
}
}
private void OnInnerInputsChanged() {
using var _ = new SuppressRecreation(this);
Inputs.Clear();
foreach (var value in _inner.Inputs) {
Inputs.Add(value);
}
}
private Type QueuedPolymorph { get; set; }
private void OnInnerPolymorph(Type newType) {
if (PolymorphSuppressed > 0) { return; }
Assert.IsNull(QueuedPolymorph);
QueuedPolymorph = newType;
_ = Task.FrameEnd().ContinueWith((_) => ApplyPolymorph());
}
private void ApplyPolymorph() {
Type = QueuedPolymorph;
QueuedPolymorph = null;
}
private uint RecreationSuppressed { get; set; } = 0;
public sealed class SuppressRecreation : IDisposable {
private Node Node { get; set; }
public SuppressRecreation(Node node) {
Node = node;
Node.RecreationSuppressed += 1;
}
public void Dispose() {
Node.RecreationSuppressed -= 1;
}
}
private uint PolymorphSuppressed { get; set; } = 0;
public sealed class SuppressPolymorph : IDisposable {
private Node Node { get; set; }
public SuppressPolymorph(Node node) {
Node = node;
Node.PolymorphSuppressed += 1;
}
public void Dispose() {
Node.PolymorphSuppressed -= 1;
}
}
}