DirectOuput Framework R2
DirectOutput framework R2 for virtual pinball cabinets
Go to:
Overview 
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros Pages
MatrixShiftEffectBase.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using DirectOutput.General.Color;
6 using DirectOutput.Cab.Toys.Layer;
7 
8 namespace DirectOutput.FX.MatrixFX
9 {
14  public abstract class MatrixShiftEffectBase<MatrixElementType> : MatrixEffectBase<MatrixElementType>
15  {
16  private const int RefreshIntervalMs = 30;
17 
18 
19  private MatrixShiftDirectionEnum _ShiftDirection = MatrixShiftDirectionEnum.Right;
20 
27  public MatrixShiftDirectionEnum ShiftDirection
28  {
29  get { return _ShiftDirection; }
30  set { _ShiftDirection = value; }
31  }
32 
33  private float _ShiftSpeed = 200;
34 
43  public float ShiftSpeed
44  {
45  get { return _ShiftSpeed; }
46  set { _ShiftSpeed = value.Limit(1, 10000); }
47  }
48 
49 
50  private float _ShiftAcceleration = 0;
58  public float ShiftAcceleration
59  {
60  get { return _ShiftAcceleration; }
61  set { _ShiftAcceleration = value; }
62  }
63 
64 
65 
66  private void BuildStep2ElementTable()
67  {
68  List<float> L = new List<float>();
69 
70  float NumberOfElements = (ShiftDirection == MatrixShiftDirectionEnum.Left || ShiftDirection == MatrixShiftDirectionEnum.Right ? AreaWidth : AreaHeight);
71  float Position = 0;
72  float Speed = NumberOfElements/100*(ShiftSpeed / (1000 / RefreshIntervalMs));
73  float Acceleration = NumberOfElements / 100 * (ShiftAcceleration / (1000 / RefreshIntervalMs));
74  while (Position <= NumberOfElements)
75  {
76  L.Add(Position.Limit(0,NumberOfElements));
77  Position += Speed ;
78  Speed = (Speed + Acceleration).Limit(NumberOfElements / 100 * (1 / (1000 / RefreshIntervalMs)), 10000);
79  }
80  L.Add(Position.Limit(0, NumberOfElements));
81 
82 
83  Step2Element = L.ToArray();
84  }
85 
86  float[] Step2Element=null;
87 
88  private void DoStep()
89  {
90  if (!Active)
91  {
92  Table.Pinball.Alarms.RegisterIntervalAlarm(RefreshIntervalMs, DoStep);
93  Active = true;
94  }
95 
96 
97  int NumberOfElements = (ShiftDirection == MatrixShiftDirectionEnum.Left || ShiftDirection == MatrixShiftDirectionEnum.Right ? AreaWidth : AreaHeight);
98 
99 
100  float FromElementNr = NumberOfElements;
101  float ToElementNr = 0;
102  float[] Value = new float[NumberOfElements+1];
103 
104  int LastValue = LastDiscardedValue;
105 
106  int ToNr;
107  foreach (KeyValuePair<int, int> KV in TriggerValueBuffer)
108  {
109  ToElementNr = Step2Element[(CurrentStep-KV.Key)];
110 
111  if (FromElementNr.Floor() == ToElementNr.Floor())
112  {
113  Value[(int)FromElementNr.Floor()] += (FromElementNr - ToElementNr) * LastValue;
114  }
115  else
116  {
117  if (!FromElementNr.IsIntegral())
118  {
119  Value[(int)FromElementNr.Floor()] += (FromElementNr - FromElementNr.Floor()) * LastValue;
120  }
121 
122  ToNr = (int)(ToElementNr.Ceiling());
123  for (int i = (int)FromElementNr.Floor()-1; i >= ToNr; i--)
124  {
125  Value[i] = LastValue;
126  }
127  if (!ToElementNr.IsIntegral())
128  {
129  Value[(int)ToElementNr.Floor()] += (ToElementNr.Ceiling() - ToElementNr) * LastValue;
130  }
131 
132  }
133  FromElementNr=ToElementNr;
134  LastValue = KV.Value;
135  }
136  ToElementNr = 0;
137  if (FromElementNr != ToElementNr)
138  {
139  if (!FromElementNr.IsIntegral() && FromElementNr.Floor() < Width - 1)
140  {
141  Value[(int)FromElementNr.Floor()] += (FromElementNr - FromElementNr.Floor()) * LastValue;
142  }
143 
144  ToNr = (int)(ToElementNr.Ceiling()).Limit(0, int.MaxValue);
145  for (int i = (int)FromElementNr.Floor()-1; i >= ToNr; i--)
146  {
147  Value[i] = LastValue;
148  }
149  if (!ToElementNr.IsIntegral())
150  {
151  Value[(int)ToElementNr.Floor()] += (ToElementNr.Ceiling() - ToElementNr) * LastValue;
152  }
153  }
154 
155 
156  #region Data ouput
157  switch (ShiftDirection)
158  {
159  case MatrixShiftDirectionEnum.Right:
160  for (int i = 0; i < NumberOfElements; i++)
161  {
162  int V = ((int)Value[i]).Limit(0, 255);
163  if (V > 0 && FadeMode == FadeModeEnum.OnOff) { V = 255; }
164  MatrixElementType D = GetEffectValue(V);
165 
166  for (int y = AreaTop; y <= AreaBottom; y++)
167  {
168  MatrixLayer[AreaLeft + i, y] = D;
169  }
170  }
171  break;
172  case MatrixShiftDirectionEnum.Down:
173  for (int i = 0; i < NumberOfElements; i++)
174  {
175  int V = ((int)Value[i]).Limit(0, 255);
176  if (V > 0 && FadeMode == FadeModeEnum.OnOff) { V = 255; }
177  MatrixElementType D = GetEffectValue(V);
178 
179  for (int x = AreaLeft; x <= AreaRight; x++)
180  {
181  MatrixLayer[x, AreaTop + i] = D;
182  }
183  }
184  break;
185  case MatrixShiftDirectionEnum.Up:
186  for (int i = 0; i < NumberOfElements; i++)
187  {
188  int V = ((int)Value[i]).Limit(0, 255);
189  if (V > 0 && FadeMode == FadeModeEnum.OnOff) { V = 255; }
190  MatrixElementType D = GetEffectValue(V);
191 
192  for (int x = AreaLeft; x <= AreaRight; x++)
193  {
194  MatrixLayer[x, AreaBottom - i] = D;
195  }
196  }
197  break;
198  case MatrixShiftDirectionEnum.Left:
199  default:
200  for (int i = 0; i < NumberOfElements; i++)
201  {
202  int V = ((int)Value[i]).Limit(0, 255);
203  if (V > 0 && FadeMode == FadeModeEnum.OnOff) { V = 255; }
204  MatrixElementType D = GetEffectValue(V);
205 
206  for (int y = AreaTop; y <= AreaBottom; y++)
207  {
208  MatrixLayer[AreaRight - i, y] = D;
209  }
210  }
211  break;
212  }
213  #endregion
214 
215 
216 
217 
218 
219  int DropKey = CurrentStep - (Step2Element.Length-1);
220  if (TriggerValueBuffer.ContainsKey(DropKey))
221  {
222  LastDiscardedValue = TriggerValueBuffer[DropKey];
223  TriggerValueBuffer.Remove(DropKey);
224  };
225 
226  if (TriggerValueBuffer.Count > 0 || LastDiscardedValue!=0)
227  {
228  CurrentStep++;
229  }
230  else
231  {
232  Table.Pinball.Alarms.UnregisterIntervalAlarm(DoStep);
233  LastDiscardedValue = 0;
234  CurrentStep = 0;
235  Active = false;
236  }
237  }
238 
239  int LastDiscardedValue = 0;
240  bool Active = false;
241 
242  SortedDictionary<int, int> TriggerValueBuffer = new SortedDictionary<int, int>();
243  int LastTriggerValue = 0;
244 
245 
246  int CurrentStep = 0;
247 
248 
249 
256  protected abstract MatrixElementType GetEffectValue(int TriggerValue);
257 
258 
259  public override void Trigger(Table.TableElementData TableElementData)
260  {
261  if (LastTriggerValue != TableElementData.Value && MatrixLayer!=null)
262  {
263  LastTriggerValue = TableElementData.Value;
264 
265 
266  if (TriggerValueBuffer.ContainsKey(CurrentStep))
267  {
268  TriggerValueBuffer[CurrentStep] = LastTriggerValue;
269  }
270  else
271  {
272  TriggerValueBuffer.Add(CurrentStep, LastTriggerValue);
273  }
274 
275  if (!Active)
276  {
277  DoStep();
278  }
279 
280  }
281 
282 
283  }
284 
285 
286 
287 
288 
289  public override void Init(Table.Table Table)
290  {
291  base.Init(Table);
292  BuildStep2ElementTable();
293  }
294 
295  public override void Finish()
296  {
297  Table.Pinball.Alarms.UnregisterIntervalAlarm(DoStep);
298  base.Finish();
299  }
300 
301  }
302 }