FlowGraph.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using UnityEngine;
  6. namespace Unity.VisualScripting
  7. {
  8. [SerializationVersion("A")]
  9. [DisplayName("Script Graph")]
  10. public sealed class FlowGraph : Graph, IGraphWithVariables, IGraphEventListener
  11. {
  12. public FlowGraph()
  13. {
  14. units = new GraphElementCollection<IUnit>(this);
  15. controlConnections = new GraphConnectionCollection<ControlConnection, ControlOutput, ControlInput>(this);
  16. valueConnections = new GraphConnectionCollection<ValueConnection, ValueOutput, ValueInput>(this);
  17. invalidConnections = new GraphConnectionCollection<InvalidConnection, IUnitOutputPort, IUnitInputPort>(this);
  18. groups = new GraphElementCollection<GraphGroup>(this);
  19. elements.Include(units);
  20. elements.Include(controlConnections);
  21. elements.Include(valueConnections);
  22. elements.Include(invalidConnections);
  23. elements.Include(groups);
  24. controlInputDefinitions = new UnitPortDefinitionCollection<ControlInputDefinition>();
  25. controlOutputDefinitions = new UnitPortDefinitionCollection<ControlOutputDefinition>();
  26. valueInputDefinitions = new UnitPortDefinitionCollection<ValueInputDefinition>();
  27. valueOutputDefinitions = new UnitPortDefinitionCollection<ValueOutputDefinition>();
  28. variables = new VariableDeclarations();
  29. }
  30. public override IGraphData CreateData()
  31. {
  32. return new FlowGraphData(this);
  33. }
  34. public void StartListening(GraphStack stack)
  35. {
  36. stack.GetGraphData<FlowGraphData>().isListening = true;
  37. foreach (var unit in units)
  38. {
  39. (unit as IGraphEventListener)?.StartListening(stack);
  40. }
  41. }
  42. public void StopListening(GraphStack stack)
  43. {
  44. foreach (var unit in units)
  45. {
  46. (unit as IGraphEventListener)?.StopListening(stack);
  47. }
  48. stack.GetGraphData<FlowGraphData>().isListening = false;
  49. }
  50. public bool IsListening(GraphPointer pointer)
  51. {
  52. return pointer.GetGraphData<FlowGraphData>().isListening;
  53. }
  54. #region Variables
  55. [Serialize]
  56. public VariableDeclarations variables { get; private set; }
  57. public IEnumerable<string> GetDynamicVariableNames(VariableKind kind, GraphReference reference)
  58. {
  59. return units.OfType<IUnifiedVariableUnit>()
  60. .Where(v => v.kind == kind && Flow.CanPredict(v.name, reference))
  61. .Select(v => Flow.Predict<string>(v.name, reference))
  62. .Where(name => !StringUtility.IsNullOrWhiteSpace(name))
  63. .Distinct()
  64. .OrderBy(name => name);
  65. }
  66. #endregion
  67. #region Elements
  68. [DoNotSerialize]
  69. public GraphElementCollection<IUnit> units { get; private set; }
  70. [DoNotSerialize]
  71. public GraphConnectionCollection<ControlConnection, ControlOutput, ControlInput> controlConnections { get; private set; }
  72. [DoNotSerialize]
  73. public GraphConnectionCollection<ValueConnection, ValueOutput, ValueInput> valueConnections { get; private set; }
  74. [DoNotSerialize]
  75. public GraphConnectionCollection<InvalidConnection, IUnitOutputPort, IUnitInputPort> invalidConnections { get; private set; }
  76. [DoNotSerialize]
  77. public GraphElementCollection<GraphGroup> groups { get; private set; }
  78. #endregion
  79. #region Definition
  80. private const string DefinitionRemoveWarningTitle = "Remove Port Definition";
  81. private const string DefinitionRemoveWarningMessage = "Removing this definition will break any existing connection to this port. Are you sure you want to continue?";
  82. [Serialize]
  83. [InspectorLabel("Trigger Inputs")]
  84. [InspectorWide(true)]
  85. [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
  86. public UnitPortDefinitionCollection<ControlInputDefinition> controlInputDefinitions { get; private set; }
  87. [Serialize]
  88. [InspectorLabel("Trigger Outputs")]
  89. [InspectorWide(true)]
  90. [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
  91. public UnitPortDefinitionCollection<ControlOutputDefinition> controlOutputDefinitions { get; private set; }
  92. [Serialize]
  93. [InspectorLabel("Data Inputs")]
  94. [InspectorWide(true)]
  95. [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
  96. public UnitPortDefinitionCollection<ValueInputDefinition> valueInputDefinitions { get; private set; }
  97. [Serialize]
  98. [InspectorLabel("Data Outputs")]
  99. [InspectorWide(true)]
  100. [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
  101. public UnitPortDefinitionCollection<ValueOutputDefinition> valueOutputDefinitions { get; private set; }
  102. public IEnumerable<IUnitPortDefinition> validPortDefinitions =>
  103. LinqUtility.Concat<IUnitPortDefinition>(controlInputDefinitions,
  104. controlOutputDefinitions,
  105. valueInputDefinitions,
  106. valueOutputDefinitions)
  107. .Where(upd => upd.isValid)
  108. .DistinctBy(upd => upd.key);
  109. public event Action onPortDefinitionsChanged;
  110. public void PortDefinitionsChanged()
  111. {
  112. onPortDefinitionsChanged?.Invoke();
  113. }
  114. #endregion
  115. public static FlowGraph WithInputOutput()
  116. {
  117. return new FlowGraph()
  118. {
  119. units =
  120. {
  121. new GraphInput() { position = new Vector2(-250, -30) },
  122. new GraphOutput() { position = new Vector2(105, -30) }
  123. }
  124. };
  125. }
  126. public static FlowGraph WithStartUpdate()
  127. {
  128. return new FlowGraph()
  129. {
  130. units =
  131. {
  132. new Start() { position = new Vector2(-204, -144) },
  133. new Update() { position = new Vector2(-204, 60) }
  134. }
  135. };
  136. }
  137. }
  138. }