Update .gitignore to exclude new build and tool files

Added FodyWeavers.xsd, .dotnet-home/.dotnet, .dotnet-home/.dotnet/TelemetryStorageService, and .nuget to .gitignore to prevent tracking of generated and tool-related files.
This commit is contained in:
Michal Vrba
2026-02-13 21:20:00 +01:00
parent 488e3c64a3
commit 11a4311bc4
5 changed files with 399 additions and 29 deletions
+320 -18
View File
@@ -19,6 +19,8 @@ public sealed class FractalRenderer : IDisposable
private Color[] _previousFrame;
private readonly List<NoteParticle> _notes = [];
private readonly List<DetectedNoteParticle> _detectedNotes = [];
private readonly List<StaffNoteParticle> _staffNotes = [];
private readonly List<ScrollingStaffNoteParticle> _scrollStaffNotes = [];
private readonly List<FireworkRocket> _fireworkRockets = [];
private readonly List<FireworkSpark> _fireworkSparks = [];
private readonly Random _rng = new();
@@ -45,8 +47,9 @@ public sealed class FractalRenderer : IDisposable
};
private float _noteSpawnAccumulator;
private float _detectedNoteAccumulator;
private float _fireworkSpawnAccumulator;
private float _sheetOffsetX;
private float _lastRenderTimeSeconds = -1f;
private int _lastChordCode = -1;
private float _chordFlash;
private float _runtimePerformanceScale = 1f;
@@ -140,11 +143,14 @@ public sealed class FractalRenderer : IDisposable
_previousFrame = new Color[_internalWidth * _internalHeight];
_notes.Clear();
_detectedNotes.Clear();
_staffNotes.Clear();
_scrollStaffNotes.Clear();
_fireworkRockets.Clear();
_fireworkSparks.Clear();
_noteSpawnAccumulator = 0f;
_detectedNoteAccumulator = 0f;
_fireworkSpawnAccumulator = 0f;
_sheetOffsetX = 0f;
_lastRenderTimeSeconds = -1f;
}
private int ScaleCount(int baseCount, int minCount = 1)
@@ -234,6 +240,12 @@ public sealed class FractalRenderer : IDisposable
case 21:
RenderChordCenter(features, timeSeconds);
break;
case 22:
RenderMusicStaffNotes(features, timeSeconds);
break;
case 23:
RenderScrollingMusicStaff(features, timeSeconds);
break;
default:
RenderJulia(features, timeSeconds);
break;
@@ -1204,13 +1216,9 @@ public sealed class FractalRenderer : IDisposable
}
}
float whistleBoost = GetWhistleSpawnBoost(features.DominantFrequencyHz);
float spawnRate = features.DetectedNoteStrength * (0.9f + whistleBoost * 1.7f + Clamp01(features.Beat) * 0.35f);
_detectedNoteAccumulator += spawnRate * _runtimePerformanceScale;
while (_detectedNoteAccumulator >= 1f)
if (features.NoteOnset)
{
SpawnDetectedNote(features);
_detectedNoteAccumulator -= 1f;
}
for (int i = _detectedNotes.Count - 1; i >= 0; i--)
@@ -1232,17 +1240,6 @@ public sealed class FractalRenderer : IDisposable
}
}
private static float GetWhistleSpawnBoost(float frequencyHz)
{
if (frequencyHz < 800f || frequencyHz > 5000f)
{
return 0f;
}
float norm = (frequencyHz - 800f) / (5000f - 800f);
return Clamp01(norm);
}
private void RenderChordCenter(AudioFeatures features, float timeSeconds)
{
for (int y = 0; y < _internalHeight; y++)
@@ -1284,6 +1281,248 @@ public sealed class FractalRenderer : IDisposable
DrawTextPixels(chordText, x0, y0, scale, textColor, 0.95f);
}
private void RenderMusicStaffNotes(AudioFeatures features, float timeSeconds)
{
for (int y = 0; y < _internalHeight; y++)
{
float t = y / (float)(_internalHeight - 1);
Color bg = new(0.98f - t * 0.05f, 0.97f - t * 0.05f, 0.93f - t * 0.04f, 1f);
int row = y * _internalWidth;
for (int x = 0; x < _internalWidth; x++)
{
_pixelBuffer[row + x] = bg;
}
}
int left = (int)(_internalWidth * 0.08f);
int right = (int)(_internalWidth * 0.92f);
int top = (int)(_internalHeight * 0.32f);
int spacing = Math.Max(5, _internalHeight / 24);
for (int i = 0; i < 5; i++)
{
int y = top + i * spacing;
DrawRect(left, y, right - left, 1, new Vector3(0.15f, 0.15f, 0.18f), 0.85f);
}
if (features.NoteOnset)
{
SpawnStaffNote(features, left, right, top, spacing);
}
for (int i = _staffNotes.Count - 1; i >= 0; i--)
{
StaffNoteParticle n = _staffNotes[i];
n.Life -= 0.0065f;
n.X += n.Vx;
if (n.Life <= 0f || n.X > right + 20)
{
_staffNotes.RemoveAt(i);
continue;
}
_staffNotes[i] = n;
DrawStaffNote(n, top, spacing);
}
}
private void RenderScrollingMusicStaff(AudioFeatures features, float timeSeconds)
{
float dt;
if (_lastRenderTimeSeconds < 0f)
{
dt = 1f / 120f;
}
else
{
dt = Math.Clamp(timeSeconds - _lastRenderTimeSeconds, 1f / 240f, 1f / 20f);
}
_lastRenderTimeSeconds = timeSeconds;
for (int y = 0; y < _internalHeight; y++)
{
float t = y / (float)(_internalHeight - 1);
Color bg = new(0.985f - t * 0.04f, 0.98f - t * 0.04f, 0.95f - t * 0.03f, 1f);
int row = y * _internalWidth;
for (int x = 0; x < _internalWidth; x++)
{
_pixelBuffer[row + x] = bg;
}
}
int left = (int)(_internalWidth * 0.06f);
int right = (int)(_internalWidth * 0.94f);
int top = (int)(_internalHeight * 0.34f);
int spacing = Math.Max(5, _internalHeight / 24);
float bpm = features.Bpm > 0f ? features.Bpm : 90f;
float pxPerSecond = 14f + bpm * 0.24f;
float speed = pxPerSecond * dt;
_sheetOffsetX += speed;
int measureSpacing = Math.Max(30, _internalWidth / 6);
if (_sheetOffsetX >= measureSpacing)
{
_sheetOffsetX -= measureSpacing;
}
for (int i = 0; i < 5; i++)
{
int y = top + i * spacing;
DrawRect(left, y, right - left, 1, new Vector3(0.14f, 0.14f, 0.16f), 0.85f);
}
for (int x = right - (int)_sheetOffsetX; x > left; x -= measureSpacing)
{
DrawRect(x, top - spacing / 2, 1, spacing * 5, new Vector3(0.2f, 0.2f, 0.24f), 0.55f);
}
if (features.NoteOnset)
{
SpawnScrollingStaffNote(features, right, top, spacing);
}
for (int i = _scrollStaffNotes.Count - 1; i >= 0; i--)
{
ScrollingStaffNoteParticle n = _scrollStaffNotes[i];
n.X -= speed * (0.95f + n.SpeedJitter);
n.Life -= 0.0045f;
if (n.Life <= 0f || n.X < left - 30)
{
_scrollStaffNotes.RemoveAt(i);
continue;
}
_scrollStaffNotes[i] = n;
DrawScrollingStaffNote(n, top, spacing);
}
}
private void SpawnScrollingStaffNote(AudioFeatures features, int right, int top, int spacing)
{
if (features.DetectedNoteIndex < 0 || _scrollStaffNotes.Count >= ScaleCount(180, 30))
{
return;
}
int staffStep = NoteToStaffStep(features.DetectedNoteIndex);
int staffCenterY = top + spacing * 4;
int y = staffCenterY - (staffStep * (spacing / 2));
int x = right - 8 + _rng.Next(0, 8);
_scrollStaffNotes.Add(new ScrollingStaffNoteParticle
{
X = x,
Y = y,
Life = 1f,
UpStem = _rng.NextDouble() > 0.5,
Filled = features.DetectedNoteStrength > 0.20f,
SpeedJitter = (float)_rng.NextDouble() * 0.35f
});
}
private void DrawScrollingStaffNote(ScrollingStaffNoteParticle n, int top, int spacing)
{
int x = (int)n.X;
int y = n.Y;
float a = Clamp01(n.Life);
Vector3 ink = new(0.07f, 0.07f, 0.1f);
int rx = Math.Max(2, spacing / 3);
int ry = Math.Max(2, spacing / 4 + 1);
DrawEllipse(x, y, rx, ry, ink, a, n.Filled);
int stemH = spacing * 3;
if (n.UpStem)
{
DrawRect(x + rx, y - stemH, 1, stemH, ink, a);
}
else
{
DrawRect(x - rx, y, 1, stemH, ink, a);
}
int staffTop = top;
int staffBottom = top + spacing * 4;
if (y < staffTop - spacing / 2 || y > staffBottom + spacing / 2)
{
DrawRect(x - spacing / 2, y, spacing, 1, ink, a * 0.9f);
}
}
private void SpawnStaffNote(AudioFeatures features, int left, int right, int top, int spacing)
{
if (features.DetectedNoteIndex < 0 || _staffNotes.Count >= ScaleCount(120, 20))
{
return;
}
int noteIndex = features.DetectedNoteIndex;
int staffStep = NoteToStaffStep(noteIndex);
int staffCenterY = top + spacing * 4;
int y = staffCenterY - (staffStep * (spacing / 2));
int x = left + _rng.Next(0, Math.Max(10, right - left - 20));
_staffNotes.Add(new StaffNoteParticle
{
X = x,
Y = y,
Vx = 0.20f + (float)_rng.NextDouble() * 0.35f,
Life = 1f,
UpStem = _rng.NextDouble() > 0.5,
Filled = features.DetectedNoteStrength > 0.22f
});
}
private static int NoteToStaffStep(int noteIndex)
{
return noteIndex switch
{
0 => -1,
1 => -1,
2 => 0,
3 => 0,
4 => 1,
5 => 2,
6 => 2,
7 => 3,
8 => 3,
9 => 4,
10 => 4,
11 => 5,
_ => 0
};
}
private void DrawStaffNote(StaffNoteParticle n, int top, int spacing)
{
int x = (int)n.X;
int y = n.Y;
float a = Clamp01(n.Life);
Vector3 ink = new(0.08f, 0.08f, 0.1f);
int rx = Math.Max(2, spacing / 3);
int ry = Math.Max(2, spacing / 4 + 1);
DrawEllipse(x, y, rx, ry, ink, a, n.Filled);
int stemH = spacing * 3;
if (n.UpStem)
{
DrawRect(x + rx, y - stemH, 1, stemH, ink, a);
}
else
{
DrawRect(x - rx, y, 1, stemH, ink, a);
}
int staffTop = top;
int staffBottom = top + spacing * 4;
if (y < staffTop - spacing / 2 || y > staffBottom + spacing / 2)
{
DrawRect(x - spacing / 2, y, spacing, 1, ink, a * 0.9f);
}
}
private void SpawnDetectedNote(AudioFeatures features)
{
if (features.DetectedNoteIndex < 0 || features.DetectedNoteIndex > 11)
@@ -1577,6 +1816,49 @@ public sealed class FractalRenderer : IDisposable
}
}
private void DrawEllipse(int cx, int cy, int rx, int ry, Vector3 color, float alpha, bool filled)
{
int minX = cx - rx - 1;
int maxX = cx + rx + 1;
int minY = cy - ry - 1;
int maxY = cy + ry + 1;
float irx = 1f / (rx * rx + 1e-6f);
float iry = 1f / (ry * ry + 1e-6f);
for (int y = minY; y <= maxY; y++)
{
if (y < 0 || y >= _internalHeight)
{
continue;
}
for (int x = minX; x <= maxX; x++)
{
if (x < 0 || x >= _internalWidth)
{
continue;
}
float dx = x - cx;
float dy = y - cy;
float d = dx * dx * irx + dy * dy * iry;
if (filled)
{
if (d <= 1f)
{
BlendPixel(x, y, color, alpha);
}
}
else
{
if (d >= 0.7f && d <= 1.2f)
{
BlendPixel(x, y, color, alpha);
}
}
}
}
}
private void BlendPixel(int x, int y, Vector3 color, float alpha)
{
int idx = y * _internalWidth + x;
@@ -1705,6 +1987,26 @@ public sealed class FractalRenderer : IDisposable
public Vector3 Color;
}
private struct StaffNoteParticle
{
public float X;
public int Y;
public float Vx;
public float Life;
public bool UpStem;
public bool Filled;
}
private struct ScrollingStaffNoteParticle
{
public float X;
public int Y;
public float Life;
public bool UpStem;
public bool Filled;
public float SpeedJitter;
}
private struct FireworkRocket
{
public float X;