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 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) { 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; }
/// <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(); }
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 level = LevelCurve.GetValue(GetEffectTimeIntervalPosition(frame)*100)/100; using (var bitmap = new Bitmap(BufferWi, BufferHt)) { InitialRender(frame, bitmap); foreach (IGrouping<int, ElementLocation> elementLocations in nodes) { foreach (var elementLocation in elementLocations) { CalculatePixel(elementLocation.X, elementLocation.Y, bitmap, level, frameBuffer); } } } } }
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) { 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++) { 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; } } } } }