Exemple #1
0
        private void GenerateExtendedStaticPulse(ElementNode target, Curve newCurve, ColorGradient gradient, TimeSpan duration, TimeSpan offset)
        {
            var result = PulseRenderer.RenderNode(target, newCurve, gradient, duration, HasDiscreteColors);

            result.OffsetAllCommandsByTime(offset);
            _elementData.Add(result);
        }
Exemple #2
0
        private void RenderElement(GradientLevelPair gradientLevelPair, TimeSpan startTime, TimeSpan interval,
                                   ElementNode element, EffectIntents effectIntents)
        {
            var result = PulseRenderer.RenderNode(element, gradientLevelPair.Curve, gradientLevelPair.ColorGradient, interval, HasDiscreteColors);

            result.OffsetAllCommandsByTime(startTime);
            effectIntents.Add(result);
        }
Exemple #3
0
        private void DoRendering(CancellationTokenSource tokenSource = null)
        {
            List <ElementNode> renderNodes = GetNodesToRenderOn();
            int targetNodeCount            = renderNodes.Count;

            //If there are no nodes to render on Exit!
            if (targetNodeCount == 0)
            {
                return;
            }

            ElementNode lastTargetedNode = null;

            //Pulse.Pulse pulse;
            EffectIntents pulseData;

            // apply the 'background' values to all targets if nonzero
            if (EnableDefaultLevel)
            {
                int i = 0;
                foreach (ElementNode target in renderNodes)
                {
                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    bool discreteColors = ColorModule.isElementNodeDiscreteColored(target);

                    if (target == null)
                    {
                        continue;
                    }

                    if (target != null)
                    {
                        double level = DefaultLevel * 100.0;

                        // figure out what color gradient to use for the pulse
                        switch (ColorHandling)
                        {
                        case SpinColorHandling.GradientForEachPulse:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new [] { level, level })), StaticColorGradient, TimeSpan, HasDiscreteColors, true);
                            _elementData.Add(pulseData);
                            break;

                        case SpinColorHandling.GradientThroughWholeEffect:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new [] { level, level })), ColorGradient, TimeSpan, HasDiscreteColors, true);
                            _elementData.Add(pulseData);
                            break;

                        case SpinColorHandling.StaticColor:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new[] { level, level })), StaticColorGradient, TimeSpan, HasDiscreteColors, true);
                            _elementData.Add(pulseData);
                            break;

                        case SpinColorHandling.ColorAcrossItems:
                            double positionWithinGroup = i / (double)targetNodeCount;
                            if (discreteColors)
                            {
                                List <Tuple <Color, float> > colorsAtPosition =
                                    ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                                foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                                {
                                    double value = level * colorProportion.Item2;
                                    pulseData = PulseRenderer.RenderNode(target,
                                                                         new Curve(new PointPairList(new double[] { 0, 100 }, new [] { value, value })), new ColorGradient(colorProportion.Item1), TimeSpan, HasDiscreteColors, true);
                                    _elementData.Add(pulseData);
                                }
                            }
                            else
                            {
                                pulseData = PulseRenderer.RenderNode(target,
                                                                     new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { level, level })), new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup)), TimeSpan, HasDiscreteColors, true);
                                _elementData.Add(pulseData);
                            }
                            break;
                        }

                        i++;
                    }
                }
            }

            // calculate the pulse time and revolution time exactly (based on the parameters from the data)
            double revTimeMs = 0;             // single revolution time (ms)

            // figure out the relative length of a individual pulse
            double pulseConstant   = 0;           // how much of each pulse is a constant time
            double pulseFractional = 0;           // how much of each pulse is a fraction of a single spin

            if (PulseLengthFormat == SpinPulseLengthFormat.FixedTime)
            {
                pulseConstant = PulseTime;
            }
            else if (PulseLengthFormat == SpinPulseLengthFormat.PercentageOfRevolution)
            {
                pulseFractional = PulsePercentage / 100.0;
            }
            else if (PulseLengthFormat == SpinPulseLengthFormat.EvenlyDistributedAcrossSegments)
            {
                pulseFractional = 1.0 / (double)targetNodeCount;
            }

            // magic number. (the inaccuracy of interpolating the curve into a position. eg. if we have 5 'positions', then
            // the curve should really be from 0-80% for the last spin, to make sure the last pulse finishes accurately.)
            double pulseInterpolationOffset = 1.0 / (double)targetNodeCount;

            // figure out either the revolution count or time, based on what data we have
            if (SpeedFormat == SpinSpeedFormat.RevolutionCount)
            {
                revTimeMs = (TimeSpan.TotalMilliseconds - pulseConstant) /
                            (RevolutionCount + pulseFractional - pulseInterpolationOffset);
            }
            else if (SpeedFormat == SpinSpeedFormat.RevolutionFrequency)
            {
                revTimeMs = (1.0 / RevolutionFrequency) * 1000.0;             // convert Hz to period ms
            }
            else if (SpeedFormat == SpinSpeedFormat.FixedTime)
            {
                revTimeMs = RevolutionTime;
            }

            double pulTimeMs = pulseConstant + (revTimeMs * pulseFractional);

            TimeSpan revTimeSpan   = TimeSpan.FromMilliseconds(revTimeMs);
            TimeSpan pulseTimeSpan = TimeSpan.FromMilliseconds(pulTimeMs);

            // figure out which way we're moving through the elements
            Curve movement;

            if (ReverseSpin)
            {
                movement = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { 100, 0 }));
            }
            else
            {
                movement = new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { 0, 100 }));
            }

            //TODO: get a better increment time. doing it every X ms is..... shitty at best.
            //Less crappy is try to make some adjustment if there are a lot of nodes in a shorter time to sample more often.
            //A hard and fast 2ms was leaving gaps in larger node counts
            var sampleMs = revTimeSpan.TotalMilliseconds / targetNodeCount / 2.0;

            if (sampleMs < .25)
            {
                sampleMs = .25;
            }
            else if (sampleMs > 2)
            {
                sampleMs = 2;
            }
            TimeSpan increment = TimeSpan.FromTicks((long)(sampleMs * TimeSpan.TicksPerMillisecond));

            // iterate up to and including the last pulse generated
            // a bit iffy, but stops 'carry over' spins past the end (when there's overlapping spins). But we need to go past
            // (total - pulse) as the last pulse can often be a bit inaccurate due to the rounding of the increment
            for (TimeSpan current = TimeSpan.Zero; current <= TimeSpan - pulseTimeSpan + increment; current += increment)
            {
                if (tokenSource != null && tokenSource.IsCancellationRequested)
                {
                    return;
                }

                double currentPercentageIntoSpin = ((double)(current.Ticks % revTimeSpan.Ticks) / (double)revTimeSpan.Ticks) * 100.0;

                double targetElementPosition = movement.GetValue(currentPercentageIntoSpin);
                int    currentNodeIndex      = (int)((targetElementPosition / 100.0) * targetNodeCount);

                // on the off chance we hit the 100% mark *exactly*...
                if (currentNodeIndex == targetNodeCount)
                {
                    currentNodeIndex--;
                }

                if (currentNodeIndex >= targetNodeCount)
                {
                    Logging.Warn(
                        "Spin 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;
                }

                bool discreteColors = ColorModule.isElementNodeDiscreteColored(currentNode);

                // figure out what color gradient to use for the pulse
                switch (ColorHandling)
                {
                case SpinColorHandling.GradientForEachPulse:
                    pulseData = PulseRenderer.RenderNode(currentNode, new Curve(PulseCurve), ColorGradient, pulseTimeSpan, HasDiscreteColors);
                    pulseData.OffsetAllCommandsByTime(current);
                    _elementData.Add(pulseData);
                    break;

                case SpinColorHandling.GradientThroughWholeEffect:
                    double startPos = ((double)current.Ticks / (double)TimeSpan.Ticks);
                    double endPos   = 1.0;
                    if (TimeSpan - current >= pulseTimeSpan)
                    {
                        endPos = ((double)(current + pulseTimeSpan).Ticks / (double)TimeSpan.Ticks);
                    }

                    if (discreteColors)
                    {
                        double range = endPos - startPos;
                        if (range <= 0.0)
                        {
                            Logging.Error("Spin: bad range: " + range + " (SP=" + startPos + ", EP=" + endPos + ")");
                            break;
                        }

                        ColorGradient cg = ColorGradient.GetSubGradientWithDiscreteColors(startPos, endPos);

                        foreach (Color color in cg.GetColorsInGradient())
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            Curve newCurve = new Curve(PulseCurve.Points);
                            foreach (PointPair point in newCurve.Points)
                            {
                                double effectRelativePosition = startPos + ((point.X / 100.0) * range);
                                double proportion             = ColorGradient.GetProportionOfColorAt(effectRelativePosition, color);
                                point.Y *= proportion;
                            }
                            pulseData = PulseRenderer.RenderNode(currentNode, newCurve, new ColorGradient(color), pulseTimeSpan, HasDiscreteColors);
                            pulseData.OffsetAllCommandsByTime(current);
                            _elementData.Add(pulseData);
                        }
                    }
                    else
                    {
                        pulseData = PulseRenderer.RenderNode(currentNode, new Curve(PulseCurve), ColorGradient.GetSubGradient(startPos, endPos), pulseTimeSpan, HasDiscreteColors);
                        pulseData.OffsetAllCommandsByTime(current);
                        _elementData.Add(pulseData);
                    }
                    break;

                case SpinColorHandling.StaticColor:
                    pulseData = PulseRenderer.RenderNode(currentNode, new Curve(PulseCurve), StaticColorGradient, pulseTimeSpan, HasDiscreteColors);
                    pulseData.OffsetAllCommandsByTime(current);
                    _elementData.Add(pulseData);
                    break;

                case SpinColorHandling.ColorAcrossItems:
                    if (discreteColors)
                    {
                        List <Tuple <Color, float> > colorsAtPosition = ColorGradient.GetDiscreteColorsAndProportionsAt(targetElementPosition / 100.0);
                        foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }

                            float proportion = colorProportion.Item2;
                            // scale all levels of the pulse curve by the proportion that is applicable to this color

                            Curve newCurve = new Curve(PulseCurve.Points);
                            foreach (PointPair pointPair in newCurve.Points)
                            {
                                pointPair.Y *= proportion;
                            }
                            pulseData = PulseRenderer.RenderNode(currentNode, newCurve, new ColorGradient(colorProportion.Item1), pulseTimeSpan, HasDiscreteColors);
                            pulseData.OffsetAllCommandsByTime(current);
                            _elementData.Add(pulseData);
                        }
                    }
                    else
                    {
                        pulseData = PulseRenderer.RenderNode(currentNode, new Curve(PulseCurve), new ColorGradient(ColorGradient.GetColorAt(targetElementPosition / 100.0)), pulseTimeSpan, HasDiscreteColors);
                        pulseData.OffsetAllCommandsByTime(current);
                        _elementData.Add(pulseData);
                    }
                    break;
                }

                lastTargetedNode = currentNode;
            }

            _elementData = EffectIntents.Restrict(_elementData, TimeSpan.Zero, TimeSpan);
        }
Exemple #4
0
        private EffectIntents RenderElement(ElementNode node, double positionWithinGroup, bool discreteColors,
                                            List <IndividualTwinkleDetails> twinkles = null)
        {
            if (twinkles == null)
            {
                twinkles = GenerateTwinkleData();
            }

            EffectIntents result = new EffectIntents();

            // render the flat 'minimum value' across the entire effect
            //Pulse.Pulse pulse = new Pulse.Pulse();
            //pulse.TargetNodes = new ElementNode[] {node};
            //pulse.TimeSpan = TimeSpan;

            double        minPulseValue = MinimumLevel * 100.0;
            EffectIntents pulseData;

            // figure out what color gradient to use for the pulse
            if (MinimumLevel > 0.0)
            {
                switch (ColorHandling)
                {
                case TwinkleColorHandling.GradientForEachPulse:
                    if (discreteColors)
                    {
                        List <Tuple <Color, float> > colorProportions = ColorGradient.GetDiscreteColorsAndProportionsAt(0);
                        foreach (Tuple <Color, float> colorProportion in colorProportions)
                        {
                            double value = minPulseValue * colorProportion.Item2;
                            //pulse.LevelCurve = new Curve(new PointPairList(new double[] {0, 100}, new [] {value, value}));
                            //pulse.ColorGradient = new ColorGradient(colorProportion.Item1);
                            //pulseData = pulse.Render();
                            pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new[] { value, value })), new ColorGradient(colorProportion.Item1), TimeSpan, HasDiscreteColors);
                            result.Add(pulseData);
                        }
                    }
                    else
                    {
                        //pulse.LevelCurve = new Curve(new PointPairList(new double[] {0, 100}, new double[] {minPulseValue, minPulseValue}));
                        //pulse.ColorGradient = new ColorGradient(ColorGradient.GetColorAt(0));
                        //pulseData = pulse.Render();
                        pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { minPulseValue, minPulseValue })), new ColorGradient(ColorGradient.GetColorAt(0)), TimeSpan, HasDiscreteColors);
                        result.Add(pulseData);
                    }
                    break;

                case TwinkleColorHandling.GradientThroughWholeEffect:
                    //pulse.LevelCurve = new Curve(new PointPairList(new double[] {0, 100}, new double[] {minPulseValue, minPulseValue}));
                    //pulse.ColorGradient = ColorGradient;
                    //pulseData = pulse.Render();
                    pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new [] { minPulseValue, minPulseValue })), ColorGradient, TimeSpan, HasDiscreteColors);
                    result.Add(pulseData);
                    break;

                case TwinkleColorHandling.StaticColor:
                    //pulse.LevelCurve = new Curve(new PointPairList(new double[] {0, 100}, new double[] {minPulseValue, minPulseValue}));
                    //pulse.ColorGradient = StaticColorGradient;
                    //pulseData = pulse.Render();
                    pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new [] { minPulseValue, minPulseValue })), StaticColorGradient, TimeSpan, HasDiscreteColors);
                    result.Add(pulseData);
                    break;

                case TwinkleColorHandling.ColorAcrossItems:
                    if (discreteColors)
                    {
                        List <Tuple <Color, float> > colorsAtPosition = ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                        foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                        {
                            double value = minPulseValue * 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();
                            pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new[] { value, value })), new ColorGradient(colorProportion.Item1), TimeSpan, HasDiscreteColors);
                            result.Add(pulseData);
                        }
                    }
                    else
                    {
                        //pulse.LevelCurve = new Curve(new PointPairList(new double[] {0, 100}, new double[] {minPulseValue, minPulseValue}));
                        //pulse.ColorGradient = new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup));
                        //pulseData = pulse.Render();
                        pulseData = PulseRenderer.RenderNode(node, new Curve(new PointPairList(new double[] { 0, 100 }, new double[] { minPulseValue, minPulseValue })), new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup)), TimeSpan, HasDiscreteColors);
                        result.Add(pulseData);
                    }
                    break;
                }
            }

            // render all the individual twinkles
            foreach (IndividualTwinkleDetails twinkle in twinkles)
            {
                {
                    // make a pulse for it

                    //pulse.TargetNodes = new [] {node};
                    //pulse.TimeSpan = twinkle.Duration;
                    //pulse.LevelCurve = new Curve(new PointPairList(new double[] { 0, 50, 100 }, new [] { twinkle.curvePoints[0], twinkle.curvePoints[1], twinkle.curvePoints[2] }));
                    var curve = new Curve(new PointPairList(new double[] { 0, 50, 100 }, new[] { twinkle.curvePoints[0], twinkle.curvePoints[1], twinkle.curvePoints[2] }));
                    // figure out what color gradient to use for the pulse
                    switch (ColorHandling)
                    {
                    case TwinkleColorHandling.GradientForEachPulse:
                        //pulse.ColorGradient = ColorGradient;
                        //pulseData = pulse.Render();
                        pulseData = PulseRenderer.RenderNode(node, curve, ColorGradient, twinkle.Duration, HasDiscreteColors);
                        pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                        result.Add(pulseData);
                        break;

                    case TwinkleColorHandling.GradientThroughWholeEffect:
                        double startPos = (twinkle.StartTime.Ticks / (double)TimeSpan.Ticks);
                        double endPos   = ((twinkle.StartTime + twinkle.Duration).Ticks / (double)TimeSpan.Ticks);

                        if (discreteColors)
                        {
                            double range = endPos - startPos;
                            if (range <= 0.0)
                            {
                                Logging.Error("Twinkle: bad range: " + range + " (SP=" + startPos + ", EP=" + endPos + ")");
                                break;
                            }

                            ColorGradient cg = ColorGradient.GetSubGradientWithDiscreteColors(startPos, endPos);

                            foreach (Color color in cg.GetColorsInGradient())
                            {
                                curve = new Curve(curve.Points);
                                foreach (PointPair point in curve.Points)
                                {
                                    double effectRelativePosition = startPos + ((point.X / 100.0) * range);
                                    double proportion             = ColorGradient.GetProportionOfColorAt(effectRelativePosition, color);
                                    point.Y *= proportion;
                                }
                                //pulse.LevelCurve = newCurve;
                                //pulse.ColorGradient = new ColorGradient(color);
                                //pulseData = pulse.Render();
                                pulseData = PulseRenderer.RenderNode(node, curve, new ColorGradient(color), twinkle.Duration, HasDiscreteColors);
                                pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                                result.Add(pulseData);
                            }
                        }
                        else
                        {
                            //pulse.ColorGradient = ColorGradient.GetSubGradient(startPos, endPos);
                            //pulseData = pulse.Render();
                            pulseData = PulseRenderer.RenderNode(node, curve, ColorGradient.GetSubGradient(startPos, endPos), twinkle.Duration, HasDiscreteColors);
                            pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                            result.Add(pulseData);
                        }
                        break;

                    case TwinkleColorHandling.StaticColor:
                        //pulse.ColorGradient = StaticColorGradient;
                        //pulseData = pulse.Render();
                        pulseData = PulseRenderer.RenderNode(node, curve, StaticColorGradient, twinkle.Duration, HasDiscreteColors);
                        pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                        result.Add(pulseData);
                        break;

                    case TwinkleColorHandling.ColorAcrossItems:
                        if (discreteColors)
                        {
                            List <Tuple <Color, float> > colorsAtPosition = ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                            foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                            {
                                float proportion = colorProportion.Item2;
                                // scale all levels of the twinkle curve by the proportion that is applicable to this color
                                curve = new Curve(curve.Points);
                                foreach (PointPair pointPair in curve.Points)
                                {
                                    pointPair.Y *= proportion;
                                }
                                //pulse.LevelCurve = newCurve;
                                //pulse.ColorGradient = new ColorGradient(colorProportion.Item1);
                                //pulseData = pulse.Render();
                                pulseData = PulseRenderer.RenderNode(node, curve, new ColorGradient(colorProportion.Item1), twinkle.Duration, HasDiscreteColors);
                                pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                                result.Add(pulseData);
                            }
                        }
                        else
                        {
                            //pulse.ColorGradient = new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup));
                            //pulseData = pulse.Render();
                            pulseData = PulseRenderer.RenderNode(node, curve, new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup)), twinkle.Duration, HasDiscreteColors);
                            pulseData.OffsetAllCommandsByTime(twinkle.StartTime);
                            result.Add(pulseData);
                        }
                        break;
                    }
                }
            }

            return(result);
        }
Exemple #5
0
        private void RenderMovement(List <IElementNode[]> renderNodes, CancellationTokenSource tokenSource)
        {
            double   previousMovement = 2.0;
            TimeSpan startTime        = TimeSpan.Zero;
            TimeSpan timeInterval     = TimeSpan.FromMilliseconds(_timeInterval);
            int      intervals        = Convert.ToInt32(Math.Ceiling(TimeSpan.TotalMilliseconds / _timeInterval));
            int      burst            = Direction != WipeDirection.DiagonalUp ? 0 : _pulsePercent - 1;

            List <WipeClass> renderElements = new List <WipeClass>();

            for (int i = 0; i < intervals; i++)
            {
                double position = (double)100 / intervals * i;
                double movement = MovementCurve.GetValue(position) / 100;
                if (previousMovement != movement)
                {
                    if (renderElements.Count > 0)
                    {
                        renderElements.Last().Duration = startTime - renderElements.Last().StartTime;
                    }

                    WipeClass wc = new WipeClass
                    {
                        ElementIndex = (int)((renderNodes.Count - 1) * movement),
                        StartTime    = startTime,
                        Duration     = TimeSpan - startTime
                    };

                    if (ReverseColorDirection)
                    {
                        wc.ReverseColorDirection = previousMovement < movement ? 0 : 1;
                    }

                    renderElements.Add(wc);
                }

                previousMovement = movement;
                startTime       += timeInterval;
            }
            double pos = ((double)100 / _pulsePercent) / 100;

            // Now render element
            foreach (var wipeNode in renderElements)
            {
                for (int i = 0; i < _pulsePercent; i++)
                {
                    double position = wipeNode.ReverseColorDirection - pos * i;
                    if (position < 0)
                    {
                        position = -position;
                    }
                    Color  color      = _data.ColorGradient.GetColorAt(position);
                    double curveValue = _data.Curve.GetValue(position * 100) / 100;

                    if (wipeNode.ElementIndex - i > 0 && wipeNode.ElementIndex - i + burst < renderNodes.Count)
                    {
                        IElementNode[] elementGroup = renderNodes[wipeNode.ElementIndex - i + burst];
                        if (tokenSource != null && tokenSource.IsCancellationRequested)
                        {
                            return;
                        }

                        foreach (var item in elementGroup)
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            if (item != null)
                            {
                                var result = PulseRenderer.RenderNode(item, curveValue, color, wipeNode.Duration);
                                result.OffsetAllCommandsByTime(wipeNode.StartTime);
                                _elementData.Add(result);
                            }
                        }
                    }
                }
            }
        }
Exemple #6
0
        private void RenderCount(List <IElementNode[]> renderNodes, CancellationTokenSource tokenSource)
        {
            TimeSpan effectTime   = TimeSpan.Zero;
            int      count        = 0;
            double   pulseSegment = (TimeSpan.Ticks * ((PulsePercent * ((double)_steps / renderNodes.Count())) / 100)) / PassCount;
            TimeSpan intervalTime = TimeSpan.FromTicks((long)((TimeSpan.Ticks - pulseSegment) / (renderNodes.Count() * PassCount)));
            TimeSpan segmentPulse = TimeSpan.FromTicks((long)pulseSegment);

            while (count < PassCount)
            {
                foreach (IElementNode[] item in renderNodes)
                {
                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    foreach (IElementNode element in item)
                    {
                        if (tokenSource != null && tokenSource.IsCancellationRequested)
                        {
                            return;
                        }
                        if (element == null)
                        {
                            continue;
                        }

                        EffectIntents result;
                        if (ColorHandling == ColorHandling.GradientThroughWholeEffect)
                        {
                            result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse,
                                                              HasDiscreteColors);
                            result.OffsetAllCommandsByTime(effectTime);
                            if (WipeOff && count == 0 && result.Any())
                            {
                                foreach (var effectIntent in result.FirstOrDefault().Value)
                                {
                                    _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element, effectIntent,
                                                                                               HasDiscreteColors));
                                }
                            }

                            if (WipeOn && result.Any() && count == PassCount - 1)
                            {
                                foreach (var effectIntent in result.FirstOrDefault().Value)
                                {
                                    _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element, effectIntent,
                                                                                               TimeSpan, HasDiscreteColors));
                                }
                            }

                            _elementData.Add(result);
                        }
                        else
                        {
                            double positionWithinGroup = (double)(1.0 / (TimeSpan.Ticks - segmentPulse.Ticks)) * (effectTime.Ticks);
                            if (ColorAcrossItemPerCount)
                            {
                                positionWithinGroup = positionWithinGroup * PassCount % 1;
                            }
                            if (HasDiscreteColors)
                            {
                                List <Tuple <Color, float> > colorsAtPosition =
                                    ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                                foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                                {
                                    float proportion = colorProportion.Item2;
                                    // scale all levels of the pulse curve by the proportion that is applicable to this color
                                    Curve newCurve = new Curve(Curve.Points);
                                    foreach (PointPair pointPair in newCurve.Points)
                                    {
                                        pointPair.Y *= proportion;
                                    }

                                    result = PulseRenderer.RenderNode(element, newCurve,
                                                                      new ColorGradient(colorProportion.Item1), segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);

                                    if (WipeOff && count == 0)
                                    {
                                        foreach (var effectIntent in result.FirstOrDefault().Value)
                                        {
                                            _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element,
                                                                                                       effectIntent, HasDiscreteColors,
                                                                                                       new ColorGradient(colorProportion.Item1)));
                                        }
                                    }

                                    if (result.Count > 0)
                                    {
                                        _elementData.Add(result);
                                    }

                                    if (WipeOn && count == PassCount - 1)
                                    {
                                        foreach (var effectIntent in result.FirstOrDefault().Value)
                                        {
                                            _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element,
                                                                                                       effectIntent, TimeSpan, HasDiscreteColors,
                                                                                                       new ColorGradient(colorProportion.Item1)));
                                        }
                                    }
                                }
                            }
                            else
                            {
                                result = PulseRenderer.RenderNode(element, _data.Curve,
                                                                  new ColorGradient(_data.ColorGradient.GetColorAt(positionWithinGroup)),
                                                                  segmentPulse, HasDiscreteColors);
                                result.OffsetAllCommandsByTime(effectTime);

                                if (WipeOff && count == 0)
                                {
                                    foreach (var effectIntent in result.FirstOrDefault().Value)
                                    {
                                        _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element,
                                                                                                   effectIntent, HasDiscreteColors));
                                    }
                                }

                                if (WipeOn && count == PassCount - 1)
                                {
                                    foreach (var effectIntent in result.FirstOrDefault().Value)
                                    {
                                        _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element,
                                                                                                   effectIntent, TimeSpan, HasDiscreteColors));
                                    }
                                }
                                _elementData.Add(result);
                            }
                        }
                    }
                    effectTime += intervalTime;
                }
                count++;
            }
        }
Exemple #7
0
        private void RenderPulseLength(List <IElementNode[]> renderNodes, CancellationTokenSource tokenSource)
        {
            TimeSpan effectTime   = TimeSpan.Zero;
            double   intervals    = (double)PulseTime / renderNodes.Count();
            var      intervalTime = TimeSpan.FromMilliseconds(intervals);

            // the calculation above blows up render time/memory as count goes up, try this..
            // also fails if intervals is less than half a ms and intervalTime then gets 0
            intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5));
            TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime);

            while (effectTime < TimeSpan)
            {
                foreach (var item in renderNodes)
                {
                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                    {
                        return;
                    }
                    foreach (IElementNode element in item)
                    {
                        if (tokenSource != null && tokenSource.IsCancellationRequested)
                        {
                            return;
                        }
                        if (element == null)
                        {
                            continue;
                        }

                        EffectIntents result;
                        if (ColorHandling == ColorHandling.GradientThroughWholeEffect)
                        {
                            result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse,
                                                              HasDiscreteColors);
                            result.OffsetAllCommandsByTime(effectTime);

                            _elementData.Add(result);
                        }
                        else
                        {
                            double positionWithinGroup = (double)(1.0 / (TimeSpan.Ticks - segmentPulse.Ticks)) * (effectTime.Ticks);
                            if (ColorAcrossItemPerCount)
                            {
                                positionWithinGroup = positionWithinGroup * PassCount % 1;
                            }
                            if (HasDiscreteColors)
                            {
                                List <Tuple <Color, float> > colorsAtPosition =
                                    ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                                foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                                {
                                    float proportion = colorProportion.Item2;
                                    // scale all levels of the pulse curve by the proportion that is applicable to this color
                                    Curve newCurve = new Curve(Curve.Points);
                                    foreach (PointPair pointPair in newCurve.Points)
                                    {
                                        pointPair.Y *= proportion;
                                    }

                                    result = PulseRenderer.RenderNode(element, newCurve,
                                                                      new ColorGradient(colorProportion.Item1), segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                }
                            }
                            else
                            {
                                result = PulseRenderer.RenderNode(element, _data.Curve,
                                                                  new ColorGradient(_data.ColorGradient.GetColorAt(positionWithinGroup)),
                                                                  segmentPulse, HasDiscreteColors);
                                result.OffsetAllCommandsByTime(effectTime);

                                _elementData.Add(result);
                            }
                        }
                    }
                    effectTime += intervalTime;
                    if (effectTime >= TimeSpan)
                    {
                        return;
                    }
                }
            }
        }
Exemple #8
0
        private void RenderBurst(CancellationTokenSource tokenSource, WipeDirection direction)
        {
            switch (direction)
            {
            case WipeDirection.In:
            case WipeDirection.Out:
                break;

            default:
                throw new InvalidOperationException("the RenderBurst method should only be called for Wipe Directions In and Out");
                break;
            }
            var burstNodes = TargetNodes.SelectMany(x => x.GetLeafEnumerator())
                             .Select(s =>
            {
                var prop = s.Properties.Get(LocationDescriptor._typeId);
                if (prop != null)
                {
                    return(new Tuple <ElementNode, int, int, int>(s, ((LocationData)prop.ModuleData).X, ((LocationData)prop.ModuleData).Y, ((LocationData)prop.ModuleData).Z));
                }
                return(new Tuple <ElementNode, int, int, int>(null, -1, -1, -1));
                //return null
            })
                             .Where(s => s.Item2 > 0)                                                                               // Ignore the pseudo null values
                             .ToList();

            if (!burstNodes.Any())
            {
                return;
            }
            var maxX = burstNodes.Max(m => m.Item2);
            var maxY = burstNodes.Max(m => m.Item3);

            var minX = burstNodes.Min(m => m.Item2);
            var minY = burstNodes.Min(m => m.Item3);

            var Steps = (int)(Math.Max(maxX - minX, maxY - minY) / 2);

            List <Tuple <int, ElementNode[]> > groups = new List <Tuple <int, ElementNode[]> >();

            for (int i = 0; i < Steps; i++)
            {
                List <ElementNode> elements = new List <ElementNode>();

                var xNodes = burstNodes.Where(x =>
                                              (x.Item2 == minX + i || x.Item2 == maxX - i)
                                              )
                             .Select(s => s.Item1).ToList();

                var yNodes = burstNodes.Where(x =>
                                              (
                                                  x.Item3 == minY + i ||
                                                  x.Item3 == maxY - i)
                                              )
                             .Select(s => s.Item1).ToList();
                yNodes.RemoveAll(s =>
                {
                    var prop = s.Properties.Get(LocationDescriptor._typeId);
                    if (prop != null)
                    {
                        return(((LocationData)prop.ModuleData).X < minX + i || ((LocationData)prop.ModuleData).X > maxX - i);
                    }
                    return(false);
                });
                xNodes.RemoveAll(s =>
                {
                    var prop = s.Properties.Get(LocationDescriptor._typeId);
                    if (prop != null)
                    {
                        return(((LocationData)prop.ModuleData).Y < minY + i || ((LocationData)prop.ModuleData).Y > maxY - i);
                    }
                    return(false);
                });
                elements.AddRange(yNodes);
                elements.AddRange(xNodes);

                groups.Add(new Tuple <int, ElementNode[]>(i, elements.ToArray()));
            }
            List <ElementNode[]> renderNodes = new List <ElementNode[]>();

            switch (direction)
            {
            case WipeDirection.In:
                renderNodes = groups.OrderBy(o => o.Item1).Select(s => s.Item2).ToList();
                break;

            case WipeDirection.Out:
                renderNodes = groups.OrderByDescending(o => o.Item1).Select(s => s.Item2).ToList();
                break;
            }

            //var pulse = new Pulse.Pulse();
            if (renderNodes != null && renderNodes.Any())
            {
                TimeSpan effectTime = TimeSpan.Zero;
                if (WipeByCount)
                {
                    int      count        = 0;
                    double   pulseSegment = TimeSpan.Ticks / (double)PassCount * (PulsePercent / 100);
                    TimeSpan intervalTime = TimeSpan.FromTicks((long)((TimeSpan.Ticks - pulseSegment) / (renderNodes.Count() * PassCount)));
                    TimeSpan segmentPulse = TimeSpan.FromTicks((long)pulseSegment);

                    while (count < PassCount)
                    {
                        foreach (var item in renderNodes)
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            EffectIntents result;

                            foreach (ElementNode element in item)
                            {
                                if (tokenSource != null && tokenSource.IsCancellationRequested)
                                {
                                    return;
                                }
                                if (element != null)
                                {
                                    //pulse.TimeSpan = segmentPulse;
                                    //pulse.ColorGradient = _data.ColorGradient;
                                    //pulse.LevelCurve = _data.Curve;
                                    //pulse.TargetNodes = new ElementNode[] { element };
                                    //result = pulse.Render();
                                    result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                    bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element);
                                    _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement));
                                }
                            }
                            effectTime += intervalTime;
                        }
                        count++;
                    }
                }
                else
                {
                    double intervals    = (double)PulseTime / (double)renderNodes.Count();
                    var    intervalTime = TimeSpan.FromMilliseconds(intervals);
                    // the calculation above blows up render time/memory as count goes up, try this..
                    // also fails if intervals is less than half a ms and intervalTime then gets 0
                    intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5));
                    TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime);
                    while (effectTime < TimeSpan)
                    {
                        foreach (var item in renderNodes)
                        {
                            EffectIntents result;

                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            foreach (ElementNode element in item)
                            {
                                if (element != null)
                                {
                                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                                    {
                                        return;
                                    }

                                    //pulse.TimeSpan = segmentPulse;
                                    //pulse.ColorGradient = _data.ColorGradient;
                                    //pulse.LevelCurve = _data.Curve;
                                    //pulse.TargetNodes = new ElementNode[] { element };
                                    //result = pulse.Render();
                                    result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                    bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element);
                                    _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement));
                                }
                            }
                            effectTime += intervalTime;
                            if (effectTime >= TimeSpan)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
Exemple #9
0
        private void RenderNonBurst(CancellationTokenSource tokenSource, IEnumerable <IGrouping <int, ElementNode> > renderNodes)
        {
            //var pulse = new Pulse.Pulse();
            if (renderNodes != null && renderNodes.Any())
            {
                TimeSpan effectTime = TimeSpan.Zero;
                if (WipeByCount)
                {
                    int      count        = 0;
                    double   pulseSegment = TimeSpan.Ticks / (double)PassCount * (PulsePercent / 100);
                    TimeSpan intervalTime = TimeSpan.FromTicks((long)((TimeSpan.Ticks - pulseSegment) / (renderNodes.Count() * PassCount)));
                    TimeSpan segmentPulse = TimeSpan.FromTicks((long)pulseSegment);

                    while (count < PassCount)
                    {
                        foreach (var item in renderNodes)
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            EffectIntents result;

                            foreach (ElementNode element in item)
                            {
                                if (tokenSource != null && tokenSource.IsCancellationRequested)
                                {
                                    return;
                                }
                                if (element != null)
                                {
                                    //pulse.TimeSpan = segmentPulse;
                                    //pulse.ColorGradient = _data.ColorGradient;
                                    //pulse.LevelCurve = _data.Curve;
                                    //pulse.TargetNodes = new ElementNode[] { element };
                                    //result = pulse.Render();
                                    result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                    bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element);
                                    _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement));
                                }
                            }
                            effectTime += intervalTime;
                        }
                        count++;
                    }
                }
                else
                {
                    double intervals    = (double)PulseTime / (double)renderNodes.Count();
                    var    intervalTime = TimeSpan.FromMilliseconds(intervals);
                    // the calculation above blows up render time/memory as count goes up, try this..
                    // also fails if intervals is less than half a ms and intervalTime then gets 0
                    intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5));
                    TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime);
                    while (effectTime < TimeSpan)
                    {
                        foreach (var item in renderNodes)
                        {
                            EffectIntents result;

                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }
                            foreach (ElementNode element in item)
                            {
                                if (element != null)
                                {
                                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                                    {
                                        return;
                                    }
                                    //pulse.TimeSpan = segmentPulse;
                                    //pulse.ColorGradient = _data.ColorGradient;
                                    //pulse.LevelCurve = _data.Curve;
                                    //pulse.TargetNodes = new ElementNode[] { element };
                                    //result = pulse.Render();
                                    result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                    bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element);
                                    _elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement));
                                }
                            }
                            effectTime += intervalTime;
                            if (effectTime >= TimeSpan)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
Exemple #10
0
        //private void GenerateExtendedStaticPulse(ElementNode target, IIntentNode intentNode, ColorGradient gradient=null)
        //{
        //	if (intentNode == null || intentNode.EndTime >= TimeSpan) return;
        //	var lightingIntent = intentNode.Intent as LightingIntent;
        //	if (lightingIntent != null && lightingIntent.EndValue.Intensity > 0)
        //	{
        //		var newCurve = new Curve(lightingIntent.EndValue.Intensity*100);
        //		GenerateExtendedStaticPulse(target, newCurve, gradient ?? new ColorGradient(lightingIntent.EndValue.FullColor),
        //			TimeSpan - intentNode.EndTime, intentNode.EndTime);
        //	}
        //	else
        //	{
        //		var discreteIntent = intentNode.Intent as DiscreteLightingIntent;
        //		if (discreteIntent != null && discreteIntent.EndValue.Intensity > 0)
        //		{
        //			var newCurve = new Curve(discreteIntent.EndValue.Intensity*100);
        //			GenerateExtendedStaticPulse(target, newCurve, gradient ?? new ColorGradient(discreteIntent.EndValue.FullColor),
        //				TimeSpan - intentNode.EndTime, intentNode.EndTime);
        //		}
        //	}
        //}

        //private void GenerateExtendedStaticPulse(ElementNode target, Curve newCurve, ColorGradient gradient, TimeSpan duration, TimeSpan offset)
        //{
        //	var result = PulseRenderer.RenderNode(target, newCurve, gradient, duration, HasDiscreteColors);
        //	result.OffsetAllCommandsByTime(offset);
        //	_elementData.Add(result);
        //}

        //private void GenerateStartingStaticPulse(ElementNode target, IIntentNode intentNode, ColorGradient gradient=null)
        //{
        //	if (intentNode == null || intentNode.StartTime <= TimeSpan.Zero) return;
        //	var lightingIntent = intentNode.Intent as LightingIntent;
        //	if (lightingIntent != null && lightingIntent.StartValue.Intensity > 0)
        //	{
        //		var newCurve = new Curve(lightingIntent.StartValue.Intensity*100);
        //		GenerateStartingStaticPulse(target,newCurve, gradient ?? new ColorGradient(lightingIntent.StartValue.FullColor), intentNode.StartTime);
        //	}
        //	else
        //	{
        //		var discreteIntent = intentNode.Intent as DiscreteLightingIntent;
        //		if (discreteIntent != null && discreteIntent.StartValue.Intensity > 0)
        //		{
        //			var newCurve = new Curve(discreteIntent.StartValue.Intensity*100);
        //			GenerateStartingStaticPulse(target, newCurve, gradient ?? new ColorGradient(discreteIntent.StartValue.FullColor),
        //				intentNode.StartTime);
        //		}
        //	}
        //}

        //private void GenerateStartingStaticPulse(ElementNode target, Curve newCurve, ColorGradient gradient, TimeSpan time)
        //{
        //	var result = PulseRenderer.RenderNode(target, newCurve, gradient, time, HasDiscreteColors);
        //	_elementData.Add(result);
        //}

        private void GeneratePulse(ElementNode target, TimeSpan startTime, TimeSpan duration, double currentMovementPosition)
        {
            EffectIntents result = null;

            // figure out what color gradient to use for the pulse
            switch (ColorHandling)
            {
            case ChaseColorHandling.GradientForEachPulse:
                result = PulseRenderer.RenderNode(target, PulseCurve, ColorGradient, duration, HasDiscreteColors);
                result.OffsetAllCommandsByTime(startTime);
                if (ExtendPulseToStart && result.Count > 0)
                {
                    foreach (var effectIntent in result.FirstOrDefault().Value)
                    {
                        _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, effectIntent, HasDiscreteColors));
                    }
                }
                _elementData.Add(result);
                if (ExtendPulseToEnd && result.Count > 0)
                {
                    foreach (var effectIntent in result.FirstOrDefault().Value)
                    {
                        _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, effectIntent, TimeSpan, HasDiscreteColors));
                    }
                }
                break;

            case ChaseColorHandling.GradientThroughWholeEffect:
                double startPos = (startTime.Ticks / (double)TimeSpan.Ticks);
                double endPos   = ((startTime + duration).Ticks / (double)TimeSpan.Ticks);
                if (startPos < 0.0)
                {
                    startPos = 0.0;
                }
                if (endPos > 1.0)
                {
                    endPos = 1.0;
                }

                if (HasDiscreteColors)
                {
                    double range = endPos - startPos;
                    if (range <= 0.0)
                    {
                        Logging.Error("Chase: bad range: " + range + " (SP=" + startPos + ", EP=" + endPos + ")");
                        break;
                    }

                    ColorGradient cg = ColorGradient.GetSubGradientWithDiscreteColors(startPos, endPos);

                    foreach (Color color in cg.GetColorsInGradient())
                    {
                        Curve newCurve = new Curve(PulseCurve.Points);
                        foreach (PointPair point in newCurve.Points)
                        {
                            double effectRelativePosition = startPos + ((point.X / 100.0) * range);
                            double proportion             = ColorGradient.GetProportionOfColorAt(effectRelativePosition, color);
                            point.Y *= proportion;
                        }
                        result = PulseRenderer.RenderNode(target, newCurve, new ColorGradient(color), duration, HasDiscreteColors);
                        result.OffsetAllCommandsByTime(startTime);
                        if (ExtendPulseToStart && result.Count > 0)
                        {
                            foreach (var effectIntent in result.FirstOrDefault().Value)
                            {
                                _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, effectIntent, HasDiscreteColors, new ColorGradient(color)));
                            }
                        }
                        if (result.Count > 0)
                        {
                            _elementData.Add(result);
                        }
                        if (ExtendPulseToEnd && result.Count > 0)
                        {
                            foreach (var effectIntent in result.FirstOrDefault().Value)
                            {
                                _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, effectIntent, TimeSpan, HasDiscreteColors, new ColorGradient(color)));
                            }
                        }
                    }
                }
                else
                {
                    result = PulseRenderer.RenderNode(target, PulseCurve, ColorGradient.GetSubGradient(startPos, endPos), duration, HasDiscreteColors);
                    result.OffsetAllCommandsByTime(startTime);
                    if (ExtendPulseToStart && result.Count > 0)
                    {
                        foreach (var effectIntent in result.FirstOrDefault().Value)
                        {
                            _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, effectIntent, HasDiscreteColors, ColorGradient.GetSubGradient(0, startPos)));
                        }
                    }
                    _elementData.Add(result);
                    if (ExtendPulseToEnd && result.Count > 0)
                    {
                        foreach (var effectIntent in result.FirstOrDefault().Value)
                        {
                            _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, effectIntent, TimeSpan, HasDiscreteColors, ColorGradient.GetSubGradient(endPos, 1)));
                        }
                    }
                }

                break;

            case ChaseColorHandling.StaticColor:
                result = PulseRenderer.RenderNode(target, PulseCurve, StaticColorGradient, duration, HasDiscreteColors);
                result.OffsetAllCommandsByTime(startTime);
                if (ExtendPulseToStart && result.Count > 0)
                {
                    var intent = result.FirstOrDefault().Value.FirstOrDefault();
                    _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, intent, HasDiscreteColors));
                }
                _elementData.Add(result);
                if (ExtendPulseToEnd && result.Count > 0)
                {
                    var intent = result.FirstOrDefault().Value.LastOrDefault();
                    _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, intent, TimeSpan, HasDiscreteColors));
                }
                break;

            case ChaseColorHandling.ColorAcrossItems:
                if (HasDiscreteColors)
                {
                    List <Tuple <Color, float> > colorsAtPosition = ColorGradient.GetDiscreteColorsAndProportionsAt(currentMovementPosition / 100.0);
                    foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                    {
                        float proportion = colorProportion.Item2;
                        // scale all levels of the pulse curve by the proportion that is applicable to this color
                        Curve newCurve = new Curve(PulseCurve.Points);
                        foreach (PointPair pointPair in newCurve.Points)
                        {
                            pointPair.Y *= proportion;
                        }
                        result = PulseRenderer.RenderNode(target, newCurve, new ColorGradient(colorProportion.Item1), duration, HasDiscreteColors);
                        result.OffsetAllCommandsByTime(startTime);
                        if (ExtendPulseToStart && result.Count > 0)
                        {
                            foreach (var effectIntent in result.FirstOrDefault().Value)
                            {
                                _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, effectIntent, HasDiscreteColors, new ColorGradient(colorProportion.Item1)));
                            }
                        }
                        if (result.Count > 0)
                        {
                            _elementData.Add(result);
                        }
                        if (ExtendPulseToEnd && result.Count > 0)
                        {
                            foreach (var effectIntent in result.FirstOrDefault().Value)
                            {
                                _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, effectIntent, TimeSpan, HasDiscreteColors, new ColorGradient(colorProportion.Item1)));
                            }
                        }
                    }
                }
                else
                {
                    result = PulseRenderer.RenderNode(target, PulseCurve, new ColorGradient(ColorGradient.GetColorAt(currentMovementPosition / 100.0)), duration, HasDiscreteColors);
                    result.OffsetAllCommandsByTime(startTime);
                    if (ExtendPulseToStart && result.Count > 0)
                    {
                        foreach (var effectIntent in result.FirstOrDefault().Value)
                        {
                            _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(target, effectIntent, HasDiscreteColors));
                        }
                    }
                    _elementData.Add(result);
                    if (ExtendPulseToEnd && result.Count > 0)
                    {
                        foreach (var effectIntent in result.FirstOrDefault().Value)
                        {
                            _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(target, effectIntent, TimeSpan, HasDiscreteColors));
                        }
                    }
                }
                break;
            }
        }
Exemple #11
0
        private void DoRendering(CancellationTokenSource tokenSource = null)
        {
            List <ElementNode> renderNodes = GetNodesToRenderOn();

            int targetNodeCount = renderNodes.Count;

            // apply the 'background' values to all targets if the level is supposed to be enabled
            if (EnableDefaultLevel)
            {
                int i = 0;
                foreach (ElementNode target in renderNodes)
                {
                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    if (target != null)
                    {
                        bool discreteColors = ColorModule.isElementNodeDiscreteColored(target);

                        double level = DefaultLevel * 100.0;

                        // figure out what color gradient to use for the pulse
                        EffectIntents pulseData;
                        switch (ColorHandling)
                        {
                        case ChaseColorHandling.GradientForEachPulse:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new[] { level, level })), StaticColorGradient, TimeSpan, HasDiscreteColors, true);
                            _elementData.Add(pulseData);
                            break;

                        case ChaseColorHandling.GradientThroughWholeEffect:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new[] { level, level })), ColorGradient, TimeSpan, HasDiscreteColors, true);
                            _elementData.Add(pulseData);
                            break;

                        case ChaseColorHandling.StaticColor:
                            pulseData = PulseRenderer.RenderNode(target,
                                                                 new Curve(new PointPairList(new double[] { 0, 100 }, new[] { level, level })), StaticColorGradient, TimeSpan, HasDiscreteColors, true);
                            _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;
                                    pulseData = PulseRenderer.RenderNode(target,
                                                                         new Curve(new PointPairList(new double[] { 0, 100 }, new[] { value, value })), new ColorGradient(colorProportion.Item1), TimeSpan, HasDiscreteColors, true);
                                    _elementData.Add(pulseData);
                                }
                            }
                            else
                            {
                                pulseData = PulseRenderer.RenderNode(target,
                                                                     new Curve(new PointPairList(new double[] { 0, 100 }, new [] { level, level })), new ColorGradient(ColorGradient.GetColorAt(positionWithinGroup)), TimeSpan, HasDiscreteColors, true);
                                _elementData.Add(pulseData);
                            }
                            break;
                        }

                        i++;
                    }
                }
            }



            // the total chase time
            TimeSpan chaseTime = TimeSpan.FromMilliseconds(TimeSpan.TotalMilliseconds - PulseOverlap);

            if (chaseTime.TotalMilliseconds <= 0)
            {
                chaseTime = TimeSpan.FromMilliseconds(1);
            }

            //TODO: get a better increment time. doing it every X ms is..... shitty at best.
            //Less crappy is try to make some adjustment if there are a lot of nodes in a shorter time to sample more often.
            //A hard and fast 2ms was leaving gaps in larger node counts
            var sampleMs = chaseTime.TotalMilliseconds / targetNodeCount / 2.0;

            if (sampleMs < .25)
            {
                sampleMs = .25;
            }
            else if (sampleMs > 2)
            {
                sampleMs = 2;
            }
            TimeSpan increment = TimeSpan.FromTicks((long)(sampleMs * TimeSpan.TicksPerMillisecond));


            // 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 = (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, ChaseMovement.GetValue(100));
            }

            _elementData = EffectIntents.Restrict(_elementData, TimeSpan.Zero, TimeSpan);
        }
Exemple #12
0
        private void RenderNonBurst(CancellationTokenSource tokenSource, IEnumerable <IGrouping <int, ElementNode> > renderNodes)
        {
            //var pulse = new Pulse.Pulse();
            if (renderNodes != null && renderNodes.Any())
            {
                TimeSpan effectTime = TimeSpan.Zero;
                if (WipeByCount)
                {
                    int    count        = 0;
                    double pulseSegment = TimeSpan.Ticks / (double)PassCount * (PulsePercent / 100);

                    var    maxKey      = renderNodes.Select(x => x.Key).Max();
                    var    minKey      = renderNodes.Select(x => x.Key).Min();
                    double adjustedMax = maxKey - minKey;

                    TimeSpan totalWipeTime = TimeSpan.FromTicks((long)((TimeSpan.Ticks - pulseSegment) / PassCount));
                    TimeSpan segmentPulse  = TimeSpan.FromTicks((long)pulseSegment);

                    while (count < PassCount)
                    {
                        foreach (var item in renderNodes)
                        {
                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }

                            switch (Direction)
                            {
                            case WipeDirection.Left:
                            case WipeDirection.Up:
                                effectTime = TimeSpan.FromTicks((long)(totalWipeTime.Ticks * (1 - (item.Key - minKey) / adjustedMax) + count * totalWipeTime.Ticks));
                                break;

                            default:
                                effectTime = TimeSpan.FromTicks((long)(totalWipeTime.Ticks * (item.Key - minKey) / adjustedMax + count * totalWipeTime.Ticks));
                                break;
                            }

                            foreach (ElementNode element in item)
                            {
                                if (tokenSource != null && tokenSource.IsCancellationRequested)
                                {
                                    return;
                                }
                                if (element != null)
                                {
                                    EffectIntents result;
                                    if (ColorHandling == ColorHandling.GradientThroughWholeEffect)
                                    {
                                        result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                        result.OffsetAllCommandsByTime(effectTime);

                                        if (WipeOff && count == 0)
                                        {
                                            foreach (var effectIntent in result.FirstOrDefault().Value)
                                            {
                                                _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element, effectIntent, HasDiscreteColors));
                                            }
                                        }

                                        _elementData.Add(result);

                                        if (WipeOn && count == PassCount - 1)
                                        {
                                            foreach (var effectIntent in result.FirstOrDefault().Value)
                                            {
                                                _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element, effectIntent, TimeSpan, HasDiscreteColors));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        double positionWithinGroup = effectTime.Ticks / (double)totalWipeTime.Ticks;
                                        if (HasDiscreteColors)
                                        {
                                            List <Tuple <Color, float> > colorsAtPosition =
                                                ColorGradient.GetDiscreteColorsAndProportionsAt(positionWithinGroup);
                                            foreach (Tuple <Color, float> colorProportion in colorsAtPosition)
                                            {
                                                float proportion = colorProportion.Item2;
                                                // scale all levels of the pulse curve by the proportion that is applicable to this color
                                                Curve newCurve = new Curve(Curve.Points);
                                                foreach (PointPair pointPair in newCurve.Points)
                                                {
                                                    pointPair.Y *= proportion;
                                                }
                                                result = PulseRenderer.RenderNode(element, newCurve, new ColorGradient(colorProportion.Item1), segmentPulse, HasDiscreteColors);
                                                result.OffsetAllCommandsByTime(effectTime);

                                                if (WipeOff && count == 0)
                                                {
                                                    foreach (var effectIntent in result.FirstOrDefault().Value)
                                                    {
                                                        _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element, effectIntent, HasDiscreteColors, new ColorGradient(colorProportion.Item1)));
                                                    }
                                                }

                                                if (result.Count > 0)
                                                {
                                                    _elementData.Add(result);
                                                }

                                                if (WipeOn && count == PassCount - 1)
                                                {
                                                    foreach (var effectIntent in result.FirstOrDefault().Value)
                                                    {
                                                        _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element, effectIntent, TimeSpan, HasDiscreteColors, new ColorGradient(colorProportion.Item1)));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            result = PulseRenderer.RenderNode(element, _data.Curve,
                                                                              new ColorGradient(_data.ColorGradient.GetColorAt(positionWithinGroup)), segmentPulse, HasDiscreteColors);
                                            result.OffsetAllCommandsByTime(effectTime);

                                            if (WipeOff && count == 0)
                                            {
                                                foreach (var effectIntent in result.FirstOrDefault().Value)
                                                {
                                                    _elementData.Add(PulseRenderer.GenerateStartingStaticPulse(element, effectIntent, HasDiscreteColors));
                                                }
                                            }

                                            _elementData.Add(result);

                                            if (WipeOn && count == PassCount - 1)
                                            {
                                                foreach (var effectIntent in result.FirstOrDefault().Value)
                                                {
                                                    _elementData.Add(PulseRenderer.GenerateExtendedStaticPulse(element, effectIntent, TimeSpan, HasDiscreteColors));
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        count++;
                    }
                }
                else
                {
                    double intervals    = (double)PulseTime / (double)renderNodes.Count();
                    var    intervalTime = TimeSpan.FromMilliseconds(intervals);
                    // the calculation above blows up render time/memory as count goes up, try this..
                    // also fails if intervals is less than half a ms and intervalTime then gets 0
                    intervalTime = TimeSpan.FromMilliseconds(Math.Max(intervalTime.TotalMilliseconds, 5));
                    TimeSpan segmentPulse = TimeSpan.FromMilliseconds(PulseTime);
                    while (effectTime < TimeSpan)
                    {
                        foreach (var item in renderNodes)
                        {
                            EffectIntents result;

                            if (tokenSource != null && tokenSource.IsCancellationRequested)
                            {
                                return;
                            }

                            foreach (ElementNode element in item)
                            {
                                if (element != null)
                                {
                                    if (tokenSource != null && tokenSource.IsCancellationRequested)
                                    {
                                        return;
                                    }
                                    result = PulseRenderer.RenderNode(element, _data.Curve, _data.ColorGradient, segmentPulse, HasDiscreteColors);
                                    result.OffsetAllCommandsByTime(effectTime);
                                    //bool discreteElement = HasDiscreteColors && ColorModule.isElementNodeDiscreteColored(element);
                                    //_elementData.Add(IntentBuilder.ConvertToStaticArrayIntents(result, TimeSpan, discreteElement));
                                    _elementData.Add(result);
                                }
                            }
                            effectTime += intervalTime;
                            if (effectTime >= TimeSpan)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
Exemple #13
0
        private void GenerateStartingStaticPulse(ElementNode target, Curve newCurve, ColorGradient gradient, TimeSpan time)
        {
            var result = PulseRenderer.RenderNode(target, newCurve, gradient, time, HasDiscreteColors);

            _elementData.Add(result);
        }