New Release Build 3.5.6-RC5

This commit is contained in:
Sven Vogel 2021-06-11 13:36:55 +02:00
parent 0297d922ab
commit 5a9fb1e9c9
60 changed files with 497 additions and 368 deletions

View File

@ -1,11 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Matrix_App namespace Matrix_App
{ {
@ -15,44 +11,45 @@ namespace Matrix_App
public class GifWriter : IDisposable public class GifWriter : IDisposable
{ {
#region Fields #region Fields
const long SourceGlobalColorInfoPosition = 10,
SourceImageBlockPosition = 789; private const long SourceGlobalColorInfoPosition = 10, SourceImageBlockPosition = 789;
readonly BinaryWriter _writer; private readonly object syncLock = new object();
bool _firstFrame = true; private readonly BinaryWriter writer;
readonly object _syncLock = new object(); private bool firstFrame = true;
#endregion #endregion
/// <summary> /// <summary>
/// Creates a new instance of GifWriter. /// Creates a new instance of GifWriter.
/// </summary> /// </summary>
/// <param name="OutStream">The <see cref="Stream"/> to output the Gif to.</param> /// <param name="outStream">The <see cref="Stream"/> to output the Gif to.</param>
/// <param name="DefaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param> /// <param name="defaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param>
/// <param name="Repeat">No of times the Gif should repeat... -1 not to repeat, 0 to repeat indefinitely.</param> /// <param name="repeat">No of times the Gif should repeat... -1 not to repeat, 0 to repeat indefinitely.</param>
public GifWriter(Stream OutStream, int DefaultFrameDelay = 500, int Repeat = 0) public GifWriter(Stream outStream, int defaultFrameDelay = 500, int repeat = 0)
{ {
if (OutStream == null) if (outStream == null)
throw new ArgumentNullException(nameof(OutStream)); throw new ArgumentNullException(nameof(outStream));
if (DefaultFrameDelay <= 0) if (defaultFrameDelay <= 0)
throw new ArgumentOutOfRangeException(nameof(DefaultFrameDelay)); throw new ArgumentOutOfRangeException(nameof(defaultFrameDelay));
if (Repeat < -1) if (repeat < -1)
throw new ArgumentOutOfRangeException(nameof(Repeat)); throw new ArgumentOutOfRangeException(nameof(repeat));
_writer = new BinaryWriter(OutStream); writer = new BinaryWriter(outStream);
this.DefaultFrameDelay = DefaultFrameDelay; this.DefaultFrameDelay = defaultFrameDelay;
this.Repeat = Repeat; this.Repeat = repeat;
} }
/// <summary> /// <summary>
/// Creates a new instance of GifWriter. /// Creates a new instance of GifWriter.
/// </summary> /// </summary>
/// <param name="FileName">The path to the file to output the Gif to.</param> /// <param name="fileName">The path to the file to output the Gif to.</param>
/// <param name="DefaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param> /// <param name="defaultFrameDelay">Default Delay between consecutive frames... FrameRate = 1000 / DefaultFrameDelay.</param>
/// <param name="Repeat">No of times the Gif should repeat... -1 not to repeat, 0 to repeat indefinitely.</param> /// <param name="repeat">No of times the Gif should repeat... -1 not to repeat, 0 to repeat indefinitely.</param>
public GifWriter(string FileName, int DefaultFrameDelay = 500, int Repeat = -1) public GifWriter(string fileName, int defaultFrameDelay = 500, int repeat = -1)
: this(new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read), DefaultFrameDelay, Repeat) { } : this(new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read), defaultFrameDelay, repeat) { }
#region Properties #region Properties
/// <summary> /// <summary>
@ -80,114 +77,114 @@ namespace Matrix_App
/// <summary> /// <summary>
/// Adds a frame to this animation. /// Adds a frame to this animation.
/// </summary> /// </summary>
/// <param name="Image">The image to add</param> /// <param name="image">The image to add</param>
/// <param name="Delay">Delay in Milliseconds between this and last frame... 0 = <see cref="DefaultFrameDelay"/></param> /// <param name="delay">Delay in Milliseconds between this and last frame... 0 = <see cref="DefaultFrameDelay"/></param>
public void WriteFrame(Image Image, int Delay = 0) public void WriteFrame(Image image, int delay = 0)
{ {
lock (_syncLock) lock (syncLock)
using (var gifStream = new MemoryStream()) using (var gifStream = new MemoryStream())
{ {
Image.Save(gifStream, ImageFormat.Gif); image.Save(gifStream, ImageFormat.Gif);
// Steal the global color table info // Steal the global color table info
if (_firstFrame) if (firstFrame)
InitHeader(gifStream, _writer, Image.Width, Image.Height); InitHeader(gifStream, writer, image.Width, image.Height);
WriteGraphicControlBlock(gifStream, _writer, Delay == 0 ? DefaultFrameDelay : Delay); WriteGraphicControlBlock(gifStream, writer, delay == 0 ? DefaultFrameDelay : delay);
WriteImageBlock(gifStream, _writer, !_firstFrame, 0, 0, Image.Width, Image.Height); WriteImageBlock(gifStream, writer, !firstFrame, 0, 0, image.Width, image.Height);
} }
if (_firstFrame) if (firstFrame)
_firstFrame = false; firstFrame = false;
} }
#region Write #region Write
void InitHeader(Stream SourceGif, BinaryWriter Writer, int Width, int Height) private void InitHeader(Stream sourceGif, BinaryWriter writer, int width, int height)
{ {
// File Header // File Header
Writer.Write("GIF".ToCharArray()); // File type writer.Write("GIF".ToCharArray()); // File type
Writer.Write("89a".ToCharArray()); // File Version writer.Write("89a".ToCharArray()); // File Version
Writer.Write((short)(DefaultWidth == 0 ? Width : DefaultWidth)); // Initial Logical Width writer.Write((short)(DefaultWidth == 0 ? width : DefaultWidth)); // Initial Logical Width
Writer.Write((short)(DefaultHeight == 0 ? Height : DefaultHeight)); // Initial Logical Height writer.Write((short)(DefaultHeight == 0 ? height : DefaultHeight)); // Initial Logical Height
SourceGif.Position = SourceGlobalColorInfoPosition; sourceGif.Position = SourceGlobalColorInfoPosition;
Writer.Write((byte)SourceGif.ReadByte()); // Global Color Table Info writer.Write((byte)sourceGif.ReadByte()); // Global Color Table Info
Writer.Write((byte)0); // Background Color Index writer.Write((byte)0); // Background Color Index
Writer.Write((byte)0); // Pixel aspect ratio writer.Write((byte)0); // Pixel aspect ratio
WriteColorTable(SourceGif, Writer); WriteColorTable(sourceGif, writer);
// App Extension Header for Repeating // App Extension Header for Repeating
if (Repeat == -1) if (Repeat == -1)
return; return;
Writer.Write(unchecked((short)0xff21)); // Application Extension Block Identifier writer.Write(unchecked((short)0xff21)); // Application Extension Block Identifier
Writer.Write((byte)0x0b); // Application Block Size writer.Write((byte)0x0b); // Application Block Size
Writer.Write("NETSCAPE2.0".ToCharArray()); // Application Identifier writer.Write("NETSCAPE2.0".ToCharArray()); // Application Identifier
Writer.Write((byte)3); // Application block length writer.Write((byte)3); // Application block length
Writer.Write((byte)1); writer.Write((byte)1);
Writer.Write((short)Repeat); // Repeat count for images. writer.Write((short)Repeat); // Repeat count for images.
Writer.Write((byte)0); // terminator writer.Write((byte)0); // terminator
} }
static void WriteColorTable(Stream SourceGif, BinaryWriter Writer) static void WriteColorTable(Stream sourceGif, BinaryWriter writer)
{ {
SourceGif.Position = 13; // Locating the image color table sourceGif.Position = 13; // Locating the image color table
var colorTable = new byte[768]; var colorTable = new byte[768];
SourceGif.Read(colorTable, 0, colorTable.Length); sourceGif.Read(colorTable, 0, colorTable.Length);
Writer.Write(colorTable, 0, colorTable.Length); writer.Write(colorTable, 0, colorTable.Length);
} }
static void WriteGraphicControlBlock(Stream SourceGif, BinaryWriter Writer, int FrameDelay) static void WriteGraphicControlBlock(Stream sourceGif, BinaryWriter writer, int frameDelay)
{ {
SourceGif.Position = 781; // Locating the source GCE sourceGif.Position = 781; // Locating the source GCE
var blockhead = new byte[8]; var blockhead = new byte[8];
SourceGif.Read(blockhead, 0, blockhead.Length); // Reading source GCE sourceGif.Read(blockhead, 0, blockhead.Length); // Reading source GCE
Writer.Write(unchecked((short)0xf921)); // Identifier writer.Write(unchecked((short)0xf921)); // Identifier
Writer.Write((byte)0x04); // Block Size writer.Write((byte)0x04); // Block Size
Writer.Write((byte)(blockhead[3] & 0xf7 | 0x08)); // Setting disposal flag writer.Write((byte)(blockhead[3] & 0xf7 | 0x08)); // Setting disposal flag
Writer.Write((short)(FrameDelay / 10)); // Setting frame delay writer.Write((short)(frameDelay / 10)); // Setting frame delay
Writer.Write(blockhead[6]); // Transparent color index writer.Write(blockhead[6]); // Transparent color index
Writer.Write((byte)0); // Terminator writer.Write((byte)0); // Terminator
} }
static void WriteImageBlock(Stream SourceGif, BinaryWriter Writer, bool IncludeColorTable, int X, int Y, int Width, int Height) static void WriteImageBlock(Stream sourceGif, BinaryWriter writer, bool includeColorTable, int x, int y, int width, int height)
{ {
SourceGif.Position = SourceImageBlockPosition; // Locating the image block sourceGif.Position = SourceImageBlockPosition; // Locating the image block
var header = new byte[11]; var header = new byte[11];
SourceGif.Read(header, 0, header.Length); sourceGif.Read(header, 0, header.Length);
Writer.Write(header[0]); // Separator writer.Write(header[0]); // Separator
Writer.Write((short)X); // Position X writer.Write((short)x); // Position X
Writer.Write((short)Y); // Position Y writer.Write((short)y); // Position Y
Writer.Write((short)Width); // Width writer.Write((short)width); // Width
Writer.Write((short)Height); // Height writer.Write((short)height); // Height
if (IncludeColorTable) // If first frame, use global color table - else use local if (includeColorTable) // If first frame, use global color table - else use local
{ {
SourceGif.Position = SourceGlobalColorInfoPosition; sourceGif.Position = SourceGlobalColorInfoPosition;
Writer.Write((byte)(SourceGif.ReadByte() & 0x3f | 0x80)); // Enabling local color table writer.Write((byte)(sourceGif.ReadByte() & 0x3f | 0x80)); // Enabling local color table
WriteColorTable(SourceGif, Writer); WriteColorTable(sourceGif, writer);
} }
else Writer.Write((byte)(header[9] & 0x07 | 0x07)); // Disabling local color table else writer.Write((byte)(header[9] & 0x07 | 0x07)); // Disabling local color table
Writer.Write(header[10]); // LZW Min Code Size writer.Write(header[10]); // LZW Min Code Size
// Read/Write image data // Read/Write image data
SourceGif.Position = SourceImageBlockPosition + header.Length; sourceGif.Position = SourceImageBlockPosition + header.Length;
var dataLength = SourceGif.ReadByte(); var dataLength = sourceGif.ReadByte();
while (dataLength > 0) while (dataLength > 0)
{ {
var imgData = new byte[dataLength]; var imgData = new byte[dataLength];
SourceGif.Read(imgData, 0, dataLength); sourceGif.Read(imgData, 0, dataLength);
Writer.Write((byte)dataLength); writer.Write((byte)dataLength);
Writer.Write(imgData, 0, dataLength); writer.Write(imgData, 0, dataLength);
dataLength = SourceGif.ReadByte(); dataLength = sourceGif.ReadByte();
} }
Writer.Write((byte)0); // Terminator writer.Write((byte)0); // Terminator
} }
#endregion #endregion
@ -197,10 +194,10 @@ namespace Matrix_App
public void Dispose() public void Dispose()
{ {
// Complete File // Complete File
_writer.Write((byte)0x3b); // File Trailer writer.Write((byte)0x3b); // File Trailer
_writer.BaseStream.Dispose(); writer.BaseStream.Dispose();
_writer.Dispose(); writer.Dispose();
} }
} }
} }

View File

@ -38,5 +38,6 @@
<EmbeddedResource Remove="SplashScreen.resx" /> <EmbeddedResource Remove="SplashScreen.resx" />
<None Remove="Resources\pfüsikuh.png" /> <None Remove="Resources\pfüsikuh.png" />
<None Remove="Utils.cs~" /> <None Remove="Utils.cs~" />
<None Remove="Resources\pfüsikuh.png~" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -10,13 +10,13 @@ namespace Matrix_App
/// </summary> /// </summary>
private System.ComponentModel.IContainer components = null; private System.ComponentModel.IContainer components = null;
/// <summary> /// <summary>
/// Clean up any resources being used. /// Clean up any resources being used.
/// </summary> /// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
IMAGE_DRAWER.Stop();
MatrixGifGenerator.Close(); MatrixGifGenerator.Close();
commandQueue.Close(); commandQueue.Close();
if (disposing && (components != null)) if (disposing && (components != null))
@ -47,7 +47,6 @@ namespace Matrix_App
this.label3 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label();
this.FramesLabel = new System.Windows.Forms.Label(); this.FramesLabel = new System.Windows.Forms.Label();
this.configButton = new System.Windows.Forms.Button(); this.configButton = new System.Windows.Forms.Button();
this.read_me = new System.Windows.Forms.RichTextBox();
this.DelayLabel = new System.Windows.Forms.Label(); this.DelayLabel = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
@ -81,7 +80,7 @@ namespace Matrix_App
this.Play = new System.Windows.Forms.Button(); this.Play = new System.Windows.Forms.Button();
this.Apply = new System.Windows.Forms.Button(); this.Apply = new System.Windows.Forms.Button();
this.DragDropButton = new System.Windows.Forms.Button(); this.DragDropButton = new System.Windows.Forms.Button();
this.matrixView = new Matrix_App.Matrix(); matrixView = new Matrix_App.Matrix();
this.panel3 = new System.Windows.Forms.Panel(); this.panel3 = new System.Windows.Forms.Panel();
this.Modus.SuspendLayout(); this.Modus.SuspendLayout();
this.tabPage1.SuspendLayout(); this.tabPage1.SuspendLayout();
@ -140,7 +139,6 @@ namespace Matrix_App
this.tabPage1.Controls.Add(this.label3); this.tabPage1.Controls.Add(this.label3);
this.tabPage1.Controls.Add(this.FramesLabel); this.tabPage1.Controls.Add(this.FramesLabel);
this.tabPage1.Controls.Add(this.configButton); this.tabPage1.Controls.Add(this.configButton);
this.tabPage1.Controls.Add(this.read_me);
this.tabPage1.Controls.Add(this.DelayLabel); this.tabPage1.Controls.Add(this.DelayLabel);
this.tabPage1.Controls.Add(this.label4); this.tabPage1.Controls.Add(this.label4);
this.tabPage1.Controls.Add(this.label2); this.tabPage1.Controls.Add(this.label2);
@ -248,17 +246,6 @@ namespace Matrix_App
this.configButton.UseVisualStyleBackColor = true; this.configButton.UseVisualStyleBackColor = true;
this.configButton.Click += new System.EventHandler(this.ConfigButton_Click); this.configButton.Click += new System.EventHandler(this.ConfigButton_Click);
// //
// read_me
//
this.read_me.Dock = System.Windows.Forms.DockStyle.Bottom;
this.read_me.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.read_me.Location = new System.Drawing.Point(0, 344);
this.read_me.Name = "read_me";
this.read_me.ReadOnly = true;
this.read_me.Size = new System.Drawing.Size(232, 291);
this.read_me.TabIndex = 5;
this.read_me.Text = "Reads Me";
//
// DelayLabel // DelayLabel
// //
this.DelayLabel.AutoSize = true; this.DelayLabel.AutoSize = true;
@ -689,16 +676,16 @@ namespace Matrix_App
// //
// matrixView // matrixView
// //
this.matrixView.Dock = System.Windows.Forms.DockStyle.Fill; matrixView.Dock = System.Windows.Forms.DockStyle.Fill;
this.matrixView.Location = new System.Drawing.Point(16, 16); matrixView.Location = new System.Drawing.Point(16, 16);
this.matrixView.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); matrixView.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.matrixView.Name = "matrixView"; matrixView.Name = "matrixView";
this.matrixView.Size = new System.Drawing.Size(627, 557); matrixView.Size = new System.Drawing.Size(627, 557);
this.matrixView.TabIndex = 3; matrixView.TabIndex = 3;
// //
// panel3 // panel3
// //
this.panel3.Controls.Add(this.matrixView); this.panel3.Controls.Add(matrixView);
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill; this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(240, 0); this.panel3.Location = new System.Drawing.Point(240, 0);
this.panel3.Name = "panel3"; this.panel3.Name = "panel3";
@ -757,7 +744,6 @@ namespace Matrix_App
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label4;
private System.Windows.Forms.RichTextBox read_me;
private System.Windows.Forms.Panel ToolBar; private System.Windows.Forms.Panel ToolBar;
private System.Windows.Forms.NumericUpDown matrixHeight; private System.Windows.Forms.NumericUpDown matrixHeight;
private System.Windows.Forms.NumericUpDown matrixWidth; private System.Windows.Forms.NumericUpDown matrixWidth;
@ -782,7 +768,7 @@ namespace Matrix_App
private System.Windows.Forms.Button Save; private System.Windows.Forms.Button Save;
private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button configButton; private System.Windows.Forms.Button configButton;
private Matrix matrixView; private static Matrix matrixView;
private System.Windows.Forms.TabPage pregeneratedMods; private System.Windows.Forms.TabPage pregeneratedMods;
private System.Windows.Forms.FlowLayoutPanel pregeneratedModsBase; private System.Windows.Forms.FlowLayoutPanel pregeneratedModsBase;
private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Panel panel2;

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
@ -44,8 +45,10 @@ namespace Matrix_App
/// <summary> /// <summary>
/// Gif like frame video buffer /// Gif like frame video buffer
/// </summary> /// </summary>
public byte[][] gifBuffer = CreateImageRGB_NT(MatrixStartWidth, MatrixStartHeight, MatrixStartFrames); public static byte[][] gifBuffer = CreateImageRGB_NT(MatrixStartWidth, MatrixStartHeight, MatrixStartFrames);
public static readonly ThreadQueue IMAGE_DRAWER = new ThreadQueue("Matrix Image Drawer", 4);
#endregion #endregion
#region Setup #region Setup
@ -595,24 +598,37 @@ namespace Matrix_App
private void Timeline_ValueChanged(object sender, EventArgs e) private void Timeline_ValueChanged(object sender, EventArgs e)
{ {
int width = matrixView.matrixWidth(); var timeFrame = Timeline.Value;
int height = matrixView.matrixHeight();
IMAGE_DRAWER.Enqueue(() =>
for (int y = 0; y < height; y++)
{ {
int index = y * width; WriteImage(gifBuffer[timeFrame]);
var width = matrixView.matrixWidth();
var height = matrixView.matrixHeight();
for (int x = 0; x < width; x++) lock (matrixView)
{ {
int tmp = (index + x) * 3; for (var y = 0; y < height; y++)
{
var index = y * width;
var color = Color.FromArgb(gifBuffer[Timeline.Value][tmp + 1], gifBuffer[Timeline.Value][tmp], gifBuffer[Timeline.Value][tmp + 2]); for (var x = 0; x < width; x++)
{
var tmp = (index + x) * 3;
matrixView.SetPixelNoRefresh(x, y, color); var color = Color.FromArgb(gifBuffer[timeFrame][tmp + 1], gifBuffer[timeFrame][tmp], gifBuffer[timeFrame][tmp + 2]);
matrixView.SetPixelNoRefresh(x, y, color);
}
}
} }
}
matrixView.Refresh();
return true;
});
matrixView.Refresh(); matrixView.Refresh();
WriteImage(gifBuffer[Timeline.Value]);
} }
/// <summary> /// <summary>

View File

@ -1,11 +1,10 @@
using Matrix_App.PregeneratedMods; using Matrix_App.PregeneratedMods;
using System; using System;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using Matrix_App.PregeneratedMods.reflection;
using static Matrix_App.Utils; using static Matrix_App.Utils;
using static Matrix_App.Defaults; using static Matrix_App.Defaults;
using Timer = System.Windows.Forms.Timer; using Timer = System.Windows.Forms.Timer;
@ -26,33 +25,46 @@ namespace Matrix_App
new Grayscale(), new Grayscale(),
new Invert() new Invert()
}; };
private static readonly Timer PlaybackTimer = new Timer(); // Static generator accessible members
// must work on multiple threads
private static int _playbackFrame; protected static int totalFrames; // total amount of frames to generate
protected static byte[][]? actualStore; // image copy of previous GIF for generator
protected static int totalFrames;
protected static byte[][]? actualStore;
protected static int width; protected static int width;
protected static int height; protected static int height;
// updates the preview matrix for animation
private static readonly Timer PlaybackTimer = new Timer();
// current frame to play
private static int _playbackFrame;
// temporary buffer for storing snapshots for buttons
private static readonly byte[][] Snapshot; private static readonly byte[][] Snapshot;
private static byte[][] _initialBuffer; private static byte[][] _initialBuffer; // temporary buffer for swapping
// Generator renderer
private static readonly ThreadQueue Renderer; private static readonly ThreadQueue Renderer;
// Current generator to use
private static MatrixGifGenerator? _generator; private static MatrixGifGenerator? _generator;
static MatrixGifGenerator() static MatrixGifGenerator()
{ {
PlaybackTimer.Tick += PlaybackFrame; PlaybackTimer.Tick += PlaybackFrame;
// Generate buffer for button filter snapshots
Snapshot = CreateImageRGB_NT(FilterPreviewWidth, FilterPreviewHeight, 1); Snapshot = CreateImageRGB_NT(FilterPreviewWidth, FilterPreviewHeight, 1);
_initialBuffer = CreateImageRGB_NT(FilterPreviewWidth, FilterPreviewHeight, 1); _initialBuffer = CreateImageRGB_NT(FilterPreviewWidth, FilterPreviewHeight, 1);
Renderer = new ThreadQueue("Matrix Gif Renderer", 2); Renderer = new ThreadQueue("Matrix Gif Renderer", 2);
} }
/// <summary>
/// Plays the next frame of what is currently in the animation buffer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void PlaybackFrame(object? sender, EventArgs e) private static void PlaybackFrame(object? sender, EventArgs e)
{ {
if (_playbackFrame >= _animationBuffer.Length - 1) if (_playbackFrame >= _animationBuffer.Length - 1)
@ -65,12 +77,25 @@ namespace Matrix_App
_playbackFrame++; _playbackFrame++;
} }
/// <summary>
/// Colors a single fragment at the specified pixel location (x|y) at frame frame.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="u">Normalized pixel X-coordinate</param>
/// <param name="v">Normalized pixel Y-coordinate</param>
/// <param name="frame">Current frame</param>
/// <param name="r">Pixel Red value in range [0, 1] (saturated)</param>
/// <param name="g">Pixel Green value in range [0, 1] (saturated)</param>
/// <param name="b">Pixel Blue value in range [0, 1] (saturated)</param>
protected abstract void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b); protected abstract void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b);
// Buffer to store generator result in
private static byte[][] _animationBuffer = null!; private static byte[][] _animationBuffer = null!;
// Main application reference
private static MatrixDesignerMain _form = null!; private static MatrixDesignerMain _form = null!;
private static Matrix _preview = null!; private static Matrix _preview = null!; // preview matrix
public static void GenerateBaseUi(FlowLayoutPanel anchor, Matrix matrix, MatrixDesignerMain form1) public static void GenerateBaseUi(FlowLayoutPanel anchor, Matrix matrix, MatrixDesignerMain form1)
{ {
@ -79,10 +104,11 @@ namespace Matrix_App
// generate access buttons for available generators // generate access buttons for available generators
foreach (var generator in Generators) foreach (var generator in Generators)
{ {
// generate button
var button = new Button var button = new Button
{ {
Width = 215, Width = 215,
Text = GetBetterFieldName(generator.GetType().Name) Text = FieldWidgets.GetBetterFieldName(generator.GetType().Name)
}; };
button.Click += (sender, e) => OpenGeneratorUi(generator, matrix); button.Click += (sender, e) => OpenGeneratorUi(generator, matrix);
button.Image = CreateSnapshot(generator); button.Image = CreateSnapshot(generator);
@ -124,16 +150,34 @@ namespace Matrix_App
Thread.Sleep(50); Thread.Sleep(50);
} }
} }
private static void OpenGeneratorUi(MatrixGifGenerator matrixGifGenerator, Matrix matrix) private static void OpenGeneratorUi(MatrixGifGenerator matrixGifGenerator, Matrix matrix)
{ {
_generator = matrixGifGenerator; _generator = matrixGifGenerator;
if (!ShowEditDialog(matrix)) if (!ShowEditDialog(matrix))
return; return;
FlipColorStoreRG_GR(_animationBuffer, _form.gifBuffer); if (Renderer.HasWork())
_form.ResetTimeline(); {
if (DialogResult.Yes ==
MessageBox.Show($@"The filter {_generator.GetType().Name} hasn't finished yet, wait for completion?",
@"Filter incomplete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning))
{
BlockBuffer();
FlipColorStoreRG_GR(_animationBuffer, MatrixDesignerMain.gifBuffer);
_form.ResetTimeline();
}
else
{
MessageBox.Show($@"The filter {_generator.GetType().Name} has timedout", @"Failed applying filter", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
FlipColorStoreRG_GR(_animationBuffer, MatrixDesignerMain.gifBuffer);
_form.ResetTimeline();
}
} }
private static void SetGlobalArgs(int w, int h, int f, in byte[][]? previous, in byte[][] preview) private static void SetGlobalArgs(int w, int h, int f, in byte[][]? previous, in byte[][] preview)
@ -149,6 +193,11 @@ namespace Matrix_App
private static bool ShowEditDialog(Matrix matrix) private static bool ShowEditDialog(Matrix matrix)
{ {
if (_generator == null)
{
return false;
}
var success = false; var success = false;
Initialize(matrix); Initialize(matrix);
@ -160,7 +209,7 @@ namespace Matrix_App
Text = @"Vorgenerierter Modus: " + _generator.GetType().Name Text = @"Vorgenerierter Modus: " + _generator.GetType().Name
}; };
var confirmation = new Button {Text = "Apply", Anchor = AnchorStyles.Top | AnchorStyles.Left}; var confirmation = new Button {Text = @"Apply", Anchor = AnchorStyles.Top | AnchorStyles.Left};
confirmation.Click += (sender, e) => { confirmation.Click += (sender, e) => {
success = true; success = true;
prompt.Close(); prompt.Close();
@ -175,20 +224,21 @@ namespace Matrix_App
AutoSize = true AutoSize = true
}; };
var fields = _generator.GetType().GetFields();
PlaybackTimer.Interval = _form.GetDelayTime(); PlaybackTimer.Interval = _form.GetDelayTime();
PlaybackTimer.Enabled = true; PlaybackTimer.Enabled = true;
var type = _generator.GetType();
var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
CreateDivider(controlPanel, 2); CreateDivider(controlPanel, 2);
foreach (var field in fields) foreach (var field in fields)
{ {
if (field.IsStatic || !field.IsPublic) var widget = FieldWidgets.GetFieldWidget(field, _generator, InvokeGenerator);
if (widget == null)
continue; continue;
var fieldValue = field.GetValue(_generator); controlPanel.Controls.AddRange(widget);
controlPanel.Controls.AddRange(GetFieldUi(field, _generator.GetType(), fieldValue, _generator));
CreateDivider(controlPanel, 1); CreateDivider(controlPanel, 1);
} }
@ -218,130 +268,17 @@ namespace Matrix_App
return success; return success;
} }
private static Control[] GetFieldUi(FieldInfo field, Type clazz, object? fieldValue, MatrixGifGenerator generator)
{
var panel = new FlowLayoutPanel
{
FlowDirection = FlowDirection.LeftToRight,
Anchor = AnchorStyles.Top | AnchorStyles.Left,
AutoSize = true
};
var title = GetBetterFieldName(field.Name);
var description = new Label();
if (Attribute.GetCustomAttribute(field, typeof(UiDescriptionAttribute)) is UiDescriptionAttribute desc)
{
title = desc.title;
description.Text = desc.description;
description.ForeColor = Color.Gray;
description.Height += 10;
description.AutoSize = true;
}
panel.Controls.Add(new Label
{
TextAlign = ContentAlignment.MiddleLeft,
Text = title,
Dock = DockStyle.Left,
Anchor = AnchorStyles.Top | AnchorStyles.Left,
Width = 100
});
switch (fieldValue)
{
case int value:
{
var upDown = new NumericUpDown
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Right,
Width = 360,
Value = value
};
upDown.ValueChanged += (a, b) =>
{
field.SetValue(generator, (int) upDown.Value);
InvokeGenerator();
};
panel.Controls.Add(upDown);
break;
}
case bool value1:
{
var upDown = new CheckBox
{
Dock = DockStyle.Fill, Anchor = AnchorStyles.Top | AnchorStyles.Right, Checked = value1
};
upDown.CheckedChanged += (a, b) =>
{
field.SetValue(generator, (bool) upDown.Checked);
InvokeGenerator();
};
panel.Controls.Add(upDown);
break;
}
case float floatValue:
{
var upDown = new TrackBar
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Right,
Maximum = 100,
Minimum = 0,
Value = (int) (floatValue * 100.0f),
TickFrequency = 10,
Width = 360
};
upDown.ValueChanged += (a, b) =>
{
field.SetValue(generator, upDown.Value / 1e2f);
InvokeGenerator();
};
panel.Controls.Add(upDown);
break;
}
}
return new Control[] {description, panel};
}
/// <summary>
/// Generates a new name from standard class names
/// Example: SomeClassA --> some class a
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private static string GetBetterFieldName(string name)
{
var groups = Regex.Match(name, @"([A-Z]*[a-z]+)([A-Z]+[a-z]*)|(.*)").Groups;
var newName = "";
for (var c = 1; c < groups.Count; c++)
{
newName += groups[c].Value.ToLower() + " ";
}
return newName;
}
private static void Initialize(in Matrix matrix) private static void Initialize(in Matrix matrix)
{ {
// Create new initial buffer and copy what ever was in the Gif buffer to it // Create new initial buffer and copy what ever was in the Gif buffer to it
_initialBuffer = CreateImageRGB_NT(matrix.matrixWidth(), matrix.matrixHeight(), _form.gifBuffer.Length); _initialBuffer = CreateImageRGB_NT(matrix.matrixWidth(), matrix.matrixHeight(), MatrixDesignerMain.gifBuffer.Length);
FlipColorStoreRG_GR(_form.gifBuffer, _initialBuffer); FlipColorStoreRG_GR(MatrixDesignerMain.gifBuffer, _initialBuffer);
// Set Generator args // Set Generator args
SetGlobalArgs(matrix.matrixWidth(), SetGlobalArgs(matrix.matrixWidth(),
matrix.matrixHeight(), matrix.matrixHeight(),
_form.gifBuffer.Length - 1, MatrixDesignerMain.gifBuffer.Length - 1,
_initialBuffer, _initialBuffer,
CreateImageRGB_NT(matrix.matrixWidth(), matrix.matrixHeight(), _form.gifBuffer.Length) CreateImageRGB_NT(matrix.matrixWidth(), matrix.matrixHeight(), MatrixDesignerMain.gifBuffer.Length)
); );
// Create preview matrix // Create preview matrix
@ -356,13 +293,14 @@ namespace Matrix_App
/// Adds a separating line to the controls /// Adds a separating line to the controls
/// </summary> /// </summary>
/// <param name="controlPanel"></param> /// <param name="controlPanel"></param>
private static void CreateDivider(Control controlPanel, int height) /// <param name="lineHeight"></param>
private static void CreateDivider(Control controlPanel, int lineHeight)
{ {
var divider = new Label var divider = new Label
{ {
BorderStyle = BorderStyle.Fixed3D, BorderStyle = BorderStyle.Fixed3D,
AutoSize = false, AutoSize = false,
Height = height, Height = lineHeight,
Width = 500 Width = 500
}; };
@ -383,7 +321,7 @@ namespace Matrix_App
{ {
var v = y / (float)height; var v = y / (float)height;
_generator.ColorFragment(x, y, u, v, frame, out var r, out var g, out var b); _generator!.ColorFragment(x, y, u, v, frame, out var r, out var g, out var b);
var index = (x + y * width) * 3; var index = (x + y * width) * 3;

View File

@ -1,12 +1,14 @@
using System; using System;
using Matrix_App.PregeneratedMods.reflection;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public sealed class Boxblur : MatrixGifGenerator public sealed class Boxblur : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Blur size", description: "The side length of the bounding square used to blur in pixels")] [UiWidget]
public int blurSize = 2; [UiDescription(title: "Blur size", description: "The side length of the bounding square used to blur in pixels")]
private int blurSize = 2;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {

View File

@ -1,47 +1,58 @@
using System; using System;
using System.Collections.Generic; using Matrix_App.PregeneratedMods.reflection;
using System.Text;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public sealed class ColorAdjust : MatrixGifGenerator public class ColorAdjust : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Tone offset", description: "Sets an additional offset to the pixels hue")] [UiWidget]
public float hueOffset = 0.0f; [UiDescription(title: "Tone offset", description: "Sets an additional offset to the pixels hue")]
[UiDescriptionAttribute(title: "Saturation boost", description: "Decreases or increases saturation")] private float hueOffset = 0.0f;
public float saturationBoost = 0.5f;
[UiDescriptionAttribute(title: "Brightness boost", description: "Decreases or increases brightness")] [UiWidget]
public float valueBoost = 0.5f; [UiDescription(title: "Saturation boost", description: "Decreases or increases saturation")]
private float saturationBoost = 0.5f;
[UiWidget]
[UiDescription(title: "Brightness boost", description: "Decreases or increases brightness")]
private float valueBoost = 0.5f;
[UiDescriptionAttribute(title: "Red boost", description: "Decreases or increases Red")] [UiWidget]
public float redBoost = 0.5f; [UiDescription(title: "Red boost", description: "Decreases or increases Red")]
[UiDescriptionAttribute(title: "Green boost", description: "Decreases or increases Green")] private float redBoost = 0.5f;
public float greenBoost = 0.5f;
[UiDescriptionAttribute(title: "Blue boost", description: "Decreases or increases Blue")] [UiWidget]
public float blueBoost = 0.5f; [UiDescription(title: "Green boost", description: "Decreases or increases Green")]
private float greenBoost = 0.5f;
[UiWidget]
[UiDescription(title: "Blue boost", description: "Decreases or increases Blue")]
private float blueBoost = 0.5f;
private float boost(float x, float y) private static float Boost(float x, float y)
{ {
return Math.Clamp(x + (y - 0.5f) * 2.0f, 0.0f, 1.0f); return Math.Clamp(x + (y - 0.5f) * 2.0f, 0.0f, 1.0f);
} }
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
SampleFrame(actualStore, frame, x, y, width, out float tr, out float tg, out float tb); SampleFrame(actualStore!, frame, x, y, width, out float tr, out float tg, out float tb);
// Adjust HSV
HsvFromRgb(tr, tg, tb, out float h, out float s, out float value); HsvFromRgb(tr, tg, tb, out float h, out float s, out float value);
h = h / 360.0f + hueOffset; h = h / 360.0f + hueOffset;
h = (h - MathF.Floor(h)) * 360.0f; h = (h - MathF.Floor(h)) * 360.0f;
s = boost(s, saturationBoost); s = Boost(s, saturationBoost);
value = boost(value, valueBoost); value = Boost(value, valueBoost);
// Adjust RGB
RgbFromHsv(h, s, value, out tr, out tg, out tb); RgbFromHsv(h, s, value, out tr, out tg, out tb);
r = boost(tr, redBoost); r = Boost(tr, redBoost);
g = boost(tg, greenBoost); g = Boost(tg, greenBoost);
b = boost(tb, blueBoost); b = Boost(tb, blueBoost);
} }
} }
} }

View File

@ -1,18 +1,17 @@
using System; using Matrix_App.PregeneratedMods.reflection;
using System.Collections.Generic;
using System.Text;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public sealed class Grayscale : MatrixGifGenerator public sealed class Grayscale : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "use Luminance", description: "Use luminance as defined by ITU-R BT.709 as grayscale output")] [UiWidget]
public bool byLuminance = false; [UiDescription(title: "use Luminance", description: "Use luminance as defined by ITU-R BT.709 as grayscale output")]
private bool byLuminance = false;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
SampleFrame(actualStore, frame, x, y, width, out float lr, out float lg, out float lb); SampleFrame(actualStore!, frame, x, y, width, out float lr, out float lg, out float lb);
if (byLuminance) if (byLuminance)
{ {

View File

@ -1,19 +1,16 @@
using System; using static Matrix_App.GifGeneratorUtils;
using System.Collections.Generic;
using System.Text;
using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
class Invert : MatrixGifGenerator public sealed class Invert : MatrixGifGenerator
{ {
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
SampleFrame(actualStore, frame, x, y, width, out float lr, out float lg, out float lb); SampleFrame(actualStore!, frame, x, y, width, out float lr, out float lg, out float lb);
r = 1- lr; r = 1 - lr;
g = 1 -lg; g = 1 - lg;
b = 1 -lb; b = 1 - lb;
} }
} }
} }

View File

@ -6,38 +6,38 @@ namespace Matrix_App.PregeneratedMods
{ {
public sealed class Rain : MatrixGifGenerator public sealed class Rain : MatrixGifGenerator
{ {
private float Fract(float x) private static float Fract(float x)
{ {
return x - MathF.Floor(x); return x - MathF.Floor(x);
} }
private float Step(float x, float y) private static float Step(float x, float y)
{ {
return y > x ? 1.0f : 0.0f; return y > x ? 1.0f : 0.0f;
} }
private float Shower(float u, float v, float x, float y, float t, float frame) private static float Shower(float u, float v, float x, float y, float t, float frame)
{ {
float movY = Fract(v - frame * t + y + MathF.Sin(u * 5.0f) * 0.3f); var movY = Fract(v - frame * t + y + MathF.Sin(u * 5.0f) * 0.3f);
float opacityX = Step(0.7f, Fract((u + x) * 93.0f)); var opacityX = Step(0.7f, Fract((u + x) * 93.0f));
float opacityY = Step(0.6f, movY); var opacityY = Step(0.6f, movY);
float drop = MathF.Pow(movY, 6.0f); var drop = MathF.Pow(movY, 6.0f);
return opacityX * opacityY * drop; return opacityX * opacityY * drop;
} }
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
float time = frame / (totalFrames * 0.5f); var time = frame / (totalFrames * 0.5f);
float s1 = Shower(u, v, 0.00f, 0.0f, 1.0f, time); var s1 = Shower(u, v, 0.00f, 0.0f, 1.0f, time);
float s2 = Shower(u, v, 3.11f, 0.5f, 1.0f, time); var s2 = Shower(u, v, 3.11f, 0.5f, 1.0f, time);
float s3 = Shower(u, v, 3.40f, 0.2f, 0.6f, time); var s3 = Shower(u, v, 3.40f, 0.2f, 0.6f, time);
float s4 = Shower(u, v, 3.20f, 0.7f, 0.6f, time); var s4 = Shower(u, v, 3.20f, 0.7f, 0.6f, time);
float skyLight = (Fract(MathF.Sin(u * v + v) * 67128.0f + time) * 0.3f + 0.7f) * (1.3f - v); var skyLight = (Fract(MathF.Sin(u * v + v) * 67128.0f + time) * 0.3f + 0.7f) * (1.3f - v);
r = skyLight * 0.1f; r = skyLight * 0.1f;
g = skyLight * 0.2f; g = skyLight * 0.2f;

View File

@ -1,22 +1,24 @@
using System; using System;
using Matrix_App.PregeneratedMods.reflection;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public class RandomPixels : MatrixGifGenerator public class RandomPixels : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Seed", description: "Just a seed for a bad deterministic random function")] [UiWidget]
public int seed = 0; [UiDescription(title: "Seed", description: "Just a seed for a bad deterministic random function")]
private int seed = 0;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
r = next(frame, x, y); r = Next(frame, x, y);
g = next(frame, x, y + 67); g = Next(frame, x, y + 67);
b = next(frame, x, y + 34968); b = Next(frame, x, y + 34968);
} }
private float next(int frame, int x, int y) private float Next(int frame, int x, int y)
{ {
float k = MathF.Sin(frame * 2356f + (x + y) * 5334f + (y * x) * 534f + 78.0f + seed * 435f) * 567f; var k = MathF.Sin(frame * 2356f + (x + y) * 5334f + (y * x) * 534f + 78.0f + seed * 435f) * 567f;
return k - MathF.Floor(k); return k - MathF.Floor(k);
} }
} }

View File

@ -1,24 +1,28 @@
using System; using System;
using Matrix_App.PregeneratedMods.reflection;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public class SimpleRainbow : MatrixGifGenerator public sealed class SimpleRainbow : MatrixGifGenerator
{ {
[UiWidget]
[UiDescription(title: "Radial", description: "Uses the angle to alter hues")] [UiDescription(title: "Radial", description: "Uses the angle to alter hues")]
public bool radial = false; private bool radial = false;
[UiWidget]
[UiDescription(title: "Saturation", description: "Overall saturation")] [UiDescription(title: "Saturation", description: "Overall saturation")]
public float saturation = 1.0f; private float saturation = 1.0f;
[UiWidget]
[UiDescription(title: "Brightness", description: "Overall brightness")] [UiDescription(title: "Brightness", description: "Overall brightness")]
public float value = 1.0f; private float value = 1.0f;
[UiWidget]
[UiDescription(title: "Hue rotation", description: "Offset for hue calculation")] [UiDescription(title: "Hue rotation", description: "Offset for hue calculation")]
public float rotation = 0.0f; private float rotation = 0.0f;
protected override void ColorFragment(in int x, in int y, protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
in float u, in float v,
in int frame,
out float r, out float g, out float b)
{ {
if (radial) if (radial)
{ {

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
@ -14,18 +12,18 @@ namespace Matrix_App.PregeneratedMods
return clamp(v,0.,1.); return clamp(v,0.,1.);
} }
*/ */
private float SpiralCurve(float s, float t, float time) private static float SpiralCurve(float s, float t, float time)
{ {
float r = MathF.Sqrt(s * s + t * t); var r = MathF.Sqrt(s * s + t * t);
float a = MathF.Atan2(t, s); var a = MathF.Atan2(t, s);
float v = MathF.Sin(50 * (MathF.Sqrt(r) - 0.02f * a - time)); var v = MathF.Sin(50 * (MathF.Sqrt(r) - 0.02f * a - time));
return v; return v;
} }
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
float sp = SpiralCurve((u - 0.5f) * 0.1f, (v - 0.5f) * 0.1f, frame / (float) totalFrames); var sp = SpiralCurve((u - 0.5f) * 0.1f, (v - 0.5f) * 0.1f, frame / (float) totalFrames);
r = sp; r = sp;
g = sp; g = sp;

View File

@ -1,16 +1,15 @@
using System; 
using System.Collections.Generic; using System;
using System.Text;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
class UvGrid : MatrixGifGenerator public sealed class UvGrid : MatrixGifGenerator
{ {
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)
{ {
r = u; r = u;
g = v; g = v;
b = 0.5f; b = MathF.Sin(frame / (float) totalFrames * MathF.PI);
} }
} }
} }

View File

@ -0,0 +1,134 @@
using System;
using System.Drawing;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace Matrix_App.PregeneratedMods.reflection
{
public static class FieldWidgets
{
public delegate void UiEvent();
public static Control[]? GetFieldWidget(FieldInfo field, object instance, UiEvent eventTask)
{
if (field.IsStatic || !field.IsDefined(typeof(UiWidget)))
return null;
// fallback
return GetDefaultFieldUi(field, field.GetValue(instance), (instance as MatrixGifGenerator)!, eventTask);
}
private static Control[] GetDefaultFieldUi(FieldInfo field, object? fieldValue, MatrixGifGenerator generator, UiEvent eventTask)
{
var panel = new FlowLayoutPanel
{
FlowDirection = FlowDirection.LeftToRight,
Anchor = AnchorStyles.Top | AnchorStyles.Left,
AutoSize = true
};
var title = GetBetterFieldName(field.Name);
var description = new Label();
if (Attribute.GetCustomAttribute(field, typeof(UiDescriptionAttribute)) is UiDescriptionAttribute desc)
{
title = desc.title;
description.Text = desc.description;
description.ForeColor = Color.Gray;
description.Height += 10;
description.AutoSize = true;
}
panel.Controls.Add(new Label
{
TextAlign = ContentAlignment.MiddleLeft,
Text = title,
Dock = DockStyle.Left,
Anchor = AnchorStyles.Top | AnchorStyles.Left,
Width = 100
});
switch (fieldValue)
{
case int value:
{
var upDown = new NumericUpDown
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Right,
Width = 360,
Value = value
};
upDown.ValueChanged += (a, b) =>
{
field.SetValue(generator, (int) upDown.Value);
eventTask();
};
panel.Controls.Add(upDown);
break;
}
case bool value1:
{
var upDown = new CheckBox
{
Dock = DockStyle.Fill, Anchor = AnchorStyles.Top | AnchorStyles.Right, Checked = value1
};
upDown.CheckedChanged += (a, b) =>
{
field.SetValue(generator, upDown.Checked);
eventTask();
};
panel.Controls.Add(upDown);
break;
}
case float floatValue:
{
var upDown = new TrackBar
{
Dock = DockStyle.Fill,
Anchor = AnchorStyles.Top | AnchorStyles.Right,
Maximum = 100,
Minimum = 0,
Value = (int) (floatValue * 100.0f),
TickFrequency = 10,
Width = 360
};
upDown.ValueChanged += (a, b) =>
{
field.SetValue(generator, upDown.Value / 1e2f);
eventTask();
};
panel.Controls.Add(upDown);
break;
}
}
return new Control[] {description, panel};
}
/// <summary>
/// Generates a new name from standard class names
/// Example: SomeClassA --> some class a
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static string GetBetterFieldName(string name)
{
var groups = Regex.Match(name, @"([A-Z]*[a-z]+)([A-Z]+[a-z]*)|(.*)").Groups;
var newName = "";
for (var c = 1; c < groups.Count; c++)
{
newName += groups[c].Value.ToLower() + " ";
}
return newName;
}
}
}

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods.reflection
{ {
[AttributeUsage(AttributeTargets.Field)] [AttributeUsage(AttributeTargets.Field)]
public class UiDescriptionAttribute : Attribute public class UiDescriptionAttribute : Attribute

View File

@ -0,0 +1,9 @@
using System;
namespace Matrix_App.PregeneratedMods.reflection
{
[AttributeUsage(AttributeTargets.Field)]
public class UiWidget : Attribute
{
}
}

View File

@ -143,6 +143,6 @@
<value>..\resources\frosch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\resources\frosch.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="Pfüsikuh" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="Pfüsikuh" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\pfüsikuh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\Splashcreen.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
</root> </root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

View File

@ -25,7 +25,7 @@ namespace Matrix_App
{ {
Name = name, Name = name,
IsBackground = true, IsBackground = true,
Priority = ThreadPriority.BelowNormal Priority = ThreadPriority.Normal
}; };
thread.Start(); thread.Start();
} }
@ -56,7 +56,7 @@ namespace Matrix_App
{ {
try try
{ {
Thread.Sleep(500); Thread.Sleep(10);
} catch(ThreadInterruptedException) } catch(ThreadInterruptedException)
{ {
thread.Interrupt(); thread.Interrupt();

View File

@ -1,10 +1,6 @@
using System; using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Text;
using static Matrix_App.Defaults; using static Matrix_App.Defaults;
namespace Matrix_App namespace Matrix_App
@ -81,9 +77,9 @@ namespace Matrix_App
int index = (x + y * width) * Bpp; int index = (x + y * width) * Bpp;
image.SetPixel(x, y, Color.FromArgb( image.SetPixel(x, y, Color.FromArgb(
(byte) buffer[index + 0], buffer[index + 0],
(byte) buffer[index + 1], buffer[index + 1],
(byte) buffer[index + 2] buffer[index + 2]
)); ));
} }
} }

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
0e5f843b45897d8b4a3e6250399d748fbf87d606 8b5c196e3fff81055e69fb849ea66d181b78d0ae

View File

@ -0,0 +1,8 @@
is_global = true
build_property.TargetFramework = netcoreapp3.1
build_property.TargetPlatformMinVersion = 7.0
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.PublishSingleFile =
build_property.IncludeAllContentForSelfExtract =
build_property._SupportedPlatformList = Android,iOS,Linux,macOS,Windows

View File

@ -1 +1 @@
d3ff948d4c991bd397c33d4f33adca3dc910573c d74f4da8e70ffef608fcbd55775b064d0e57aa85

View File

@ -59,3 +59,35 @@ F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matri
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.dll F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.pdb F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.pdb
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.genruntimeconfig.cache F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5_RC3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.genruntimeconfig.cache
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.exe
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.deps.json
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.runtimeconfig.json
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.runtimeconfig.dev.json
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Matrix App.pdb
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\Microsoft.Win32.Registry.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\System.CodeDom.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\System.IO.Ports.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\System.Management.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\System.Security.AccessControl.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\System.Security.Principal.Windows.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\win\lib\netstandard2.0\Microsoft.Win32.Registry.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\win\lib\netstandard2.0\System.IO.Ports.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\win\lib\netcoreapp2.0\System.Management.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\win\lib\netcoreapp2.0\System.Security.AccessControl.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\unix\lib\netcoreapp2.1\System.Security.Principal.Windows.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\bin\Release\netcoreapp3.1\runtimes\win\lib\netcoreapp2.1\System.Security.Principal.Windows.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.csprojAssemblyReference.cache
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix_App.ColorWheel.resources
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix_App.Matrix.resources
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix_App.MatrixDesignerMain.resources
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix_App.Properties.Resources.resources
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.csproj.GenerateResource.cache
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.GeneratedMSBuildEditorConfig.editorconfig
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.AssemblyInfoInputs.cache
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.AssemblyInfo.cs
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.csproj.CoreCompileInputs.cache
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.csproj.CopyComplete
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.dll
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.pdb
F:\Content\Schule\BBS-T1-Ludwigshafen\Klasse 12\Info Lk\bulli\Neopixel\App\Matrix_App_V3.5.3\Matrix App\obj\Release\netcoreapp3.1\Matrix App.genruntimeconfig.cache

View File

@ -1 +1 @@
4853592640e68725119800981d81bdaa9a74ded2 515eead76ebf0b414116e9f97a694849e0a06bf3