public async Task Blinker(int intervalMS) { bool on = false; while (true) { if (on) { foreach (Led l in this.leds) { l.Color(HSVColor.Black); } on = false; } else { foreach (Led l in this.leds) { l.Color(new HSVColor(0.2f, 1f, 1f)); } on = true; } NewFrameReady.Invoke(this, this.leds); await Task.Delay(intervalMS); } }
/// <summary> /// Plays the specified animation once. /// </summary> /// <param name="animPath">The animation path</param> /// <param name="keepTail">If set true, when the animation ends LEDs won't be set to black</param> public void RunAnimationOnce(string animPath, bool keepTail = false, float fadeOutAfterRate = 0) { Animation anim = LoadAnimation(animPath); if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); //isAnimationRunning = true; Task.Run(() => PlayOnce(anim, currentlyRunningAnim.Token)).ContinueWith(async(t) => { if (!keepTail) { if (fadeOutAfterRate > 0) { await FadeOutToBlack(fadeOutAfterRate, currentlyRunningAnim.Token); } else { this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds); } } //isAnimationRunning = false; }); }
/// <summary> /// Plays the specified animation once. /// </summary> private async Task PlayOnce(Animation anim, CancellationToken cancelToken) { int i = 0; while (true) { for (int j = 0; j < leds.Length; j++) { if (leds.Length == anim.FrameLength) { leds[j].Color(anim[i][j]); } else { // Scaling animation to fit led count leds[j].Color(HSVColor.Black); int index = (int)Utils.Scale(j, 0, leds.Length, 0, anim.FrameLength); leds.AddColorToLedsAround(j, anim[i][index], 5); } } i++; if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds); await Task.Delay(30); if (i == anim.FrameCount) { break; } } //currentlyRunningAnim = null; }
/// <summary> /// Creates a color burst, starting at the given color and progressively fading to black. /// </summary> /// <param name="color">The burst color.</param> /// <param name="fadeoutRate">The burst fade-out rate.</param> /// <returns></returns> public Task ColorBurst(HSVColor color, float fadeoutRate = 0.15f) { if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); //isAnimationRunning = true; return(Task.Run(async() => { foreach (Led l in this.leds) { l.Color(color); } NewFrameReady.Invoke(this, this.leds); if (fadeoutRate > 0) { await FadeOutToBlack(fadeoutRate, currentlyRunningAnim.Token); } else { this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds); } })); }
public Task HoldColor(HSVColor col, int durationMS) { if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); //isAnimationRunning = true; return(TaskRunner.RunAsync(Task.Run(async() => { CancellationToken token = currentlyRunningAnim.Token; foreach (Led l in this.leds) { l.Color(col); } int msCounter = 0; while (msCounter < durationMS) { if (token.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); await Task.Delay(50); msCounter += 50; } }))); }
/// <summary> /// Plays the specified animation once for <paramref name="loopDuration"/> milliseconds. /// </summary> /// <param name="fadeOutAfterRate">Optionally fade out the last animation frame progressively.</param> public void RunAnimationInLoop(string animPath, int loopDuration, float fadeOutAfterRate = 0, float timeScale = 1) { Animation anim = LoadAnimation(animPath); if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); CancellationToken token = currentlyRunningAnim.Token; var t = TaskRunner.RunAsync(Task.Run(() => PlayLoop(anim, token, loopDuration, timeScale)).ContinueWith(async(t) => { if (t.IsCanceled) { return; // don't continue if task was cancelled } if (fadeOutAfterRate > 0) { await FadeOutToBlack(fadeOutAfterRate, token, anim.AnimationMode); } else { this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds, LightingMode.Line); } //isAnimationRunning = false; })); }
/// <summary> /// Plays the specified animation once. /// </summary> /// <param name="animPath">The animation path</param> /// <param name="keepTail">If set true, when the animation ends LEDs won't be set to black</param> public Task RunAnimationOnce(string animPath, bool keepTail = false, float fadeOutAfterRate = 0, float timeScale = 1) { Animation anim = LoadAnimation(animPath); if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); //isAnimationRunning = true; return(Task.Run(() => PlayOnce(anim, currentlyRunningAnim.Token, timeScale)).ContinueWith(async(t) => { if (!keepTail) { if (fadeOutAfterRate > 0) { await FadeOutToBlack(fadeOutAfterRate, currentlyRunningAnim.Token, anim.AnimationMode); } else { this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds, LightingMode.Line); } } //isAnimationRunning = false; })); }
public async Task Blinker(int intervalMS) { bool on = false; while (true) { if (masterCancelToken.IsCancellationRequested) { return; } if (on) { foreach (Led l in this.leds) { l.Color(HSVColor.Black); } on = false; } else { foreach (Led l in this.leds) { l.Color(new HSVColor(0.2f, 1f, 1f)); } on = true; } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); await Task.Delay(intervalMS); } }
/// <summary> /// Called by a <see cref="LEDModule"/> when a new frame is available to be processed. /// </summary> /// <param name="s">Module that sent the message</param> /// <param name="data">LED data</param> private void OnNewFrameReceived(object s, Led[] data) { if (s != CurrentLEDSource) { return; // If it's from a different source that what we're listening too, ignore it } NewFrameReady?.Invoke(this, data); msSinceLastExternalFrameReceived = 0; }
void OnNewAudioData() { DoFrame(); LEDData data = LEDData.Empty; data.Strip = this.leds.CloneLeds(); NewFrameReady?.Invoke(new LEDFrame(this, data, LightZone.Strip, true)); newAudioAvailable = true; }
/// <summary> /// Plays the specified animation in loop for <paramref name="durationMs"/> milliseconds. /// </summary> private async Task PlayLoop(Animation anim, CancellationToken cancelToken, int durationMs, float timeScale) { int frameTime = (int)(30 / timeScale); int i = 0; int msCounter = 0; this.leds = anim.AnimationMode == LightingMode.Keyboard ? new Led[88] : new Led[anim.FrameLength]; if (anim.AnimationMode == LightingMode.Keyboard) { for (int j = 0; j < 88; j++) { this.leds[j] = new Led(); } } else { for (int j = 0; j < anim.FrameLength; j++) { this.leds[j] = new Led(); } } while (true) { for (int j = 0; j < this.leds.Length; j++) { if (this.leds.Length == anim.FrameLength) { this.leds[j].Color(anim[i][j]); } else { // Scaling animation to fit led count this.leds[j].Color(HSVColor.Black); int index = (int)Utils.Scale(j, 0, this.leds.Length, 0, anim.FrameLength); this.leds.AddColorToLedsAround(j, anim[i][index], 5); } } i = (i + 1) % anim.FrameCount; if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, anim.AnimationMode); await Task.Delay(frameTime); if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); // it seems to prevent some simultaneous-update bugs } msCounter += frameTime; if (msCounter >= durationMs) { break; } } //currentlyRunningAnim = null; }
/// <summary> /// Plays the specified animation once. /// </summary> private async Task PlayOnce(Animation anim, CancellationToken cancelToken, float timeScale) { int frameTime = (int)(30 / timeScale); int i = 0; this.leds = anim.AnimationMode == LightingMode.Keyboard ? new Led[88] : new Led[anim.FrameLength]; if (anim.AnimationMode == LightingMode.Keyboard) { for (int j = 0; j < 88; j++) { this.leds[j] = new Led(); } } else { for (int j = 0; j < anim.FrameLength; j++) { this.leds[j] = new Led(); } } while (true) { for (int j = 0; j < this.leds.Length; j++) { if (this.leds.Length == anim.FrameLength) { this.leds[j].Color(anim[i][j]); } else { // Scaling animation to fit led count this.leds[j].Color(HSVColor.Black); int index = (int)Utils.Scale(j, 0, this.leds.Length, 0, anim.FrameLength); this.leds.AddColorToLedsAround(j, anim[i][index], 5); } } i++; if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, anim.AnimationMode); await Task.Delay(frameTime); if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } if (i == anim.FrameCount) { break; } } //currentlyRunningAnim = null; }
private void SendFrame(LEDData data, LightZone zones, bool priority = false) { lastFrame = data; if (NewFrameReady == null) { throw new InvalidOperationException("Tried to SendFrame, but no NewFrameReady handler was attached to this AnimationModule."); } else { NewFrameReady?.Invoke(new LEDFrame(this, data, zones, priority)); } }
/// <summary> /// Called by a <see cref="LEDModule"/> when a new frame is available to be processed. /// </summary> /// <param name="s">Module that sent the message</param> /// <param name="data">LED data</param> private void OnNewFrameReceived(object s, Led[] data, LightingMode mode) { if ((s is ChampionModule && CurrentLEDSource is ItemModule && !((ItemModule)CurrentLEDSource).IsPriorityItem)) // Champion modules take priority over item casts... for the moment { CurrentLEDSource = (LEDModule)s; } if (s != CurrentLEDSource) { return; // If it's from a different source that what we're listening too, ignore it } NewFrameReady?.Invoke(this, data, mode); msSinceLastExternalFrameReceived = 0; }
/// <summary> /// Cancels the currently running animation and sets the LEDs to black. /// </summary> public void StopCurrentAnimation() { if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds, LightingMode.Line); Task.Run(async() => { // wait a bit for the current frame await Task.Delay(50); NewFrameReady.Invoke(this, this.leds, LightingMode.Line); }); //isAnimationRunning = false; } }
// Set duration to -1 for indefinite private async Task FadeBetweenTwoColors(float rate, HSVColor col1, HSVColor col2, float duration, CancellationToken cancelToken) { int msCounter = 0; while ((duration >= 0 && msCounter < duration) || duration < 0) { float sin = (float)Math.Sin((msCounter / 1000f) * rate); this.leds.SetAllToColor(HSVColor.Lerp(col1, col2, sin)); if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); await Task.Delay(30); msCounter += 30; } }
private async Task FadeOutToColor(float rate, HSVColor color, CancellationToken cancelToken) { int msCounter = 0; int fadeoutTime = (int)(GetFadeToBlackTime(rate) * 1000); while (msCounter < fadeoutTime) // TODO: calculate animation duration (rn its 1s) { this.leds.FadeToColorAllLeds(color, rate); if (cancelToken.IsCancellationRequested) { throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); await Task.Delay(30); msCounter += 30; } this.leds.SetAllToColor(color); }
/// <summary> /// Creates a color burst, starting at the given color and progressively fading to black. /// </summary> /// <param name="color">The burst color.</param> /// <param name="fadeoutRate">The burst fade-out rate.</param> /// <param name="destinationColor">The color to progressively fade to after the color burst (black by default)</param> /// <returns></returns> public Task ColorBurst(HSVColor color, float fadeoutRate = 0.15f, HSVColor destinationColor = default) { if (currentlyRunningAnim != null) { currentlyRunningAnim.Cancel(); } currentlyRunningAnim = new CancellationTokenSource(); //isAnimationRunning = true; return(TaskRunner.RunAsync(Task.Run(async() => { CancellationToken token = currentlyRunningAnim.Token; foreach (Led l in this.leds) { l.Color(color); } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); if (fadeoutRate > 0) { if (destinationColor.Equals(HSVColor.Black)) { await FadeOutToBlack(fadeoutRate, token, LightingMode.Line); } else { await FadeOutToColor(fadeoutRate, destinationColor, token); } } else { if (!destinationColor.Equals(HSVColor.Black)) { this.leds.SetAllToColor(destinationColor); } else { this.leds.SetAllToBlack(); } NewFrameReady.Invoke(this, this.leds, LightingMode.Line); } }))); }
/// <summary> /// Task that periodically updates the health bar. /// </summary> private async Task FrameTimer() { while (true) { if (masterCancelToken.IsCancellationRequested) { return; } if (msSinceLastExternalFrameReceived >= msAnimationTimerThreshold) { if (!CheckIfDead()) { HUDModule.DoFrame(this.leds, this.lightingMode, this.gameState); NewFrameReady?.Invoke(this, this.leds, this.lightingMode); } } await Task.Delay(30); msSinceLastExternalFrameReceived += 30; } }
private async Task FadeOutToBlack(float rate, CancellationToken cancelToken, LightingMode mode) { int msCounter = 0; int fadeoutTime = (int)(GetFadeToBlackTime(rate) * 1000); while (msCounter < fadeoutTime) { this.leds.FadeToBlackAllLeds(rate); if (cancelToken.IsCancellationRequested) { this.leds.SetAllToBlack(); NewFrameReady.Invoke(this, this.leds, mode); throw new TaskCanceledException(); } NewFrameReady.Invoke(this, this.leds, mode); await Task.Delay(30); msCounter += 30; } this.leds.SetAllToBlack(); }
/// <summary> /// If the player is dead, color red, and returns false so any other HUD Modules don't output data (dead = only red lights) /// </summary> /// <returns></returns> private bool CheckIfDead() { if (gameState.PlayerChampion.IsDead) { for (int i = 0; i < leds.Length; i++) { leds[i].Color(DeadColor); } wasDeadLastFrame = true; NewFrameReady?.Invoke(this, this.leds, LightingMode.Line); return(true); } else { if (wasDeadLastFrame) { leds.SetAllToBlack(); wasDeadLastFrame = false; } return(false); } }
/// <summary> /// Updates the health bar. /// </summary> private void UpdateHealthBar() { if (playerChampion.IsDead) { for (int i = 0; i < leds.Length; i++) { this.leds[i].Color(DeadColor); } } else { float maxHealth = activePlayer.Stats.MaxHealth; float currentHealth = activePlayer.Stats.CurrentHealth; float healthPercentage = currentHealth / maxHealth; int ledsToTurnOn = (int)(healthPercentage * leds.Length); for (int i = 0; i < leds.Length; i++) { // int index = reverseOrder ? this.leds.Length - 1 - i : i; if (i < ledsToTurnOn) { this.leds[i].MixNewColor(HealthColor, true); } else { if (this.leds[i].color.AlmostEqual(HealthColor)) { this.leds[i].Color(HurtColor); } else { this.leds[i].FadeToBlackBy(0.05f); } } } } NewFrameReady?.Invoke(this, this.leds); }
void OnNewAudioData() { DoFrame(); NewFrameReady?.Invoke(this, this.leds, LightingMode.Line); newAudioAvailable = true; }
private void FrameReceived(LEDFrame frame) { NewFrameReady.Invoke(frame); }
private void NewFrameReadyHandler(LEDFrame frame) { frame.SenderChain.Add(this); NewFrameReady?.Invoke(frame); }
/// <summary> /// Dispatches a frame with the given LED data, raising the NewFrameReady event. /// </summary> protected void DispatchNewFrame(Led[] ls) { NewFrameReady?.Invoke(this, ls); }
void OnNewAudioData() { DoFrame(); NewFrameReady?.Invoke(this, this.leds); newAudioAvailable = true; }
/// <summary> /// Dispatches a frame with the given LED data, raising the NewFrameReady event. /// </summary> protected void DispatchNewFrame(Led[] ls, LightingMode mode) { NewFrameReady?.Invoke(this, ls, mode); }
protected void InvokeNewFrameReady(LEDFrame frame) { frame.SenderChain.Add(this); NewFrameReady?.Invoke(frame); }