File size: 6,567 Bytes
18a519f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using UnityEngine;

namespace Unity.VisualScripting
{
    [SerializationVersion("A")]
    [DisplayName("Script Graph")]
    public sealed class FlowGraph : Graph, IGraphWithVariables, IGraphEventListener
    {
        public FlowGraph()
        {
            units = new GraphElementCollection<IUnit>(this);
            controlConnections = new GraphConnectionCollection<ControlConnection, ControlOutput, ControlInput>(this);
            valueConnections = new GraphConnectionCollection<ValueConnection, ValueOutput, ValueInput>(this);
            invalidConnections = new GraphConnectionCollection<InvalidConnection, IUnitOutputPort, IUnitInputPort>(this);
            groups = new GraphElementCollection<GraphGroup>(this);
            sticky = new GraphElementCollection<StickyNote>(this);

            elements.Include(units);
            elements.Include(controlConnections);
            elements.Include(valueConnections);
            elements.Include(invalidConnections);
            elements.Include(groups);
            elements.Include(sticky);

            controlInputDefinitions = new UnitPortDefinitionCollection<ControlInputDefinition>();
            controlOutputDefinitions = new UnitPortDefinitionCollection<ControlOutputDefinition>();
            valueInputDefinitions = new UnitPortDefinitionCollection<ValueInputDefinition>();
            valueOutputDefinitions = new UnitPortDefinitionCollection<ValueOutputDefinition>();

            variables = new VariableDeclarations();
        }

        public override IGraphData CreateData()
        {
            return new FlowGraphData(this);
        }

        public void StartListening(GraphStack stack)
        {
            stack.GetGraphData<FlowGraphData>().isListening = true;

            foreach (var unit in units)
            {
                (unit as IGraphEventListener)?.StartListening(stack);
            }
        }

        public void StopListening(GraphStack stack)
        {
            foreach (var unit in units)
            {
                (unit as IGraphEventListener)?.StopListening(stack);
            }

            stack.GetGraphData<FlowGraphData>().isListening = false;
        }

        public bool IsListening(GraphPointer pointer)
        {
            return pointer.GetGraphData<FlowGraphData>().isListening;
        }

        #region Variables

        [Serialize]
        public VariableDeclarations variables { get; private set; }

        public IEnumerable<string> GetDynamicVariableNames(VariableKind kind, GraphReference reference)
        {
            return units.OfType<IUnifiedVariableUnit>()
                .Where(v => v.kind == kind && Flow.CanPredict(v.name, reference))
                .Select(v => Flow.Predict<string>(v.name, reference))
                .Where(name => !StringUtility.IsNullOrWhiteSpace(name))
                .Distinct()
                .OrderBy(name => name);
        }

        #endregion


        #region Elements

        [DoNotSerialize]
        public GraphElementCollection<IUnit> units { get; private set; }

        [DoNotSerialize]
        public GraphConnectionCollection<ControlConnection, ControlOutput, ControlInput> controlConnections { get; private set; }

        [DoNotSerialize]
        public GraphConnectionCollection<ValueConnection, ValueOutput, ValueInput> valueConnections { get; private set; }

        [DoNotSerialize]
        public GraphConnectionCollection<InvalidConnection, IUnitOutputPort, IUnitInputPort> invalidConnections { get; private set; }

        [DoNotSerialize]
        public GraphElementCollection<GraphGroup> groups { get; private set; }

        [DoNotSerialize]
        public GraphElementCollection<StickyNote> sticky { get; private set; }
        #endregion


        #region Definition

        private const string DefinitionRemoveWarningTitle = "Remove Port Definition";

        private const string DefinitionRemoveWarningMessage = "Removing this definition will break any existing connection to this port. Are you sure you want to continue?";

        [Serialize]
        [InspectorLabel("Trigger Inputs")]
        [InspectorWide(true)]
        [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
        public UnitPortDefinitionCollection<ControlInputDefinition> controlInputDefinitions { get; private set; }

        [Serialize]
        [InspectorLabel("Trigger Outputs")]
        [InspectorWide(true)]
        [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
        public UnitPortDefinitionCollection<ControlOutputDefinition> controlOutputDefinitions { get; private set; }

        [Serialize]
        [InspectorLabel("Data Inputs")]
        [InspectorWide(true)]
        [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
        public UnitPortDefinitionCollection<ValueInputDefinition> valueInputDefinitions { get; private set; }

        [Serialize]
        [InspectorLabel("Data Outputs")]
        [InspectorWide(true)]
        [WarnBeforeRemoving(DefinitionRemoveWarningTitle, DefinitionRemoveWarningMessage)]
        public UnitPortDefinitionCollection<ValueOutputDefinition> valueOutputDefinitions { get; private set; }

        public IEnumerable<IUnitPortDefinition> validPortDefinitions =>
            LinqUtility.Concat<IUnitPortDefinition>(controlInputDefinitions,
                controlOutputDefinitions,
                valueInputDefinitions,
                valueOutputDefinitions)
                .Where(upd => upd.isValid)
                .DistinctBy(upd => upd.key);

        public event Action onPortDefinitionsChanged;

        public void PortDefinitionsChanged()
        {
            onPortDefinitionsChanged?.Invoke();
        }

        #endregion

        public static FlowGraph WithInputOutput()
        {
            return new FlowGraph()
            {
                units =
                {
                    new GraphInput() { position = new Vector2(-250, -30) },
                    new GraphOutput() { position = new Vector2(105, -30) }
                }
            };
        }

        public static FlowGraph WithStartUpdate()
        {
            return new FlowGraph()
            {
                units =
                {
                    new Start() { position = new Vector2(-204, -144) },
                    new Update() { position = new Vector2(-204, 60) }
                }
            };
        }
    }
}