protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { if (!_videoFileDetected) { return; } var bufferWi = BufferWi; var bufferHt = BufferHt; //these lookups are a bit expensive when called a lot of times var bufferWiOffset = BufferWiOffset; var bufferHtOffset = BufferHtOffset; for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; InitFrameData(frame, out double intervalPos, out double intervalPosFactor, out double level, out double adjustedBrightness); InitialRender(intervalPos, intervalPosFactor); if (_fp != null) { _fp.Lock(); foreach (var elementLocation in frameBuffer.ElementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, frameBuffer, frame, level, adjustedBrightness, ref bufferHt, ref bufferWi, true, bufferHtOffset, bufferWiOffset); } _fp.Unlock(false); } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); var bufferHt = BufferHt; var bufferWi = BufferWi; for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; _level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame) * 100) / 100; using (var bitmap = new Bitmap(bufferWi, bufferHt)) { InitialRender(frame, bitmap, bufferHt, bufferWi); FastPixel.FastPixel fp = new FastPixel.FastPixel(bitmap); fp.Lock(); foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, ref bufferHt, fp, frameBuffer); } } fp.Unlock(false); fp.Dispose(); } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int frame = 0; frame < numFrames; frame++) { var intervalPos = GetEffectTimeIntervalPosition(frame); var intervalPosFactor = intervalPos * 100; var speed = CalculateSpeed(intervalPosFactor); frameBuffer.CurrentFrame = frame; double position = intervalPosFactor * speed; double plasmaSpeed = (101 - speed) * 3; var time = (position + 1.0) / plasmaSpeed; double level = LevelCurve.GetValue(intervalPosFactor) / 100; double lineDensity = CalculateLineDensity(intervalPosFactor) * Pi; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, time, frame, level, frameBuffer, lineDensity); } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; _level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame) * 100) / 100; using (var bitmap = new Bitmap(BufferWi, BufferHt)) { InitialRender(frame, bitmap); if (_text.Count == 0 && !UseBaseColor) { continue; } foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, bitmap, frameBuffer); } } } } }
protected EffectIntents RenderNodeByLocation(ElementNode node) { EffectIntents effectIntents = new EffectIntents(); int nFrames = GetNumberFrames(); if (nFrames <= 0 | BufferWi == 0 || BufferHt == 0) { return(effectIntents); } PixelLocationFrameBuffer buffer = new PixelLocationFrameBuffer(ElementLocations.Distinct().ToList(), nFrames); TimeSpan startTime = TimeSpan.Zero; // generate all the pixels RenderEffectByLocation(nFrames, buffer); // create the intents var frameTs = new TimeSpan(0, 0, 0, 0, FrameTime); foreach (var tuple in buffer.GetElementData()) { if (tuple.Item2.Count != nFrames) { Logging.Error("{0} count has {1} instead of {2}", tuple.Item1.ElementNode.Name, tuple.Item2.Count, nFrames); } IIntent intent = new StaticArrayIntent <RGBValue>(frameTs, tuple.Item2.ToArray(), TimeSpan); effectIntents.AddIntentForElement(tuple.Item1.ElementNode.Element.Id, intent, startTime); } return(effectIntents); }
private IList <Tuple <int, int[]> > GetSparseMatrix(PixelLocationFrameBuffer frameBuffer) { IList <Tuple <int, int[]> > sparseMatrix = new List <Tuple <int, int[]> >(); if (Direction == GarlandsDirection.Up || Direction == GarlandsDirection.Down) { IEnumerable <IGrouping <int, ElementLocation> > nodes = frameBuffer.ElementLocations.OrderBy(elementLocation => elementLocation.Y).ThenBy(elementLocation => elementLocation.X).GroupBy(elementLocation => elementLocation.Y); foreach (IGrouping <int, ElementLocation> group in nodes) { sparseMatrix.Add(new Tuple <int, int[]>(group.Key, group.Select(elementLocation => elementLocation.X).ToArray())); } } else { IEnumerable <IGrouping <int, ElementLocation> > nodes = frameBuffer.ElementLocations.OrderBy(elementLocation => elementLocation.X).ThenBy(elementLocation => elementLocation.Y).GroupBy(elementLocation => elementLocation.X); foreach (IGrouping <int, ElementLocation> group in nodes) { sparseMatrix.Add(new Tuple <int, int[]>(group.Key, group.Select(elementLocation => elementLocation.Y).ToArray())); } } return(sparseMatrix); }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; double level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame) * 100) / 100; var iterationFrame = frame * Iterations % (numFrames); double position = GetEffectTimeIntervalPosition(iterationFrame); HSV hsv = HSV.FromRGB(Color.GetColorAt(position)); if (Shimmer && frame % 2 != 0) { hsv.V = 0; } foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { var v = hsv.V; //Here we offset our x, y values to get us to zero based coordinates for our math to work out //Our effect is symetrical so we don't need to waste time flipping the coordinates around v = CalculateAdjustedV(v, elementLocation.X - BufferWiOffset, elementLocation.Y - BufferHtOffset); v *= level; HSV hsv2 = hsv; hsv2.V = v; frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv2); } } } }
protected EffectIntents RenderNodeByLocation(ElementNode node, ref EffectIntents effectIntents) { int nFrames = GetNumberFrames(); if (nFrames <= 0 | BufferWi == 0 || BufferHt == 0) { return(effectIntents); } PixelLocationFrameBuffer buffer = new PixelLocationFrameBuffer(ElementLocations, nFrames); TimeSpan startTime = TimeSpan.Zero; // generate all the pixels RenderEffectByLocation(nFrames, buffer); // create the intents var frameTs = new TimeSpan(0, 0, 0, 0, FrameTime); foreach (var elementLocation in ElementLocations) { var frameData = buffer.GetFrameDataAt(elementLocation.X, elementLocation.Y); IIntent intent = new StaticArrayIntent <RGBValue>(frameTs, frameData, TimeSpan); effectIntents.AddIntentForElement(elementLocation.ElementNode.Element.Id, intent, startTime); } return(effectIntents); }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { //It kinda stinks so much of this code duplicates the RenderEffect method, but //there are enough differences in the two that it needs to be. Trying to refactor //small parts of it out into reusable chunks is probably not fruitful at this time. double posX = (BufferWi * CenterX / 100.0) + BufferWiOffset; double posY = (BufferHt * CenterY / 100.0) + BufferHtOffset; Point centerPoint = new Point((int)posX, (int)posY); var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); Point currentPoint = Point.Empty; for (int effectFrame = 0; effectFrame < numFrames; effectFrame++) { double position = GetEffectTimeIntervalPosition(effectFrame); double effectPositionAdjust = CalculateAcceleration(position, Acceleration); Color c = Color.GetColorAt(position); double centerRadius = StartRadius + (EndRadius - StartRadius) * effectPositionAdjust; double halfWidth = (StartWidth + (EndWidth - StartWidth) * effectPositionAdjust) / 2.0; var radius1 = Math.Max(0.0, centerRadius - halfWidth); var radius2 = centerRadius + halfWidth; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { currentPoint.X = elementLocation.X; currentPoint.Y = elementLocation.Y; var distance = DistanceFromCenter(centerPoint, currentPoint); if (ContainsPoint(distance, radius1, radius2)) { if (BlendEdges) { double colorPct = 1.0 - Math.Abs(distance - centerRadius) / halfWidth; if (colorPct > 0.0) { HSV hsv = HSV.FromRGB(c); hsv.V = hsv.V * colorPct; frameBuffer.SetPixel(currentPoint.X, currentPoint.Y, hsv); } else { frameBuffer.SetPixel(currentPoint.X, currentPoint.Y, System.Drawing.Color.Transparent); } } else { frameBuffer.SetPixel(currentPoint.X, currentPoint.Y, c); } } else { frameBuffer.SetPixel(currentPoint.X, currentPoint.Y, System.Drawing.Color.Transparent); } } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var bufferWi = BufferWi; var bufferHt = BufferHt; for (int effectFrame = 0; effectFrame < numFrames; effectFrame++) { frameBuffer.CurrentFrame = effectFrame; var intervalPos = GetEffectTimeIntervalPosition(effectFrame); var intervalPosFactor = intervalPos * 100; double level = LevelCurve.GetValue(intervalPos); int thickness = (int)Math.Round(CalculateBorderThickness(intervalPosFactor) / 2); int topThickness = (int)(TopThicknessCurve.GetValue(intervalPosFactor) * bufferHt / 100); int bottomThickness = (int)(BottomThicknessCurve.GetValue(intervalPosFactor) * bufferHt / 100); int leftThickness = (int)(LeftThicknessCurve.GetValue(intervalPosFactor) * bufferWi / 100); int rightThickness = (int)(RightThicknessCurve.GetValue(intervalPosFactor) * bufferWi / 100); int borderHeight = (int)CalculateBorderHeight(intervalPosFactor) / 2; int borderWidth = (int)(CalculateBorderSize(intervalPosFactor) / 2); int xOffsetAdj = CalculateXOffset(intervalPosFactor) * (bufferWi - borderWidth) / 100; int yOffsetAdj = CalculateYOffset(intervalPosFactor) * (bufferHt - borderHeight) / 100; Color color = Color.GetColorAt(GetEffectTimeIntervalPosition(effectFrame)); if (BorderMode == BorderMode.Simple) { thickness = SimpleBorderWidth; borderWidth = 0; borderHeight = 0; xOffsetAdj = 0; yOffsetAdj = 0; } else if (BorderType == BorderType.Single) { rightThickness = thickness; topThickness = thickness; leftThickness = thickness; bottomThickness = thickness; } foreach (var elementLocation in frameBuffer.ElementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, frameBuffer, thickness, topThickness, bottomThickness, leftThickness, rightThickness, level, borderWidth, borderHeight, color, xOffsetAdj, yOffsetAdj, ref bufferHt, ref bufferWi); } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { int degreesPerArm = 1; if (Arms > 0) { degreesPerArm = 360 / Arms; } for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; var intervalPos = GetEffectTimeIntervalPosition(frame); var intervalPosFactor = intervalPos * 100; double pos = MovementType == MovementType.Iterations ? intervalPos * CalculateSpeed(intervalPosFactor) * 360 : intervalPos *CalculateSpeed(intervalPosFactor) * GetNumberFrames(); var overallLevel = LevelCurve.GetValue(intervalPosFactor) / 100; double currentTwist = CalculateTwist(intervalPosFactor); var arms = CreateArms(degreesPerArm, pos, frame, overallLevel); float armsize = (float)(CalculateSize(intervalPosFactor) / 100.0); var origin = new Point(BufferWi / 2 + BufferWiOffset + CalculateXOffset(intervalPosFactor), BufferHt / 2 + BufferHtOffset + CalculateYOffset(intervalPosFactor)); var xc = OffsetPercentage ? BufferHt : DistanceFromPoint(origin, new Point(BufferWiOffset + BufferWi, BufferHtOffset + BufferHt)); var maxRadius = xc * armsize; var angleRange = CalculateThickness(intervalPosFactor) / 100.0f * degreesPerArm / 2.0f; var centerStartPct = CalculateCenterStartPct(intervalPosFactor); foreach (var elementLocation in frameBuffer.ElementLocations) { RenderPoint(frameBuffer, currentTwist, elementLocation.X, elementLocation.Y, origin, maxRadius, arms, angleRange, overallLevel, false, centerStartPct); } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var bufferHt = BufferHt; var bufferWi = BufferWi; var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; double intervalPos = GetEffectTimeIntervalPosition(frame); double intervalPosFactor = intervalPos * 100; int xOffset = CalculateXOffset(intervalPosFactor); int yOffset = CalculateYOffset(intervalPosFactor); double level = LevelCurve.GetValue(intervalPosFactor) / 100; double radius1 = CalculateRadialSize(intervalPosFactor); double radius = radius1 / 2 / _circleCount; double currentRadius = radius; double edgeWidth = CalculateEdgeWidth(intervalPosFactor, currentRadius); double barht = _maxBuffer / _circleCount; if (CircleFill == CircleFill.Empty || CircleFill == CircleFill.Fade) { barht /= _circleCount; } if (barht < 1) { barht = 1; } double blockHt = Colors.Count * barht; double foffset = frame * CalculateCenterSpeed(intervalPosFactor) / 4 % (blockHt + 1); barht = barht > 0 ? barht : 1; _circleCount = CalculateCircleCount(intervalPosFactor) / 2; if (CircleFill == CircleFill.Fade || CircleFill == CircleFill.Empty) { _circleCount /= 5; } foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, level, frameBuffer, intervalPos, radius, radius1, currentRadius, foffset, barht, blockHt, bufferWi, bufferHt, xOffset, yOffset, edgeWidth); } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int effectFrame = 0; effectFrame < numFrames; effectFrame++) { frameBuffer.CurrentFrame = effectFrame; var intervalPos = GetEffectTimeIntervalPosition(effectFrame); var intervalPosFactor = intervalPos * 100; double level = LevelCurve.GetValue(intervalPos); int thickness = (int)Math.Round(CalculateBorderThickness(intervalPosFactor) / 2); int topThickness = (int)(TopThicknessCurve.GetValue(intervalPosFactor) * BufferHt / 100); int bottomThickness = (int)(BottomThicknessCurve.GetValue(intervalPosFactor) * BufferHt / 100); int leftThickness = (int)(LeftThicknessCurve.GetValue(intervalPosFactor) * BufferWi / 100); int rightThickness = (int)(RightThicknessCurve.GetValue(intervalPosFactor) * BufferWi / 100); int borderWidth = (int)(CalculateBorderSize(intervalPosFactor) / 2); Color color = Color.GetColorAt(GetEffectTimeIntervalPosition(effectFrame)); if (BorderMode == BorderMode.Simple) { thickness = SimpleBorderWidth; borderWidth = 0; } else if (BorderType == BorderType.Single) { rightThickness = thickness; topThickness = thickness; leftThickness = thickness; bottomThickness = thickness; } foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, frameBuffer, thickness, topThickness, bottomThickness, leftThickness, rightThickness, intervalPosFactor, level, effectFrame, borderWidth, color); } } } }
/// <summary> /// Renders the effect by location. /// </summary> /// <remarks> /// The general math is identical between RenderEffectByLocation and RenderEffect. /// The RenderEffect draws the garland pattern in one pass adjusting the Y position to get the pattern. /// The RenderEffectByLocation has to process each row in the pattern separately since each row that /// makes up the pattern could be a different number of pixels. /// </remarks> protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { IList <Tuple <int, int[]> > sparseMatrix = GetSparseMatrix(frameBuffer); for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; // This tells us where we are in the effect duration normalized 0 - 1 double intervalPos = GetEffectTimeIntervalPosition(frame); // This is where we are in the effect duration normalized to 0 - 100 double intervalPosFactor = intervalPos * 100; // Get the brightness of the effect double brightnessLevel = LevelCurve.GetValue(intervalPosFactor) / 100; int height = sparseMatrix.Count; // Get a value between 1 and 20 pixels int pixelSpacing = CalculateSpacing(intervalPosFactor) * height / 100 + 3; int limit = height * pixelSpacing * 4; int garlandsState; if (MovementType == MovementType.Iterations) { garlandsState = (int)(limit - _frames * (limit / GetNumberFrames() * Iterations)) / 4; if (garlandsState <= 0) { _frames = 0; } } else { _speed += CalculateSpeed(intervalPosFactor); garlandsState = (limit - _speed % limit) / 4; //Speed } _frames++; DrawGarlandPattern(sparseMatrix, height, pixelSpacing, brightnessLevel, garlandsState, frame, frameBuffer); } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int frame = 0; frame < numFrames; frame++) { double position = GetEffectTimeIntervalPosition(frame) * Speed * 100; double plasmaSpeed = (101 - Speed) * 3; var time = (position + 1.0) / plasmaSpeed; double level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame) * 100) / 100; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, time, frame, level, frameBuffer); } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { int repeat = ConfigureRepeat(); int maxframe = BufferHt; var nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); for (int effectFrame = 0; effectFrame < numFrames; effectFrame++) { frameBuffer.CurrentFrame = effectFrame; double position = (GetEffectTimeIntervalPosition(effectFrame) * Iterations) % 1; int curState = (int)(TimeSpan.TotalMilliseconds * position * repeat); int frame = (BufferHt * curState / (int)TimeSpan.TotalMilliseconds) % maxframe; double offset = curState / TimeSpan.TotalMilliseconds; double level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(effectFrame) * 100) / 100; if (Direction == Direction.Forward) { offset = -offset; } int bufferDim = 0; if (ButterflyType == ButterflyType.Type1 || ButterflyType == ButterflyType.Type4) { bufferDim = BufferHt + BufferWi; } else if (ButterflyType == ButterflyType.Type5) { bufferDim = BufferHt * BufferWi; } foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, bufferDim, offset, frame, maxframe, level, frameBuffer); } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var nodes = frameBuffer.ElementLocations.OrderBy(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; _intervalPos = (float)GetEffectTimeIntervalPosition(frame); _intervalPosFactor = _intervalPos * 100; _radius = CalculateSize(_intervalPosFactor); _centerSpeed = CalculateCenterSpeed(_intervalPosFactor); _speedVariation = CalculateSpeedVariation(_intervalPosFactor); _level = LevelCurve.GetValue(_intervalPosFactor) / 100; int maxRandomTime = CalculateRandomMax(_intervalPosFactor); Color inverseBackColor = BackgroundColor.GetColorAt(_intervalPos); double minSpeed = _centerSpeed - (_speedVariation / 2); double maxSpeed = _centerSpeed + (_speedVariation / 2); _ballCount = CalculateBallCount(_intervalPosFactor); // Create new Balls and add balls due to increase in ball count curve. CreateBalls(minSpeed, maxSpeed, maxRandomTime); // Update Ball location, radius and speed. UpdateBalls(minSpeed, maxSpeed, maxRandomTime); //Remove Excess Balls due to BallCount Curve. RemoveBalls(); //Iterate through all grid locations. foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, frameBuffer, inverseBackColor); } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var bufferWi = BufferWi; var bufferHt = BufferHt; for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; InitFrameData(frame, out double intervalPosFactor, out double level, out double adjustedBrightness); InitialRender(frame, intervalPosFactor); if (_fp != null) { _fp.Lock(); foreach (var elementLocation in frameBuffer.ElementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, frameBuffer, frame, level, adjustedBrightness, ref bufferHt, ref bufferWi); } _fp.Unlock(false); } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { int colorcnt = Colors.Count(); int barCount = Repeat * colorcnt; if (barCount < 1) { barCount = 1; } int barHt = BufferHt / barCount + 1; if (barHt < 1) { barHt = 1; } int blockHt = colorcnt * barHt; if (blockHt < 1) { blockHt = 1; } int barWi = BufferWi / barCount + 1; if (barWi < 1) { barWi = 1; } int blockWi = colorcnt * barWi; if (blockWi < 1) { blockWi = 1; } IEnumerable <IGrouping <int, ElementLocation> > nodes; List <IGrouping <int, ElementLocation> > reversedNodes = new List <IGrouping <int, ElementLocation> >(); switch (Direction) { case BarDirection.AlternateUp: case BarDirection.Up: nodes = frameBuffer.ElementLocations.OrderBy(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); break; case BarDirection.Left: case BarDirection.AlternateLeft: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); break; case BarDirection.Right: case BarDirection.AlternateRight: nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); break; case BarDirection.Compress: case BarDirection.Expand: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); reversedNodes = nodes.Reverse().ToList(); break; case BarDirection.HCompress: case BarDirection.HExpand: nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); reversedNodes = nodes.Reverse().ToList(); break; default: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); break; } var nodeCount = nodes.Count(); var halfNodeCount = (nodeCount - 1) / 2; var evenHalfCount = nodeCount % 2 != 0; for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; double level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame) * 100) / 100; double position = (GetEffectTimeIntervalPosition(frame) * Speed) % 1; int n; int colorIdx; if (Direction < BarDirection.Left || Direction == BarDirection.AlternateUp || Direction == BarDirection.AlternateDown) { int fOffset = (int)(position * blockHt * Repeat); // : Speed * frame / 4 % blockHt); if (Direction == BarDirection.AlternateUp || Direction == BarDirection.AlternateDown) { fOffset = (int)(Math.Floor(position * barCount) * barHt); } if (Direction == BarDirection.Down || Direction == BarDirection.AlternateDown || Direction == BarDirection.Expand) { fOffset = -fOffset; } int indexAdjust = 1; int i = 0; bool exitLoop = false; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { int y = elementLocations.Key; n = y + fOffset; colorIdx = Math.Abs(((n + indexAdjust) % blockHt) / barHt); //we need the integer division here to make things work double colorPosition = Math.Abs((double)(n + indexAdjust) / barHt - (n + indexAdjust) / barHt); Color c = Colors[colorIdx].GetColorAt(colorPosition); var hsv = HSV.FromRGB(c); if (Highlight && (n + indexAdjust) % barHt == 0) { hsv.S = 0.0f; } if (Show3D) { hsv.V *= (float)(barHt - (n + indexAdjust) % barHt - 1) / barHt; } hsv.V = hsv.V * level; switch (Direction) { case BarDirection.Expand: case BarDirection.Compress: // expand / compress if (i <= halfNodeCount) { foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(elementLocation.X, y, hsv); } if (i == halfNodeCount & evenHalfCount) { i++; continue; } foreach (var elementLocation in reversedNodes[i]) { frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } i++; } else { exitLoop = true; } break; default: foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(elementLocation.X, y, hsv); } break; } if (exitLoop) { break; } } } else { int fOffset = (int)(position * blockWi * Repeat); if (Direction > BarDirection.AlternateDown) { fOffset = (int)(Math.Floor(position * barCount) * barWi); } if (Direction == BarDirection.Right || Direction == BarDirection.AlternateRight || Direction == BarDirection.HCompress) { fOffset = -fOffset; } int i = 0; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { int x = elementLocations.Key; n = x + fOffset; colorIdx = Math.Abs(((n + 1) % blockWi) / barWi); //we need the integer division here to make things work double colorPosition = Math.Abs((double)(n + 1) / barWi - (n + 1) / barWi); Color c = Colors[colorIdx].GetColorAt(colorPosition); var hsv = HSV.FromRGB(c); if (Highlight && n % barWi == 0) { hsv.S = 0.0f; } if (Show3D) { hsv.V *= (float)(barWi - n % barWi - 1) / barWi; } hsv.V = hsv.V * level; switch (Direction) { case BarDirection.HExpand: case BarDirection.HCompress: if (i <= halfNodeCount) { foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(x, elementLocation.Y, hsv); } if (i == halfNodeCount & evenHalfCount) { i++; continue; } foreach (var elementLocation in reversedNodes[i]) { frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } i++; } break; default: foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(x, elementLocation.Y, hsv); } break; } } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { int colorcnt = Colors.Count(); int barCount = Repeat * colorcnt; if (barCount < 1) { barCount = 1; } int barHt = BufferHt / barCount + 1; if (barHt < 1) { barHt = 1; } int blockHt = colorcnt * barHt; if (blockHt < 1) { blockHt = 1; } int barWi = BufferWi / barCount + 1; if (barWi < 1) { barWi = 1; } int blockWi = colorcnt * barWi; if (blockWi < 1) { blockWi = 1; } var bufferHt = BufferHt; var bufferWi = BufferWi; var bufferHtOffset = BufferHtOffset; var bufferWiOffset = BufferWiOffset; IEnumerable <IGrouping <int, ElementLocation> > nodes; List <IGrouping <int, ElementLocation> > reversedNodes = new List <IGrouping <int, ElementLocation> >(); switch (Direction) { case BarDirection.AlternateUp: case BarDirection.Up: nodes = frameBuffer.ElementLocations.OrderBy(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); break; case BarDirection.Left: case BarDirection.AlternateLeft: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); break; case BarDirection.Right: case BarDirection.AlternateRight: nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); break; case BarDirection.Compress: case BarDirection.Expand: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); reversedNodes = nodes.Reverse().ToList(); break; case BarDirection.HCompress: case BarDirection.HExpand: nodes = frameBuffer.ElementLocations.OrderBy(x => x.X).ThenBy(x => x.Y).GroupBy(x => x.X); reversedNodes = nodes.Reverse().ToList(); break; default: nodes = frameBuffer.ElementLocations.OrderByDescending(x => x.Y).ThenBy(x => x.X).GroupBy(x => x.Y); break; } var nodeCount = nodes.Count(); var halfNodeCount = (nodeCount - 1) / 2; var evenHalfCount = nodeCount % 2 != 0; for (int frame = 0; frame < numFrames; frame++) { frameBuffer.CurrentFrame = frame; double intervalPosFactor = GetEffectTimeIntervalPosition(frame) * 100; double level = LevelCurve.GetValue(intervalPosFactor) / 100; if (MovementType == MovementType.Iterations) { _position = (GetEffectTimeIntervalPosition(frame) * Speed) % 1; } else { var s = CalculateSpeed(intervalPosFactor); if (frame == 0) { _position = s; } _position += s / 100 * FrameTime / 50d; //Adjust the speed setting for different frame rates with FrameTime / 50d } int n; int colorIdx; if (Direction < BarDirection.Left || Direction == BarDirection.AlternateUp || Direction == BarDirection.AlternateDown) { int fOffset = (int)(_position * blockHt * Repeat); // : Speed * frame / 4 % blockHt); if (Direction == BarDirection.AlternateUp || Direction == BarDirection.AlternateDown) { fOffset = (int)(Math.Floor(_position * barCount) * barHt); } int indexAdjust = 1; int i = 0; bool exitLoop = false; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { int y = elementLocations.Key; switch (Direction) { case BarDirection.Down: case BarDirection.AlternateDown: case BarDirection.Expand: n = (bufferHt + bufferHtOffset) - y + fOffset; break; default: n = y - bufferHtOffset + fOffset; break; } colorIdx = ((n + indexAdjust) % blockHt) / barHt; //we need the integer division here to make things work var colorPosition = (n + indexAdjust) % barHt / (double)barHt; Color c = Colors[colorIdx].GetColorAt(colorPosition); if (Highlight || Show3D) { var hsv = HSV.FromRGB(c); if (Highlight && (n + indexAdjust) % barHt == 0 || colorPosition > .95) { hsv.S = 0.0f; } if (Show3D) { hsv.V *= (float)(barHt - (n + indexAdjust) % barHt - 1) / barHt; } hsv.V *= level; c = hsv.ToRGB(); } else { if (level < 1) { HSV hsv = HSV.FromRGB(c); hsv.V *= level; c = hsv.ToRGB(); } } switch (Direction) { case BarDirection.Expand: case BarDirection.Compress: // expand / compress if (i <= halfNodeCount) { foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(elementLocation.X, y, c); } if (i == halfNodeCount & evenHalfCount) { i++; continue; } foreach (var elementLocation in reversedNodes[i]) { frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, c); } i++; } else { exitLoop = true; } break; default: foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(elementLocation.X, y, c); } break; } if (exitLoop) { break; } } } else { int fOffset = (int)(_position * blockWi * Repeat); if (Direction > BarDirection.AlternateDown) { fOffset = (int)(Math.Floor(_position * barCount) * barWi); } int i = 0; foreach (IGrouping <int, ElementLocation> elementLocations in nodes) { int x = elementLocations.Key; switch (Direction) { case BarDirection.Right: case BarDirection.AlternateRight: case BarDirection.HCompress: n = (bufferWi + bufferWiOffset) - x + fOffset; break; default: n = x - bufferWiOffset + fOffset; break; } //we need the integer division here to make things work colorIdx = (n + 1) % blockWi / barWi; double colorPosition = (n + 1) % barWi / (double)barWi; Color c = Colors[colorIdx].GetColorAt(colorPosition); if (Highlight || Show3D) { var hsv = HSV.FromRGB(c); if (Highlight && (n + 1) % barWi == 0 || colorPosition > .95) { hsv.S = 0.0f; } if (Show3D) { hsv.V *= (float)(barWi - n % barWi - 1) / barWi; } hsv.V *= level; c = hsv.ToRGB(); } else { if (level < 1) { HSV hsv = HSV.FromRGB(c); hsv.V *= level; c = hsv.ToRGB(); } } switch (Direction) { case BarDirection.HExpand: case BarDirection.HCompress: if (i <= halfNodeCount) { foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(x, elementLocation.Y, c); } if (i == halfNodeCount & evenHalfCount) { i++; continue; } foreach (var elementLocation in reversedNodes[i]) { frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, c); } i++; } break; default: foreach (var elementLocation in elementLocations) { frameBuffer.SetPixel(x, elementLocation.Y, c); } break; } } } } }
private void DrawCurtainVerticalLocation(bool topEdge, int ylimit, List <int> swagArray, PixelLocationFrameBuffer frameBuffer, double level, int width) { var topBufferLimit = BufferHt + BufferHtOffset; var elements = topEdge ? frameBuffer.ElementLocations.Where(e => e.Y > topBufferLimit - ylimit) : frameBuffer.ElementLocations.Where(e => e.Y < ylimit + BufferHtOffset); foreach (var elementLocation in elements) { var hsv = GetVerticalLocationColor(topEdge, width, elementLocation); hsv.V = hsv.V * level; frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } //Swag if (swagArray.Count > 0) { var swagElements = topEdge ? frameBuffer.ElementLocations.Where(e => e.Y <= topBufferLimit - ylimit && e.Y >= topBufferLimit - (ylimit + swagArray.Count)).ToLookup(e => e.Y) : frameBuffer.ElementLocations.Where(e => e.Y >= ylimit + BufferHtOffset && e.Y <= ylimit + swagArray.Count + BufferHtOffset).ToLookup(e => e.Y); for (int i = 0; i < swagArray.Count; i++) { int x = topEdge ? topBufferLimit - (ylimit + i) : ylimit + i + BufferHtOffset; var limit = BufferWiOffset + swagArray[i]; foreach (var elementLocation in swagElements[x]) { if (elementLocation.X > limit) { var hsv = GetVerticalLocationColor(topEdge, width, elementLocation); hsv.V = hsv.V * level; frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } } } } }
private void DrawCurtainLocation(bool leftEdge, int xlimit, List <int> swagArray, PixelLocationFrameBuffer frameBuffer, double level, int width) { var rightBufferLimit = BufferWi + BufferWiOffset; var elements = leftEdge ? frameBuffer.ElementLocations.Where(e => e.X >= (rightBufferLimit) - xlimit) : frameBuffer.ElementLocations.Where(e => e.X <= xlimit + BufferWiOffset); foreach (var elementLocation in elements) { var hsv = GetLocationColor(leftEdge, width, elementLocation); hsv.V = hsv.V * level; frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } // swag if (swagArray.Count > 0) { var swagElements = leftEdge ? frameBuffer.ElementLocations.Where(e => e.X <= (BufferWi + BufferWiOffset) - xlimit && e.X >= (BufferWi + BufferWiOffset) - (xlimit + swagArray.Count)).ToLookup(e => e.X) : frameBuffer.ElementLocations.Where(e => e.X >= xlimit + BufferWiOffset && e.X <= xlimit + swagArray.Count + BufferWiOffset).ToLookup(e => e.X); for (int i = 0; i < swagArray.Count; i++) { int x = leftEdge? rightBufferLimit - (xlimit + i):xlimit + i + BufferWiOffset; var limit = BufferHt - swagArray[i] + BufferHtOffset; foreach (var elementLocation in swagElements[x]) { if (elementLocation.Y < limit) { var hsv = GetLocationColor(leftEdge, width, elementLocation); hsv.V = hsv.V * level; frameBuffer.SetPixel(elementLocation.X, elementLocation.Y, hsv); } } } } }
protected override void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { var swagArray = new List <int>(); int swaglen = BufferHt > 1 ? Swag * BufferWi / 40 : 0; var swagBufferHt = BufferHt; switch (Edge) { case CurtainEdge.Middle: case CurtainEdge.Top: case CurtainEdge.Bottom: swagBufferHt = BufferWi; break; } for (int effectFrame = 0; effectFrame < numFrames; effectFrame++) { frameBuffer.CurrentFrame = effectFrame; var timeIntervalPosition = GetEffectTimeIntervalPosition(effectFrame); double position = (timeIntervalPosition * Speed) % 1; double level = LevelCurve.GetValue(timeIntervalPosition * 100) / 100; if (swaglen > 0) { swagArray.Clear(); double a = (double)(swagBufferHt) / (swaglen * swaglen); for (int x = 0; x < swaglen; x++) { swagArray.Add((int)(a * x * x)); } } int xlimit; int ylimit; if (Direction < CurtainDirection.CurtainOpenClose) { if (Direction == CurtainDirection.CurtainOpen) { xlimit = (int)((position * BufferWi) + (swaglen * position * 2)); ylimit = (int)((position * BufferHt) + (swaglen * position * 2)); } else { xlimit = (int)((position * BufferWi) - (swaglen * (1 - position) * 2)); ylimit = (int)((position * BufferHt) - (swaglen * (1 - position) * 2)); } } else { if (Direction == CurtainDirection.CurtainOpenClose) { xlimit = (int)(position <= .5 ? (position * 2 * BufferWi) + (swaglen * position * 4) : ((position - .5) * 2 * BufferWi) - (swaglen * (1 - position) * 4)); ylimit = (int)(position <= .5 ? (position * 2 * BufferHt) + (swaglen * position * 4) : ((position - .5) * 2 * BufferHt) - (swaglen * (1 - position) * 4)); } else { xlimit = (int)(position <= .5 ? (position * 2 * BufferWi) - (swaglen * (0.5 - position) * 4) : ((position - .5) * 2 * BufferWi) + (swaglen * position * 2)); ylimit = (int)(position <= .5 ? (position * 2 * BufferHt) - (swaglen * (0.5 - position) * 4) : ((position - .5) * 2 * BufferHt) + (swaglen * position * 2)); } } int curtainDir; if (Direction < CurtainDirection.CurtainOpenClose) { curtainDir = (int)Direction % 2; } else if (xlimit < _lastCurtainLimit - swaglen * 2) { curtainDir = 1 - _lastCurtainDir; } else { curtainDir = _lastCurtainDir; } _lastCurtainDir = curtainDir; _lastCurtainLimit = xlimit; if (curtainDir == 0) { xlimit = BufferWi - xlimit; ylimit = BufferHt - ylimit; } int middle; switch (Edge) { case CurtainEdge.Left: // left DrawCurtainLocation(true, xlimit, swagArray, frameBuffer, level, BufferWi); break; case CurtainEdge.Center: // center middle = xlimit / 2; DrawCurtainLocation(true, middle, swagArray, frameBuffer, level, BufferWi / 2); DrawCurtainLocation(false, middle, swagArray, frameBuffer, level, BufferWi / 2); break; case CurtainEdge.Right: // right DrawCurtainLocation(false, xlimit, swagArray, frameBuffer, level, BufferWi); break; case CurtainEdge.Bottom: // bottom DrawCurtainVerticalLocation(false, ylimit, swagArray, frameBuffer, level, BufferHt); break; case CurtainEdge.Middle: // middle middle = ylimit / 2; DrawCurtainVerticalLocation(true, middle, swagArray, frameBuffer, level, BufferHt / 2); DrawCurtainVerticalLocation(false, middle, swagArray, frameBuffer, level, BufferHt / 2); break; case CurtainEdge.Top: // top DrawCurtainVerticalLocation(true, ylimit, swagArray, frameBuffer, level, BufferHt); break; } } }
/// <summary> /// Called by for effects that support location based rendering when it is enabled /// The normal array based logic inverts the effect data. This si the formula to convert the x, y coordinates /// in order to do similar math /// This inverts the coordinate /// y = Math.Abs((BufferHtOffset - y) + (BufferHt - 1 + BufferHtOffset)); /// /// This offsets it to be zero based like the others /// y = y - BufferHtOffset; /// x = x - BufferWiOffset; /// See full example in Butteryfly or partial in Colorwash. /// </summary> /// <param name="numFrames"></param> /// <param name="frameBuffer"></param> protected virtual void RenderEffectByLocation(int numFrames, PixelLocationFrameBuffer frameBuffer) { throw new NotImplementedException(); }