123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
-
- namespace Unity.VisualScripting
- {
- public sealed class UnitPreservation : IPoolable
- {
- private struct UnitPortPreservation
- {
- public readonly IUnit unit;
-
- public readonly string key;
-
- public UnitPortPreservation(IUnitPort port)
- {
- unit = port.unit;
- key = port.key;
- }
-
- public UnitPortPreservation(IUnit unit, string key)
- {
- this.unit = unit;
- this.key = key;
- }
-
- public IUnitPort GetOrCreateInput(out InvalidInput newInvalidInput)
- {
- var key = this.key;
-
- if (!unit.inputs.Any(p => p.key == key))
- {
- newInvalidInput = new InvalidInput(key);
- unit.invalidInputs.Add(newInvalidInput);
- }
- else
- {
- newInvalidInput = null;
- }
-
- return unit.inputs.Single(p => p.key == key);
- }
-
- public IUnitPort GetOrCreateOutput(out InvalidOutput newInvalidOutput)
- {
- var key = this.key;
-
- if (!unit.outputs.Any(p => p.key == key))
- {
- newInvalidOutput = new InvalidOutput(key);
- unit.invalidOutputs.Add(newInvalidOutput);
- }
- else
- {
- newInvalidOutput = null;
- }
-
- return unit.outputs.Single(p => p.key == key);
- }
- }
-
- private readonly Dictionary<string, object> defaultValues = new Dictionary<string, object>();
-
- private readonly Dictionary<string, List<UnitPortPreservation>> inputConnections = new Dictionary<string, List<UnitPortPreservation>>();
-
- private readonly Dictionary<string, List<UnitPortPreservation>> outputConnections = new Dictionary<string, List<UnitPortPreservation>>();
-
- private bool disposed;
-
- void IPoolable.New()
- {
- disposed = false;
- }
-
- void IPoolable.Free()
- {
- disposed = true;
-
- foreach (var inputConnection in inputConnections)
- {
- ListPool<UnitPortPreservation>.Free(inputConnection.Value);
- }
-
- foreach (var outputConnection in outputConnections)
- {
- ListPool<UnitPortPreservation>.Free(outputConnection.Value);
- }
-
- defaultValues.Clear();
- inputConnections.Clear();
- outputConnections.Clear();
- }
-
- private UnitPreservation() { }
-
- public static UnitPreservation Preserve(IUnit unit)
- {
- var preservation = GenericPool<UnitPreservation>.New(() => new UnitPreservation());
-
- foreach (var defaultValue in unit.defaultValues)
- {
- preservation.defaultValues.Add(defaultValue.Key, defaultValue.Value);
- }
-
- foreach (var input in unit.inputs)
- {
- if (input.hasAnyConnection)
- {
- preservation.inputConnections.Add(input.key, ListPool<UnitPortPreservation>.New());
-
- foreach (var connectedPort in input.connectedPorts)
- {
- preservation.inputConnections[input.key].Add(new UnitPortPreservation(connectedPort));
- }
- }
- }
-
- foreach (var output in unit.outputs)
- {
- if (output.hasAnyConnection)
- {
- preservation.outputConnections.Add(output.key, ListPool<UnitPortPreservation>.New());
-
- foreach (var connectedPort in output.connectedPorts)
- {
- preservation.outputConnections[output.key].Add(new UnitPortPreservation(connectedPort));
- }
- }
- }
-
- return preservation;
- }
-
- public void RestoreTo(IUnit unit)
- {
- if (disposed)
- {
- throw new ObjectDisposedException(ToString());
- }
-
- // Restore inline values if possible
-
- foreach (var previousDefaultValue in defaultValues)
- {
- if (unit.defaultValues.ContainsKey(previousDefaultValue.Key) &&
- unit.valueInputs.Contains(previousDefaultValue.Key) &&
- unit.valueInputs[previousDefaultValue.Key].type.IsAssignableFrom(previousDefaultValue.Value))
- {
- unit.defaultValues[previousDefaultValue.Key] = previousDefaultValue.Value;
- }
- }
-
- // Restore connections if possible
-
- foreach (var previousInputConnections in inputConnections)
- {
- var previousInputPort = new UnitPortPreservation(unit, previousInputConnections.Key);
- var previousOutputPorts = previousInputConnections.Value;
-
- foreach (var previousOutputPort in previousOutputPorts)
- {
- RestoreConnection(previousOutputPort, previousInputPort);
- }
- }
-
- foreach (var previousOutputConnections in outputConnections)
- {
- var previousOutputPort = new UnitPortPreservation(unit, previousOutputConnections.Key);
- var previousInputPorts = previousOutputConnections.Value;
-
- foreach (var previousInputPort in previousInputPorts)
- {
- RestoreConnection(previousOutputPort, previousInputPort);
- }
- }
-
- GenericPool<UnitPreservation>.Free(this);
- }
-
- private void RestoreConnection(UnitPortPreservation sourcePreservation, UnitPortPreservation destinationPreservation)
- {
- InvalidOutput newInvalidSource;
- InvalidInput newInvalidDestination;
-
- var source = sourcePreservation.GetOrCreateOutput(out newInvalidSource);
- var destination = destinationPreservation.GetOrCreateInput(out newInvalidDestination);
-
- if (source.CanValidlyConnectTo(destination))
- {
- source.ValidlyConnectTo(destination);
- }
- else if (source.CanInvalidlyConnectTo(destination))
- {
- source.InvalidlyConnectTo(destination);
- }
- else
- {
- // In this case, we created invalid ports to attempt a connection,
- // but even that failed (due to, for example, a cross-graph restoration).
- // Therefore, we need to delete the invalid ports we created.
-
- if (newInvalidSource != null)
- {
- sourcePreservation.unit.invalidOutputs.Remove(newInvalidSource);
- }
-
- if (newInvalidDestination != null)
- {
- destinationPreservation.unit.invalidInputs.Remove(newInvalidDestination);
- }
- }
- }
- }
- }
|