private void DoRendering(CancellationTokenSource tokenSource = null) { //TODO: get a better increment time. doing it every X ms is..... shitty at best. TimeSpan increment = TimeSpan.FromMilliseconds(2); List <ElementNode> renderNodes = GetNodesToRenderOn(); int targetNodeCount = renderNodes.Count; Pulse.Pulse pulse; EffectIntents pulseData; // apply the 'background' values to all targets if the level is supposed to be nonzero if (DefaultLevel > 0) { int i = 0; foreach (ElementNode target in renderNodes) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } if (target != null && target.Element != null) { bool discreteColors = ColorModule.isElementNodeDiscreteColored(target); pulse = new Pulse.Pulse(); pulse.TargetNodes = new ElementNode[] { target }; pulse.TimeSpan = TimeSpan; double level = DefaultLevel * 100.0; // figure out what color gradient to use for the pulse switch (ColorHandling) { case ChaseColorHandling.GradientForEachPulse: pulse.ColorGradient = StaticColorGradient; pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { level, level })); pulseData = pulse.Render(); _elementData.Add(pulseData); break; case ChaseColorHandling.GradientThroughWholeEffect: pulse.ColorGradient = ColorGradient; pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { level, level })); pulseData = pulse.Render(); _elementData.Add(pulseData); break; case ChaseColorHandling.StaticColor: pulse.ColorGradient = StaticColorGradient; pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { level, level })); pulseData = pulse.Render(); _elementData.Add(pulseData); break; case ChaseColorHandling.ColorAcrossItems: double positionWithinGroup = i / (double)targetNodeCount; if (discreteColors) { List <Tuple <Color, float> > colorsAtPosition = ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup); foreach (Tuple <Color, float> colorProportion in colorsAtPosition) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } double value = level * colorProportion.Item2; pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { value, value })); pulse.ColorGradient = new ColorGradient(colorProportion.Item1); pulseData = pulse.Render(); _elementData.Add(pulseData); } } else { pulse.ColorGradient = new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup)); pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { level, level })); pulseData = pulse.Render(); _elementData.Add(pulseData); } break; } i++; } } } // the total chase time TimeSpan chaseTime = TimeSpan.FromMilliseconds(TimeSpan.TotalMilliseconds - PulseOverlap); if (chaseTime.TotalMilliseconds <= 0) { chaseTime = TimeSpan.FromMilliseconds(1); } // we need to keep track of the element that is 'under' the curve at a given time, to see if it changes, // and when it does, we make the effect for it then (since it's a variable time pulse). ElementNode lastTargetedNode = null; TimeSpan lastNodeStartTime = TimeSpan.Zero; // iterate up to and including the last pulse generated for (TimeSpan current = TimeSpan.Zero; current <= TimeSpan; current += increment) { if (tokenSource != null && tokenSource.IsCancellationRequested) { return; } double currentPercentageIntoChase = ((double)current.Ticks / (double)chaseTime.Ticks) * 100.0; double currentMovementPosition = ChaseMovement.GetValue(currentPercentageIntoChase); int currentNodeIndex = (int)((currentMovementPosition / 100.0) * targetNodeCount); // on the off chance we hit the 100% mark *exactly*... if (currentNodeIndex == targetNodeCount && currentNodeIndex > 0) { currentNodeIndex--; } if (currentNodeIndex >= targetNodeCount) { Logging.Warn( "Chase effect: rendering, but the current node index is higher or equal to the total target nodes."); continue; } if (currentNodeIndex < 0) { continue; } ElementNode currentNode = renderNodes[currentNodeIndex]; if (currentNode == lastTargetedNode) { continue; } // if the last node targeted wasn't null, we need to make a pulse for it if (lastTargetedNode != null) { TimeSpan duration = current - lastNodeStartTime + TimeSpan.FromMilliseconds(PulseOverlap); GeneratePulse(lastTargetedNode, lastNodeStartTime, duration , currentMovementPosition); } lastTargetedNode = currentNode; lastNodeStartTime = current; // if we've hit the 100% mark of the chase curve, bail (the last one gets generated after) if (currentPercentageIntoChase >= 100.0) { break; } } // generate the last pulse if (lastTargetedNode != null) { GeneratePulse(lastTargetedNode, lastNodeStartTime, TimeSpan - lastNodeStartTime, 1.0); } _elementData = EffectIntents.Restrict(_elementData, TimeSpan.Zero, TimeSpan); }
private void DoRendering() { //TODO: get a better increment time. doing it every X ms is..... shitty at best. TimeSpan increment = TimeSpan.FromMilliseconds(2); List <ElementNode> renderNodes = GetNodesToRenderOn(); int targetNodeCount = renderNodes.Count; Pulse.Pulse pulse; EffectIntents pulseData; // apply the 'background' values to all targets int i = 0; foreach (ElementNode target in renderNodes) { pulse = new Pulse.Pulse(); pulse.TargetNodes = new ElementNode[] { target }; pulse.TimeSpan = TimeSpan; pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { DefaultLevel * 100, DefaultLevel * 100 })); // figure out what color gradient to use for the pulse switch (ColorHandling) { case ChaseColorHandling.GradientForEachPulse: pulse.ColorGradient = new ColorGradient(StaticColor); break; case ChaseColorHandling.GradientThroughWholeEffect: pulse.ColorGradient = ColorGradient; break; case ChaseColorHandling.StaticColor: pulse.ColorGradient = new ColorGradient(StaticColor); break; case ChaseColorHandling.ColorAcrossItems: pulse.ColorGradient = new ColorGradient(ColorGradient.GetColorAt((double)i / (double)targetNodeCount)); break; } pulseData = pulse.Render(); _elementData.Add(pulseData); i++; } // the total chase time TimeSpan chaseTime = TimeSpan.FromMilliseconds(TimeSpan.TotalMilliseconds - PulseOverlap); if (chaseTime.TotalMilliseconds <= 0) { chaseTime = TimeSpan.FromMilliseconds(1); } // we need to keep track of the element that is 'under' the curve at a given time, to see if it changes, // and when it does, we make the effect for it then (since it's a variable time pulse). ElementNode lastTargetedNode = null; TimeSpan lastNodeStartTime = TimeSpan.Zero; // iterate up to and including the last pulse generated for (TimeSpan current = TimeSpan.Zero; current <= TimeSpan; current += increment) { double currentPercentageIntoChase = ((double)current.Ticks / (double)chaseTime.Ticks) * 100.0; double currentMovementPosition = ChaseMovement.GetValue(currentPercentageIntoChase); int currentNodeIndex = (int)((currentMovementPosition / 100.0) * targetNodeCount); // on the off chance we hit the 100% mark *exactly*... if (currentNodeIndex == targetNodeCount) { currentNodeIndex--; } if (currentNodeIndex >= targetNodeCount) { VixenSystem.Logging.Warning("Chase effect: rendering, but the current node index is higher or equal to the total target nodes."); continue; } ElementNode currentNode = renderNodes[currentNodeIndex]; if (currentNode == lastTargetedNode) { continue; } // if the last node targeted wasn't null, we need to make a pulse for it if (lastTargetedNode != null) { GeneratePulse(lastTargetedNode, lastNodeStartTime, current - lastNodeStartTime + TimeSpan.FromMilliseconds(PulseOverlap), currentMovementPosition); } lastTargetedNode = currentNode; lastNodeStartTime = current; // if we've hit the 100% mark of the chase curve, bail (the last one gets generated after) if (currentPercentageIntoChase >= 100.0) { break; } } // generate the last pulse if (lastTargetedNode != null) { GeneratePulse(lastTargetedNode, lastNodeStartTime, TimeSpan - lastNodeStartTime, 1.0); } _elementData = EffectIntents.Restrict(_elementData, TimeSpan.Zero, TimeSpan); }