14
14
// You should have received a copy of the GNU General Public License
15
15
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
17
+ using System ;
17
18
using System . Collections . Generic ;
18
19
using System . Collections . ObjectModel ;
20
+ using System . Linq ;
19
21
using Unity . VisualScripting ;
20
22
using UnityEngine ;
23
+ using VisualPinball . Engine . Game . Engines ;
24
+ using Color = VisualPinball . Engine . Math . Color ;
21
25
22
26
namespace VisualPinball . Unity . VisualScripting
23
27
{
28
+ public struct LightComponentMapping
29
+ {
30
+ public LightComponent lightComponent ;
31
+ public string id ;
32
+
33
+ public bool IsValid ( ) => ! lightComponent . IsUnityNull ( ) ;
34
+ }
35
+
24
36
[ UnitTitle ( "Lamp Sequence" ) ]
25
37
[ UnitSurtitle ( "Gamelogic Engine" ) ]
26
38
[ UnitCategory ( "Visual Pinball" ) ]
27
39
public class LampSequenceUnit : GleUnit , IMultiInputUnit
28
40
{
41
+ [ Serialize , Inspectable , UnitHeaderInspectable ( "Value" ) ]
42
+ public LampDataType ValueDataType { get ; set ; }
43
+
44
+ [ Serialize , Inspectable , UnitHeaderInspectable ( "Non Step Value" ) ]
45
+ public LampDataType NonStepValueDataType { get ; set ; }
46
+
47
+ [ DoNotSerialize ]
48
+ [ Inspectable , UnitHeaderInspectable ( "Lamp IDs" ) ]
49
+ public int inputCount
50
+ {
51
+ get => _inputCount ;
52
+ set => _inputCount = Mathf . Clamp ( value , 1 , 10 ) ;
53
+ }
54
+
29
55
[ DoNotSerialize ]
30
56
[ PortLabelHidden ]
31
57
public ControlInput InputTrigger ;
@@ -38,55 +64,66 @@ public class LampSequenceUnit : GleUnit, IMultiInputUnit
38
64
private int _inputCount = 1 ;
39
65
40
66
[ DoNotSerialize ]
41
- [ Inspectable , UnitHeaderInspectable ( "Lamp IDs" ) ]
42
- public int inputCount
43
- {
44
- get => _inputCount ;
45
- set => _inputCount = Mathf . Clamp ( value , 1 , 10 ) ;
46
- }
67
+ public ReadOnlyCollection < ValueInput > multiInputs { get ; private set ; }
47
68
48
69
[ DoNotSerialize ]
49
- public ReadOnlyCollection < ValueInput > multiInputs { get ; private set ; }
70
+ [ PortLabel ( "Step" ) ]
71
+ public ValueInput Step ;
50
72
51
73
[ DoNotSerialize ]
52
- [ PortLabel ( "Value" ) ]
53
74
public ValueInput Value { get ; private set ; }
54
75
55
76
[ DoNotSerialize ]
56
- [ PortLabel ( "Step" ) ]
57
- public ValueInput Step ;
77
+ public ValueInput NonStepValue { get ; private set ; }
78
+
79
+ [ DoNotSerialize ]
80
+ private readonly Dictionary < string , float > _intensityMultipliers = new ( ) ;
58
81
82
+ private List < LightComponentMapping > _lightComponentCache = new ( ) ;
59
83
private int _currentIndex ;
60
- private List < LightComponent > _lightComponentCache = null ;
61
84
62
85
protected override void Definition ( )
63
86
{
64
87
InputTrigger = ControlInput ( nameof ( InputTrigger ) , Process ) ;
65
88
OutputTrigger = ControlOutput ( nameof ( OutputTrigger ) ) ;
66
89
67
- var _multiInputs = new List < ValueInput > ( ) ;
68
-
69
- multiInputs = _multiInputs . AsReadOnly ( ) ;
90
+ var mi = new List < ValueInput > ( ) ;
91
+ multiInputs = mi . AsReadOnly ( ) ;
70
92
71
93
for ( var i = 0 ; i < inputCount ; i ++ ) {
72
94
var input = ValueInput ( i . ToString ( ) , string . Empty ) ;
73
- _multiInputs . Add ( input ) ;
74
-
95
+ mi . Add ( input ) ;
75
96
Requirement ( input , InputTrigger ) ;
76
97
}
77
98
78
- Value = ValueInput ( nameof ( Value ) , 0f ) ;
79
99
Step = ValueInput ( nameof ( Step ) , 1 ) ;
80
100
101
+ Value = ValueDataType switch
102
+ {
103
+ LampDataType . OnOff => ValueInput ( nameof ( Value ) , false ) ,
104
+ LampDataType . Status => ValueInput ( nameof ( Value ) , LampStatus . Off ) ,
105
+ LampDataType . Intensity => ValueInput ( nameof ( Value ) , 0f ) ,
106
+ LampDataType . Color => ValueInput ( nameof ( Value ) , UnityEngine . Color . white ) ,
107
+ _ => throw new ArgumentOutOfRangeException ( )
108
+ } ;
109
+
110
+ NonStepValue = NonStepValueDataType switch
111
+ {
112
+ LampDataType . OnOff => ValueInput ( nameof ( NonStepValue ) , false ) ,
113
+ LampDataType . Status => ValueInput ( nameof ( NonStepValue ) , LampStatus . Off ) ,
114
+ LampDataType . Intensity => ValueInput ( nameof ( NonStepValue ) , 0f ) ,
115
+ LampDataType . Color => ValueInput ( nameof ( NonStepValue ) , UnityEngine . Color . white ) ,
116
+ _ => throw new ArgumentOutOfRangeException ( )
117
+ } ;
118
+
81
119
Succession ( InputTrigger , OutputTrigger ) ;
82
120
83
- _lightComponentCache = null ;
121
+ _lightComponentCache . Clear ( ) ;
84
122
}
85
123
86
124
private ControlOutput Process ( Flow flow )
87
125
{
88
- if ( ! AssertGle ( flow ) )
89
- {
126
+ if ( ! AssertGle ( flow ) ) {
90
127
Debug . LogError ( "Cannot find GLE." ) ;
91
128
return OutputTrigger ;
92
129
}
@@ -96,52 +133,99 @@ private ControlOutput Process(Flow flow)
96
133
return OutputTrigger ;
97
134
}
98
135
99
- var value = flow . GetValue < float > ( Value ) ;
100
- var stepRaw = flow . GetValue < int > ( Step ) ;
101
-
102
- if ( _lightComponentCache != null ) {
103
- foreach ( var component in _lightComponentCache ) {
104
- if ( component . IsUnityNull ( ) ) {
105
- _lightComponentCache = null ;
106
- break ;
107
- }
136
+ foreach ( var mapping in _lightComponentCache ) {
137
+ if ( ! mapping . IsValid ( ) ) {
138
+ _lightComponentCache . Clear ( ) ;
139
+ break ;
108
140
}
109
141
}
110
142
111
- if ( _lightComponentCache == null ) {
112
- _lightComponentCache = new List < LightComponent > ( ) ;
113
-
143
+ if ( _lightComponentCache . Count == 0 ) {
114
144
foreach ( var input in multiInputs ) {
115
145
var lampId = flow . GetValue < string > ( input ) ;
116
- _lightComponentCache . AddRange ( Flatten ( Player . LampDevice ( lampId ) ) ) ;
146
+
147
+ var mapping = Player . LampMapping . FirstOrDefault ( l => l . Id == lampId ) ;
148
+ if ( mapping != null ) {
149
+ UpdateLightComponentCache ( mapping . Device , lampId ) ;
150
+ }
151
+ else {
152
+ Debug . LogError ( $ "Unknown lamp ID { lampId } .") ;
153
+ _lightComponentCache . Clear ( ) ;
154
+
155
+ break ;
156
+ }
117
157
}
118
158
}
119
159
160
+ var stepRaw = flow . GetValue < int > ( Step ) ;
161
+
162
+ LampDataType dataType ;
163
+ ValueInput value ;
164
+
120
165
for ( var index = 0 ; index < _lightComponentCache . Count ; index ++ ) {
121
- ;
166
+ if ( index >= _currentIndex * stepRaw && index < ( _currentIndex + 1 ) * stepRaw ) {
167
+ dataType = ValueDataType ;
168
+ value = Value ;
169
+ }
170
+ else {
171
+ dataType = NonStepValueDataType ;
172
+ value = NonStepValue ;
173
+ }
174
+
175
+ var lampApi = Player . Lamp ( _lightComponentCache [ index ] . lightComponent ) ;
176
+
177
+ switch ( dataType ) {
178
+ case LampDataType . OnOff :
179
+ lampApi . OnLamp ( flow . GetValue < bool > ( value ) ? LampStatus . On : LampStatus . Off ) ;
180
+ break ;
181
+ case LampDataType . Status :
182
+ lampApi . OnLamp ( flow . GetValue < LampStatus > ( value ) ) ;
183
+ break ;
184
+ case LampDataType . Intensity :
185
+ lampApi . OnLamp ( flow . GetValue < float > ( value ) * GetIntensityMultiplier ( _lightComponentCache [ index ] . id ) ) ;
186
+ break ;
187
+ case LampDataType . Color :
188
+ lampApi . OnLamp ( flow . GetValue < UnityEngine . Color > ( value ) ) ;
189
+ break ;
190
+ default :
191
+ throw new ArgumentOutOfRangeException ( ) ;
192
+ }
122
193
}
123
194
124
195
if ( ++ _currentIndex >= _lightComponentCache . Count / stepRaw ) {
125
196
_currentIndex = 0 ;
126
197
}
127
-
198
+
128
199
return OutputTrigger ;
129
200
}
130
201
131
- private List < LightComponent > Flatten ( List < ILampDeviceComponent > lampDeviceList )
202
+ private float GetIntensityMultiplier ( string id )
132
203
{
133
- List < LightComponent > lights = new List < LightComponent > ( ) ;
204
+ if ( _intensityMultipliers . ContainsKey ( id ) ) {
205
+ return _intensityMultipliers [ id ] ;
206
+ }
134
207
135
- foreach ( ILampDeviceComponent device in lampDeviceList ) {
136
- if ( device is LightComponent ) {
137
- lights . Add ( device as LightComponent ) ;
138
- }
139
- else if ( device is LightGroupComponent ) {
140
- lights . AddRange ( Flatten ( ( ( LightGroupComponent ) device ) . Lights ) ) ;
141
- }
208
+ var mapping = Player . LampMapping . FirstOrDefault ( l => l . Id == id ) ;
209
+ if ( mapping == null ) {
210
+ Debug . LogError ( $ "Unknown lamp ID { id } .") ;
211
+ _intensityMultipliers [ id ] = 1 ;
212
+ return 1 ;
142
213
}
143
214
144
- return lights ;
215
+ _intensityMultipliers [ id ] = mapping . Type == LampType . Rgb ? 255 : 1 ;
216
+ return _intensityMultipliers [ id ] ;
217
+ }
218
+
219
+ private void UpdateLightComponentCache ( ILampDeviceComponent device , string id )
220
+ {
221
+ if ( device is LightComponent ) {
222
+ _lightComponentCache . Add ( new LightComponentMapping { lightComponent = device as LightComponent , id = id } ) ;
223
+ }
224
+ else if ( device is LightGroupComponent ) {
225
+ foreach ( var light in ( device as LightGroupComponent ) . Lights ) {
226
+ UpdateLightComponentCache ( light , id ) ;
227
+ }
228
+ }
145
229
}
146
230
}
147
231
}
0 commit comments