Skip to content

Commit

Permalink
Merge pull request #160 from roxaskeyheart/chromatics-3.x
Browse files Browse the repository at this point in the history
Chromatics 3.x
  • Loading branch information
logicallysynced authored Jul 21, 2024
2 parents 44fca54 + 83d4584 commit f9a4b4d
Show file tree
Hide file tree
Showing 27 changed files with 1,784 additions and 246 deletions.
2 changes: 1 addition & 1 deletion Chromatics/Chromatics.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<TargetFramework>net8.0-windows7.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<StartupObject>Chromatics.Program</StartupObject>
<Version>3.0.8.2</Version>
<Version>3.0.8.3</Version>
<Authors>Danielle Thompson</Authors>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Copyright>Danielle Thompson 2024</Copyright>
Expand Down
2 changes: 1 addition & 1 deletion Chromatics/Core/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class AppSettings
private static SettingsModel _settings = new SettingsModel();

public static readonly string currentSettingsVersion = "2";
public static readonly string currentEffectsVersion = "1";
public static readonly string currentEffectsVersion = "2";
public static readonly string currentPalettesVersion = "1";
public static readonly string currentMappingLayerVersion = "1";

Expand Down
7 changes: 5 additions & 2 deletions Chromatics/Enums/PaletteTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Chromatics.Enums
{
Expand Down Expand Up @@ -35,9 +36,11 @@ public enum PaletteTypes
[Display(Name = "Reactive Weather")]
ReactiveWeather = 10,
[Display(Name = "Job Classes")]
JobClasses = 11
JobClasses = 11,
[Display(Name = "Raid Effects")]
RaidEffects = 12
}

public static int TypeCount = 11;
public static int TypeCount = 12;
}
}
114 changes: 114 additions & 0 deletions Chromatics/Extensions/RGB.NET/Decorators/ArenaLightShowDecorator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using RGB.NET.Core;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Color = RGB.NET.Core.Color;

namespace Chromatics.Extensions.RGB.NET.Decorators
{
public class ArenaLightShowDecorator : AbstractUpdateAwareDecorator, ILedGroupDecorator
{
private readonly ListLedGroup ledGroup;
private readonly Random random = new Random();
private readonly double interval;
private readonly double waveSpeed;
private readonly double waveFrequency;
private readonly Color[] colors;
private readonly Color baseColor;
private ConcurrentDictionary<Led, double> ledPositions;
private Dictionary<Led, float> currentBrightness;
private Dictionary<Led, Color> currentColors;
private double Timing;

public ArenaLightShowDecorator(ListLedGroup _ledGroup, double interval, double waveSpeed, double waveFrequency, Color[] colors, RGBSurface surface, bool updateIfDisabled = false, Color baseColor = default(Color)) : base(surface, updateIfDisabled)
{
this.ledGroup = _ledGroup;
this.interval = interval;
this.waveSpeed = waveSpeed;
this.waveFrequency = waveFrequency;
this.colors = colors;
this.baseColor = baseColor == default(Color) ? Color.Transparent : baseColor;

ledPositions = new ConcurrentDictionary<Led, double>();
currentBrightness = new Dictionary<Led, float>();
currentColors = new Dictionary<Led, Color>();
Timing = 0;
}

public override void OnAttached(IDecoratable decoratable)
{
base.OnAttached(decoratable);
ledGroup.Detach();

Debug.WriteLine("Arena Light Show Decorator Attached");

foreach (var led in ledGroup)
{
ledPositions.TryAdd(led, random.NextDouble() * Math.PI * 2);
currentColors.TryAdd(led, colors[random.Next(colors.Length)]);
}
}

public override void OnDetached(IDecoratable decoratable)
{
base.OnDetached(decoratable);
ledPositions.Clear();
currentColors.Clear();
currentBrightness.Clear();
Timing = 0;

Debug.WriteLine("Arena Light Show Decorator Detached");
}

protected override void Update(double deltaTime)
{
try
{
if (ledGroup == null) return;

Timing += deltaTime * waveSpeed;

foreach (var led in ledGroup)
{
if (!ledPositions.ContainsKey(led)) continue;

double position = ledPositions[led] + Timing;
double intensity = (Math.Sin(position * waveFrequency) + 1) / 2; // Sine wave for smooth transition

var colorIndex = (int)(Math.Floor((position / Math.PI) % colors.Length));
var nextColorIndex = (colorIndex + 1) % colors.Length;

var currentColor = colors[colorIndex];
var nextColor = colors[nextColorIndex];

var color = Lerp(currentColor, nextColor, (float)intensity);

var newCol = new Color(
(int)(color.R * 255 * intensity + baseColor.R * (1 - intensity)),
(int)(color.G * 255 * intensity + baseColor.G * (1 - intensity)),
(int)(color.B * 255 * intensity + baseColor.B * (1 - intensity))
);

led.Color = newCol;
}
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"Exception: {ex.Message}");
#endif
}
}

private static Color Lerp(Color start, Color end, float amount)
{
float r = start.R + (end.R - start.R) * amount;
float g = start.G + (end.G - start.G) * amount;
float b = start.B + (end.B - start.B) * amount;

return new Color((int)(r * 255), (int)(g * 255), (int)(b * 255));
}
}
}
199 changes: 199 additions & 0 deletions Chromatics/Extensions/RGB.NET/Decorators/BPMFastStarfieldDecorator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
using RGB.NET.Core;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Color = RGB.NET.Core.Color;

namespace Chromatics.Extensions.RGB.NET.Decorators
{
public class BPMFastStarfieldDecorator : AbstractUpdateAwareDecorator, ILedGroupDecorator
{
private readonly ListLedGroup ledGroup;
private readonly Random random = new Random();
private readonly int numberOfLeds;
private readonly double fadeSpeed;
private readonly double densityMultiplier;
private readonly Color[] colors;
private readonly Color baseColor;
private ConcurrentDictionary<Led, Color> fadingInLeds;
private ConcurrentDictionary<Led, Color> fadingOutLeds;
private Dictionary<Led, float> currentBrightness;
private Dictionary<Led, Color> currentColors;
private Dictionary<Led, double> startTimes;
private double Timing;
private double startDelay;
private double updateCounter = 0;
private double interval;

public BPMFastStarfieldDecorator(ListLedGroup _ledGroup, int numberOfLeds, int bpm, double fadeSpeed, Color[] colors, RGBSurface surface, double densityMultiplier = 1.0, bool updateIfDisabled = false, Color baseColor = default(Color)) : base(surface, updateIfDisabled)
{
this.ledGroup = _ledGroup;
this.numberOfLeds = numberOfLeds;
this.fadeSpeed = fadeSpeed;
this.colors = colors;
this.baseColor = baseColor == default(Color) ? Color.Transparent : baseColor;
this.densityMultiplier = densityMultiplier;

CalculateInterval(bpm);
startTimes = new Dictionary<Led, double>();
fadingInLeds = new ConcurrentDictionary<Led, Color>();
fadingOutLeds = new ConcurrentDictionary<Led, Color>();
currentBrightness = new Dictionary<Led, float>();
currentColors = new Dictionary<Led, Color>();
Timing = 0;
startDelay = 0;
}

private void CalculateInterval(int bpm)
{
// Convert BPM to interval in seconds (interval = 60 / BPM)
interval = 60.0 / bpm;
}

public override void OnAttached(IDecoratable decoratable)
{
base.OnAttached(decoratable);
ledGroup.Detach();
}

public override void OnDetached(IDecoratable decoratable)
{
base.OnDetached(decoratable);
currentBrightness.Clear();
fadingInLeds.Clear();
fadingOutLeds.Clear();
currentColors.Clear();
startTimes.Clear();
Timing = 0;
startDelay = 0;
}

protected override void Update(double deltaTime)
{
try
{
if (ledGroup == null || fadingInLeds == null || fadingOutLeds == null) return;

Timing += deltaTime;

var minBrightness = 0;
var maxBrightness = 1;

if (Timing >= startDelay)
{
var availableLeds = ledGroup.Where(led => !fadingInLeds.ContainsKey(led) && !fadingOutLeds.ContainsKey(led));
var selectedLeds = availableLeds.OrderBy(x => Guid.NewGuid()).Take((int)(numberOfLeds * densityMultiplier));

foreach (var led in selectedLeds)
{
fadingInLeds.TryAdd(led, baseColor);
var colorIndex = random.Next(colors.Length);

if (!currentColors.ContainsKey(led))
currentColors.Add(led, colors[colorIndex]);

if (!startTimes.ContainsKey(led))
{
var rng = Timing + GetRandomStartTime();
startTimes.Add(led, rng);
}
}

startDelay = Timing + (((fadeSpeed * 2) - 50) / 1000);
}

foreach (var led in fadingInLeds)
{
if (Timing >= startTimes[led.Key])
{
if (!currentBrightness.ContainsKey(led.Key))
{
currentBrightness.Add(led.Key, minBrightness);
}

currentBrightness[led.Key] += (float)(deltaTime * (maxBrightness - minBrightness) / (fadeSpeed / 1000));

if (currentBrightness[led.Key] >= maxBrightness)
{
fadingOutLeds.TryAdd(led.Key, currentColors[led.Key]);
fadingInLeds.TryRemove(led);
}
else
{
var lerpAmount = Map(currentBrightness[led.Key], minBrightness, maxBrightness, 0, 1);
var color = Lerp(baseColor, currentColors[led.Key], lerpAmount);
fadingInLeds[led.Key] = color;
}
}
}

foreach (var led in fadingOutLeds)
{
if (!currentBrightness.ContainsKey(led.Key))
{
currentBrightness.Add(led.Key, maxBrightness);
}

currentBrightness[led.Key] -= (float)(deltaTime * (maxBrightness - minBrightness) / (fadeSpeed / 1000));

if (currentBrightness[led.Key] <= minBrightness)
{
fadingOutLeds.TryRemove(led);
currentBrightness.Remove(led.Key);
currentColors.Remove(led.Key);
startTimes.Remove(led.Key);
}
else
{
var lerpAmount = Map(currentBrightness[led.Key], minBrightness, maxBrightness, 0, 1);
var color = Lerp(baseColor, currentColors[led.Key], lerpAmount);
fadingOutLeds[led.Key] = color;
}
}

foreach (var led in ledGroup)
{
if (fadingInLeds != null && fadingInLeds.ContainsKey(led))
{
led.Color = fadingInLeds[led];
}
else if (fadingOutLeds != null && fadingOutLeds.ContainsKey(led))
{
led.Color = fadingOutLeds[led];
}
else
{
led.Color = baseColor;
}
}
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"Exception: {ex.Message}");
#endif
}
}

private double GetRandomStartTime()
{
return random.NextDouble() * (interval * 0.05);
}

private float Map(float value, float fromMin, float fromMax, float toMin, float toMax)
{
return (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;
}

private static Color Lerp(Color start, Color end, float amount)
{
float r = start.R + (end.R - start.R) * amount;
float g = start.G + (end.G - start.G) * amount;
float b = start.B + (end.B - start.B) * amount;

return new Color((int)(r * 255), (int)(g * 255), (int)(b * 255));
}
}
}
Loading

0 comments on commit f9a4b4d

Please sign in to comment.