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