123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- using System;
- using System.ComponentModel;
-
- namespace Unity.VisualScripting
- {
- [TypeIcon(typeof(FlowGraph))]
- [UnitCategory("Nesting")]
- [UnitTitle("Subgraph")]
- [RenamedFrom("Bolt.SuperUnit")]
- [RenamedFrom("Unity.VisualScripting.SuperUnit")]
- [DisplayName("Subgraph Node")]
- public sealed class SubgraphUnit : NesterUnit<FlowGraph, ScriptGraphAsset>, IGraphEventListener, IGraphElementWithData
- {
- public sealed class Data : IGraphElementData
- {
- public bool isListening;
- }
-
- public IGraphElementData CreateData()
- {
- return new Data();
- }
-
- public SubgraphUnit() : base() { }
-
- public SubgraphUnit(ScriptGraphAsset macro) : base(macro) { }
-
- public static SubgraphUnit WithInputOutput()
- {
- var superUnit = new SubgraphUnit();
- superUnit.nest.source = GraphSource.Embed;
- superUnit.nest.embed = FlowGraph.WithInputOutput();
- return superUnit;
- }
-
- public static SubgraphUnit WithStartUpdate()
- {
- var superUnit = new SubgraphUnit();
- superUnit.nest.source = GraphSource.Embed;
- superUnit.nest.embed = FlowGraph.WithStartUpdate();
- return superUnit;
- }
-
- public override FlowGraph DefaultGraph()
- {
- return FlowGraph.WithInputOutput();
- }
-
- protected override void Definition()
- {
- isControlRoot = true; // TODO: Infer relations instead
-
- // Using portDefinitions and type checks instead of specific definition collections
- // to avoid duplicates. Iterating only once for speed.
-
- foreach (var definition in nest.graph.validPortDefinitions)
- {
- if (definition is ControlInputDefinition)
- {
- var controlInputDefinition = (ControlInputDefinition)definition;
- var key = controlInputDefinition.key;
-
- ControlInput(key, (flow) =>
- {
- foreach (var unit in nest.graph.units)
- {
- if (unit is GraphInput)
- {
- var inputUnit = (GraphInput)unit;
-
- flow.stack.EnterParentElement(this);
-
- return inputUnit.controlOutputs[key];
- }
- }
-
- return null;
- });
- }
- else if (definition is ValueInputDefinition)
- {
- var valueInputDefinition = (ValueInputDefinition)definition;
- var key = valueInputDefinition.key;
- var type = valueInputDefinition.type;
- var hasDefaultValue = valueInputDefinition.hasDefaultValue;
- var defaultValue = valueInputDefinition.defaultValue;
-
- var port = ValueInput(type, key);
-
- if (hasDefaultValue)
- {
- port.SetDefaultValue(defaultValue);
- }
- }
- else if (definition is ControlOutputDefinition)
- {
- var controlOutputDefinition = (ControlOutputDefinition)definition;
- var key = controlOutputDefinition.key;
-
- ControlOutput(key);
- }
- else if (definition is ValueOutputDefinition)
- {
- var valueOutputDefinition = (ValueOutputDefinition)definition;
- var key = valueOutputDefinition.key;
- var type = valueOutputDefinition.type;
-
- ValueOutput(type, key, (flow) =>
- {
- flow.stack.EnterParentElement(this);
-
- // Manual looping to avoid LINQ allocation
- // Also removing check for multiple output nodes for speed
- // (The first output node will be used without any error)
-
- foreach (var unit in nest.graph.units)
- {
- if (unit is GraphOutput)
- {
- var outputUnit = (GraphOutput)unit;
-
- var value = flow.GetValue(outputUnit.valueInputs[key]);
-
- flow.stack.ExitParentElement();
-
- return value;
- }
- }
-
- flow.stack.ExitParentElement();
-
- throw new InvalidOperationException("Missing output node when to get value.");
- });
- }
- }
- }
-
- public void StartListening(GraphStack stack)
- {
- if (stack.TryEnterParentElement(this))
- {
- nest.graph.StartListening(stack);
- stack.ExitParentElement();
- }
-
- stack.GetElementData<Data>(this).isListening = true;
- }
-
- public void StopListening(GraphStack stack)
- {
- stack.GetElementData<Data>(this).isListening = false;
-
- if (stack.TryEnterParentElement(this))
- {
- nest.graph.StopListening(stack);
- stack.ExitParentElement();
- }
- }
-
- public bool IsListening(GraphPointer pointer)
- {
- return pointer.GetElementData<Data>(this).isListening;
- }
-
- #region Editing
-
- public override void AfterAdd()
- {
- base.AfterAdd();
-
- nest.beforeGraphChange += StopWatchingPortDefinitions;
- nest.afterGraphChange += StartWatchingPortDefinitions;
-
- StartWatchingPortDefinitions();
- }
-
- public override void BeforeRemove()
- {
- base.BeforeRemove();
-
- StopWatchingPortDefinitions();
-
- nest.beforeGraphChange -= StopWatchingPortDefinitions;
- nest.afterGraphChange -= StartWatchingPortDefinitions;
- }
-
- private void StopWatchingPortDefinitions()
- {
- if (nest.graph != null)
- {
- nest.graph.onPortDefinitionsChanged -= Define;
- }
- }
-
- private void StartWatchingPortDefinitions()
- {
- if (nest.graph != null)
- {
- nest.graph.onPortDefinitionsChanged += Define;
- }
- }
-
- #endregion
- }
- }
|