public override void Finish() { if (Active) { CurrentValue = 0; DoFlicker(); } ActiveFlickerObjects.Clear(); InactiveFlickerObjects.Clear(); base.Finish(); }
private void DoFlicker() { MatrixElementType I = GetEffectValue(0); int V = CurrentValue.Limit(0, 255); if (V > 0) { if (!Active) { Table.Pinball.Alarms.RegisterIntervalAlarm(RefreshIntervalMs, DoFlicker); Active = true; } //Effect is active (V>0) if (V > 0 && FadeMode == FadeModeEnum.OnOff) { V = 255; } int NumberOfLeds = AreaWidth * AreaHeight; int FlickerLeds = ((int)((double)NumberOfLeds / 100 * Density)).Limit(1, NumberOfLeds); int Min = MinFlickerDurationMs; int Max = MaxFlickerDurationMs; if (Max < Min) { int Tmp = Min; Min = Max; Max = Tmp; } //if (Min != Max && ActiveFlickerObjects.Count.IsBetween(0,FlickerLeds-1)) //{ // int Avg = (Min + Max / 2) - Min; // int NewObjectsAvg = ((FlickerLeds * Avg) - ActiveFlickerObjects.Sum(FO => FO.DurationMs)) / (FlickerLeds - ActiveFlickerObjects.Count); // int NewObjectsAvgChange = Avg - NewObjectsAvg; // if (NewObjectsAvgChange < 0) // { // //Increase min // Min = (Min + Math.Abs(NewObjectsAvgChange) * 2).Limit(Min, Max); // } // else // { // //Decrease max // Max = (Max - NewObjectsAvgChange * 2).Limit(Min, Max); // } //} while (ActiveFlickerObjects.Count < FlickerLeds && InactiveFlickerObjects.Count > 0) { FlickerObject FO = InactiveFlickerObjects[R.Next(InactiveFlickerObjects.Count)]; InactiveFlickerObjects.Remove(FO); FO.StartTimestamp = DateTime.Now; FO.DurationMs = R.Next(Min, Max) + FlickerFadeDownDurationMs; ActiveFlickerObjects.Add(FO); } DateTime CurrentTimestamp = DateTime.Now; for (int i = ActiveFlickerObjects.Count - 1; i >= 0; i--) { FlickerObject FO = ActiveFlickerObjects[i]; int FV; int AgeMs = (int)(DateTime.Now - FO.StartTimestamp).TotalMilliseconds; if (AgeMs > FO.DurationMs + FlickerFadeDownDurationMs) { if (AgeMs > (FO.DurationMs + FlickerFadeDownDurationMs) * 2 || R.NextDouble() > .5) { //Remove element ActiveFlickerObjects.Remove(FO); InactiveFlickerObjects.Add(FO); } FV = 0; } else if (FlickerFadeUpDurationMs > 0 && AgeMs < FlickerFadeUpDurationMs && AgeMs < FO.DurationMs) { //Fade up FV = (int)((double)V / FlickerFadeUpDurationMs * AgeMs); //Log.Write("U: " + FV.ToString()); } else if (AgeMs > FO.DurationMs && FlickerFadeDownDurationMs > 0) { //Fade down if (FO.DurationMs < FlickerFadeUpDurationMs) { FV = (int)((double)V / FlickerFadeUpDurationMs * FO.DurationMs); } else { FV = V; } FV = FV - (int)((double)FV / FlickerFadeDownDurationMs * (AgeMs - FO.DurationMs)); //Log.Write("D: " + FV.ToString()); } else { //Full on FV = V; //Log.Write("F: " + FV.ToString()); } FV = FV.Limit(0, 255); MatrixLayer[FO.X, FO.Y] = GetEffectValue(FV); } } else { foreach (FlickerObject FO in ActiveFlickerObjects) { MatrixLayer[FO.X, FO.Y] = I; } InactiveFlickerObjects.AddRange(ActiveFlickerObjects); ActiveFlickerObjects.Clear(); Table.Pinball.Alarms.UnregisterIntervalAlarm(DoFlicker); Active = false; } }