Skip to content

Commit

Permalink
#17 experimental: Fade impl. 256 layers max on 1920x1080 [64 layers b…
Browse files Browse the repository at this point in the history
…y default]
  • Loading branch information
Art-Stea1th committed May 7, 2017
1 parent 2c1e5e7 commit 8c54bc4
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class ApplicationFacade : BindableBase, IApplicationFacade {
}

public int GenerationWidth {
get => matrix.GetLength(0);
get => generationWidth;
set {
if (matrixReadyToChange) {
Set(ref generationWidth, ValidWidth(value));
Expand All @@ -40,7 +40,7 @@ public int GenerationWidth {
}

public int GenerationHeight {
get => matrix.GetLength(1);
get => generationHeight;
set {
if (matrixReadyToChange) {
Set(ref generationHeight, ValidHeight(value));
Expand Down Expand Up @@ -115,8 +115,9 @@ private void ConfigureController(IGenerationController controller) {

private Task OnStop() { // tmp
fpsGenerator.Stop();
Matrix = null;
var resultTask = new Task(() => {
ChangeResolution(matrix.GetLength(0), matrix.GetLength(1));
ChangeResolution(GenerationWidth, GenerationHeight);
});
resultTask.Start();
return resultTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal MPSGenerationService() {
fpsCollection = new DoubleCollection { 1.0, 2.0, 3.0, 5.0, 15.0, 30.0, 60.0, 120.0, 125.0 };
timer = new DispatcherTimer();
timer.Tick += (s, e) => NextFrameTime?.Invoke();
MPS = fpsCollection.TakeWhile(f => f < 120.0).Last();
MPS = fpsCollection.TakeWhile(f => f < 60.0).Last();
}

private double ValidFps(double fps) => fps < MinFPS ? MinFPS : fps > MaxFPS ? MaxFPS : fps;
Expand Down
135 changes: 87 additions & 48 deletions Application/ASD.CellUniverse.Resources/Controls/MatrixLED.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;

namespace ASD.CellUniverse.Resources.Controls {

using System.Windows.Media.Animation;
using Helpers;

public class MatrixLED : FrameworkElement {

private int cellSize;
private Size contentSize;
private Fade fade = new Fade(64);

private WriteableBitmap mask;
private WriteableBitmap fadeMask;

public uint[,] Source { get => (uint[,])GetValue(SourceProperty); set => SetValue(SourceProperty, value); }

Expand All @@ -38,7 +41,7 @@ public class MatrixLED : FrameworkElement {

public static readonly DependencyProperty ShowFadeProperty = DependencyProperty.Register(nameof(
ShowFade), typeof(bool), typeof(MatrixLED), new FrameworkPropertyMetadata(
false));
false, OnShowFadeChanged));

static MatrixLED() => StyleProperty.OverrideMetadata(typeof(MatrixLED), new FrameworkPropertyMetadata(CreateStyle()));

Expand All @@ -48,6 +51,15 @@ private static Style CreateStyle() {
style.Seal(); return style;
}

private static void OnShowFadeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
if ((bool)e.NewValue) {
(d as MatrixLED).fade = new Fade(64);
}
else {
(d as MatrixLED).fade = null;
}
}

protected override Size MeasureOverride(Size constraint) {

var count = Source == null || Source.Length < 1
Expand All @@ -66,29 +78,41 @@ protected override Size ArrangeOverride(Size arrangeSize) {
return MeasureArrangeHelper.ComputeSize(arrangeSize, contentSize);
}

private FadeHelper fh;

protected override void OnRender(DrawingContext dc) {


RepaintLedsMask();
protected override void OnRender(DrawingContext dc) {

dc.DrawRectangle(Background, null, new Rect(new Point(), RenderSize));

// bad - code of fade using =)
if (ShowFade) {
if (fh == null) {
fh = new FadeHelper(1000, 60, Foreground, RenderSize);
}
if (fh.RenderSize != RenderSize) {
fh.RenderSize = RenderSize;
}

fh.Redraw(dc);
fh.AddImage(mask.Clone());
}
fade.Add(Source);
RepaintFadeMask();

//dc.PushOpacity(0.0, new DoubleAnimation(1.0, 0.0, TimeSpan.FromMilliseconds(1000)).CreateClock());
dc.PushOpacityMask(new ImageBrush(fadeMask));
dc.DrawRectangle(Foreground, null, new Rect(new Point(), RenderSize));
dc.Pop();
//dc.Pop();
}

RepaintLedsMask();

dc.PushOpacityMask(new ImageBrush(mask));
dc.DrawRectangle(Foreground, null, new Rect(new Point(), RenderSize));

}

private void RepaintFadeMask() {
fadeMask = BitmapHelper.Valid(fadeMask, contentSize);
if (fade != null && fade.Length > 0) {
using (var context = new WriteableContext(fadeMask)) {

if (cellSize == 1) { context.WritePixels(fade); }
else { context.WriteCells(fade, cellSize); }
}
}
}

private void RepaintLedsMask() {
Expand All @@ -102,54 +126,69 @@ private void RepaintLedsMask() {
}
}

// bad-impl.fade
private class FadeHelper {
private class Fade {

private Queue<uint[,]> history;
private int historySize;
private Brush brush;
public Size RenderSize { get; set; }

private uint[,] data;
public int Length => data.Length;

private TimeSpan time;
private Queue<ImageSource> bitmaps;
public static implicit operator uint[,](Fade fade) => fade.data;

private DoubleAnimation fadeAnimation;

public void AddImage(ImageSource image) {
bitmaps.Enqueue(image);
if (bitmaps.Count > historySize) {
bitmaps.Dequeue();
}
public Fade(int historySize) {
this.historySize = historySize > 0 ? historySize : 1;
history = new Queue<uint[,]>(historySize);
data = new uint[1, 1];
}

public void Redraw(DrawingContext dc) {
public void Add(uint[,] source) {
if (source == null || source.Length < 1) {
Clear();
return;
}
if (history.Count > 0 &&
(history.First().GetLength(0) != source.GetLength(0) ||
history.First().GetLength(1) != source.GetLength(1))) {
Clear();
}
history.Enqueue(source);

dc.PushOpacity(0.0, fadeAnimation.CreateClock());
while (history.Count > historySize) {
history.Dequeue();
}
if (history.Count > 0) {
data = Merge(history);
}
}

for (var i = 0; i < bitmaps.Count; ++i) {
dc.PushOpacityMask(new ImageBrush(bitmaps.ElementAt(i)));
dc.PushOpacity((1.0 / historySize)/* * (i + 1)*/);
public void Clear() {
history = new Queue<uint[,]>(historySize);
data = new uint[1, 1];
}

dc.DrawRectangle(brush, null, new Rect(new Point(), RenderSize));
private uint[,] Merge(IEnumerable<uint[,]> layers) {

dc.Pop();
dc.Pop();
}
dc.Pop();
}
var sumAlpha = new uint[layers.First().GetLength(0), layers.First().GetLength(1)];

public FadeHelper(int durationMilliseconds, int historySize, Brush brush, Size renderSize) {
Parallel.ForEach(layers, (layer) => {
for (var y = 0; y < layer.GetLength(1); ++y) {
for (var x = 0; x < layer.GetLength(0); ++x) {
sumAlpha[x, y] += (layer[x, y] >> 24);
}
}
});

this.historySize = historySize;
this.brush = brush;
this.RenderSize = renderSize;

// ----
var alpha = new uint[sumAlpha.GetLength(0), sumAlpha.GetLength(1)];

bitmaps = new Queue<ImageSource>(historySize);
for (var y = 0; y < sumAlpha.GetLength(1); ++y) {
for (var x = 0; x < sumAlpha.GetLength(0); ++x) {
alpha[x, y] = (sumAlpha[x, y] / (uint)historySize) << 24;
}
}

time = TimeSpan.FromMilliseconds(durationMilliseconds);
fadeAnimation = new DoubleAnimation(1.0, 0.0, time);
return alpha;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Application/ASD.CellUniverse/Shell.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
Source="{Binding Facade.Matrix}"
Foreground="{StaticResource NearStarBrush}"
RenderOptions.BitmapScalingMode="{Binding SelectedScalingMode}"
ShowFade="False"/>
ShowFade="True"/>
</Border>
<Grid
Grid.Column="1"
Expand Down
Binary file modified Screenshots/main.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8c54bc4

Please sign in to comment.