diff --git a/Project-Aurora/AuroraCommon/Utils/CommonColorUtils.cs b/Project-Aurora/AuroraCommon/Utils/CommonColorUtils.cs
index c9622060a..b2351c5aa 100644
--- a/Project-Aurora/AuroraCommon/Utils/CommonColorUtils.cs
+++ b/Project-Aurora/AuroraCommon/Utils/CommonColorUtils.cs
@@ -103,7 +103,7 @@ public static Color AddColors(in Color background, in Color foreground)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref Color AddColors(in Color background, in Color foreground, ref Color resultCache)
+ public static ref Color AddColors(ref readonly Color background, ref readonly Color foreground, ref Color resultCache)
{
var foreA = foreground.A;
var backA = background.A;
@@ -347,7 +347,6 @@ public static Color FastColorTransparent(byte r, byte g, byte b)
return FastColor((byte)(r * normalizer), (byte)(g * normalizer), (byte)(b * normalizer), brightness);
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Color FastColor(byte r, byte g, byte b, byte a = 255)
{
return Color.FromArgb(
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/AuroraSourceGenerator.csproj b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/AuroraSourceGenerator.csproj
index 4a7d619e8..1164d6609 100644
--- a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/AuroraSourceGenerator.csproj
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/AuroraSourceGenerator.csproj
@@ -16,12 +16,11 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/ClassUtils.cs b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/ClassUtils.cs
new file mode 100644
index 000000000..fcd962c3f
--- /dev/null
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/ClassUtils.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace AuroraSourceGenerator;
+
+public static class ClassUtils
+{
+ public static IEnumerable GetBaseTypes(INamedTypeSymbol type)
+ {
+ var currentType = type;
+ while (currentType != null)
+ {
+ yield return currentType;
+ currentType = currentType.BaseType;
+ }
+ }
+
+ public static IEnumerable GetBaseTypes(ITypeSymbol type)
+ {
+ var currentType = type;
+ while (currentType != null)
+ {
+ yield return currentType;
+ currentType = currentType.BaseType;
+ }
+ }
+
+ public static IEnumerable GetAllInterfaces(ITypeSymbol type)
+ {
+ return type.AllInterfaces;
+ }
+}
\ No newline at end of file
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/IsExternalInit.cs b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/IsExternalInit.cs
new file mode 100644
index 000000000..c9526624f
--- /dev/null
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/IsExternalInit.cs
@@ -0,0 +1,3 @@
+namespace System.Runtime.CompilerServices;
+
+public class IsExternalInit;
\ No newline at end of file
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/NodePropertySourceGenerator.cs b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/NodePropertySourceGenerator.cs
index 84be5c69b..2c736f858 100644
--- a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/NodePropertySourceGenerator.cs
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/NodePropertySourceGenerator.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
@@ -15,71 +16,89 @@ internal class PropertyAccess(string gsiPath, string accessPath)
public string AccessPath { get; } = accessPath;
}
-///
-/// A sample source generator that creates C# classes based on the text file (in this case, Domain Driven Design ubiquitous language registry).
-/// When using a simple text file as a baseline, we can create a non-incremental source generator.
-///
[Generator]
-public class NodePropertySourceGenerator : ISourceGenerator
+public class NodePropertySourceGenerator : IIncrementalGenerator
{
- public void Initialize(GeneratorInitializationContext context)
+ private const string GameStateInterface = "AuroraRgb.Profiles.GameState";
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
- // No initialization required for this example
+ // Get all class declarations from syntax
+ IncrementalValuesProvider classDeclarations = context.SyntaxProvider
+ .CreateSyntaxProvider(
+ predicate: static (s, _) => IsSyntaxTargetForGeneration(s),
+ transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
+ .Where(static m => m is not null)!;
+
+ // Combine the compilation and the class declarations
+ IncrementalValueProvider<(Compilation Compilation, ImmutableArray Classifications)> compilationAndClasses
+ = context.CompilationProvider.Combine(classDeclarations.Collect());
+
+ // Generate the source
+ context.RegisterSourceOutput(compilationAndClasses,
+ static (spc, source) => Execute(source.Compilation, source.Classifications, spc));
}
- public void Execute(GeneratorExecutionContext context)
+ private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
+ => node is ClassDeclarationSyntax classDeclaration
+ && classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword);
+
+ private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
{
- const string gamestate = "AuroraRgb.Profiles.GameState";
- HashSet ignore = [gamestate];
-
- var compilation = context.Compilation;
+ var classDeclaration = (ClassDeclarationSyntax)context.Node;
- // Retrieve the interface symbol
- var gameStateInterface = compilation.GetTypeByMetadataName(gamestate);
+ // Get the semantic model
+ var semanticModel = context.SemanticModel;
+ var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration);
- if (gameStateInterface == null)
- {
- // Interface not found, do nothing
- return;
- }
+ if (classSymbol == null) return null;
+
+ // Check if it's an Aurora class and derives from GameState
+ if (!IsAuroraClass(classSymbol)) return null;
+
+ var gameStateInterface = semanticModel.Compilation.GetTypeByMetadataName(GameStateInterface);
+ if (gameStateInterface == null) return null;
+
+ if (!IsSubtypeOf(classSymbol, gameStateInterface)) return null;
- // Find all classes in the compilation
- var classes = compilation.SyntaxTrees
- .SelectMany(syntaxTree => syntaxTree.GetRoot().DescendantNodes())
- .OfType()
- .Select(declaration => ModelExtensions.GetDeclaredSymbol(compilation.GetSemanticModel(declaration.SyntaxTree), declaration))
- .OfType()
- .Where(IsAuroraClass)
- .Where(IsSubtypeOf(gameStateInterface))
- .Where(IsPartialClass)
- .Where(classSymbol => !ignore.Contains(classSymbol.ToDisplayString()));
-
- foreach (var classSymbol in classes)
+ return classDeclaration;
+ }
+
+ private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context)
+ {
+ if (classes.IsDefaultOrEmpty) return;
+
+ HashSet ignore = [GameStateInterface];
+
+ foreach (var classDeclaration in classes)
{
+ var semanticModel = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
+ var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration);
+
+ if (classSymbol == null) continue;
+ if (ignore.Contains(classSymbol.ToDisplayString())) continue;
+
GenerateClassProperties(context, classSymbol);
}
}
- private static Func IsSubtypeOf(INamedTypeSymbol gameStateInterface)
+ private static bool IsSubtypeOf(INamedTypeSymbol classSymbol, INamedTypeSymbol gameStateInterface)
{
- return classSymbol =>
+ var currentType = classSymbol.BaseType;
+ while (currentType != null)
{
- var currentType = classSymbol.BaseType;
- while (currentType != null)
+ if (SymbolEqualityComparer.Default.Equals(currentType, gameStateInterface))
{
- if (SymbolEqualityComparer.Default.Equals(currentType, gameStateInterface))
- {
- return true;
- }
-
- currentType = currentType.BaseType;
+ return true;
}
- return false;
- };
+ currentType = currentType.BaseType;
+ }
+
+ return false;
}
- private static void GenerateClassProperties(GeneratorExecutionContext context, INamedTypeSymbol classSymbol)
+ private static void GenerateClassProperties(SourceProductionContext context, INamedTypeSymbol classSymbol)
{
// Get all properties of the class
var properties = GetClassProperties("", classSymbol, $"(({classSymbol.Name})t).");
@@ -106,14 +125,10 @@ public partial class {{classSymbol.Name}}
}
""";
- // Add the generated source to the compilation
context.AddSource(classSymbol.Name + ".g.cs", SourceText.From(source, Encoding.UTF8));
}
- private static Func Selector()
- {
- return AccessorMethodSource;
- }
+ private static Func Selector() => AccessorMethodSource;
private static string AccessorMethodSource(PropertyAccess valueTuple)
{
@@ -123,7 +138,7 @@ private static string AccessorMethodSource(PropertyAccess valueTuple)
private static IEnumerable GetClassProperties(string currentPath, INamedTypeSymbol type, string upperAccessPath)
{
- var namedTypeSymbols = GetBaseTypes(type);
+ var namedTypeSymbols = ClassUtils.GetBaseTypes(type);
foreach (var currentType in namedTypeSymbols)
{
foreach (var member in currentType.GetMembers())
@@ -139,21 +154,19 @@ private static IEnumerable GetClassProperties(string currentPath
var propertyType = property.Type;
var accessPath = property.IsStatic ? GetStaticAccessPath(currentType, property) : upperAccessPath + property.Name;
-
- // Check if the type is a primitive type
+
if (propertyType.IsValueType || propertyType.SpecialType == SpecialType.System_String)
{
yield return new PropertyAccess(currentPath + property.Name, accessPath);
continue;
}
- // Check if the type is a class
if (propertyType.TypeKind is not (TypeKind.Class or TypeKind.Interface)) continue;
var namedTypeSymbol = (INamedTypeSymbol)property.Type;
if (!IsAuroraClass(namedTypeSymbol))
continue;
- // prevent infinite recursions, this should look for all previous types actually
+
if (SymbolEqualityComparer.Default.Equals(namedTypeSymbol, currentType))
{
continue;
@@ -163,56 +176,21 @@ private static IEnumerable GetClassProperties(string currentPath
var s = property.NullableAnnotation == NullableAnnotation.Annotated ? "?." : ".";
var lowerAccessPath = property.IsStatic ? GetStaticAccessPath(currentType, property) : upperAccessPath + property.Name + s;
-
+
foreach (var classProperty in GetClassProperties(upperProperty, namedTypeSymbol, lowerAccessPath))
{
yield return classProperty;
}
}
}
-
- }
-
- private static IEnumerable GetBaseTypes(INamedTypeSymbol type)
- {
- var currentType = type;
- while (currentType != null)
- {
- yield return currentType;
- currentType = currentType.BaseType;
- }
}
private static bool IgnoredAttribute(AttributeData arg)
- {
- return arg.AttributeClass?.Name == "GameStateIgnoreAttribute";
- }
+ => arg.AttributeClass?.Name == "GameStateIgnoreAttribute";
private static string GetStaticAccessPath(INamedTypeSymbol currentType, IPropertySymbol property)
- {
- return currentType.ContainingNamespace + "." + currentType.Name + "." + property.Name + ".";
- }
+ => currentType.ContainingNamespace + "." + currentType.Name + "." + property.Name + ".";
private static bool IsAuroraClass(INamedTypeSymbol namedTypeSymbol)
- {
- return namedTypeSymbol.ToString().StartsWith("AuroraRgb.");
- }
-
- private static bool IsPartialClass(INamedTypeSymbol namedTypeSymbol)
- {
- // Loop through all the declaration syntax references
- foreach (var syntaxNode in namedTypeSymbol.DeclaringSyntaxReferences.Select(syntaxReference => syntaxReference.GetSyntax()))
- {
- // Check if the syntax node is a class declaration
- if (syntaxNode is not ClassDeclarationSyntax classDeclaration) continue;
- // Check if the class declaration has the 'partial' modifier
- if (classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword))
- {
- return true;
- }
- }
-
- // If no 'partial' modifier is found, return false
- return false;
- }
+ => namedTypeSymbol.ToString().StartsWith("AuroraRgb.");
}
\ No newline at end of file
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/OverrideSetterSourceGenerator.cs b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/OverrideSetterSourceGenerator.cs
index 712b6ef28..421789bcb 100644
--- a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/OverrideSetterSourceGenerator.cs
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/OverrideSetterSourceGenerator.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
@@ -16,81 +17,107 @@ internal class PropertySetter(string accessPath, ITypeSymbol valueType, INamedTy
public bool IsOverride { get; } = propertyIsOverride;
}
-[Generator]
-public class OverrideSetterSourceGenerator : ISourceGenerator
+[Generator(LanguageNames.CSharp)]
+public class OverrideSetterSourceGenerator : IIncrementalGenerator
{
- public void Initialize(GeneratorInitializationContext context)
- {
- }
-
- public void Execute(GeneratorExecutionContext context)
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
const string layerHandlerProperties = "AuroraRgb.Settings.Layers.LayerHandlerProperties";
- var compilation = context.Compilation;
-
- // Retrieve the interface symbol
- var handlerPropertiesInterface = compilation.GetTypeByMetadataName(layerHandlerProperties);
-
- if (handlerPropertiesInterface == null)
- {
- // Interface not found, do nothing
- return;
- }
-
- // Find all classes in the compilation
- var classes = compilation.SyntaxTrees
- .SelectMany(syntaxTree => syntaxTree.GetRoot().DescendantNodes())
- .OfType()
- .Select(declaration => compilation.GetSemanticModel(declaration.SyntaxTree).GetDeclaredSymbol(declaration))
- .OfType()
- .Where(IsSubtypeOf(handlerPropertiesInterface));
-
- List generatedClasses = [handlerPropertiesInterface];
- foreach (var classSymbol in classes)
- {
- try
+ // Get all class declarations and their semantic models
+ var classDeclarations =
+ context.SyntaxProvider
+ .CreateSyntaxProvider(
+ predicate: static (s, _) => s is ClassDeclarationSyntax,
+ transform: (ctx, _) =>
+ {
+ var syntax = (ClassDeclarationSyntax)ctx.Node;
+ var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax) as INamedTypeSymbol;
+ return (Syntax: syntax, Symbol: symbol);
+ });
+
+ // Get the handlerPropertiesInterface
+ var handlerInterface = context.CompilationProvider.Select((c, _) => c.GetTypeByMetadataName(layerHandlerProperties));
+
+ // Combine the class declarations with the interface
+ var relevantClasses = classDeclarations
+ .Where(tuple => tuple.Symbol != null)
+ .Combine(handlerInterface.Select((i, _) => i!))
+ .Where(tuple => IsSubtypeOf(tuple.Right)(tuple.Left.Symbol!))
+ .Select((tuple, _) => (Class: tuple.Left.Symbol!, Interface: tuple.Right));
+
+ // Generate the individual class logic files
+ context.RegisterSourceOutput(relevantClasses,
+ (spc, tuple) =>
{
- GenerateLogic(context, classSymbol);
- generatedClasses.Add(classSymbol);
- GenerateLogicOverridePartial(context, classSymbol);
- }
- catch (Exception e)
+ try
+ {
+ GenerateLogic(spc, tuple.Class);
+ GenerateLogicOverridePartial(spc, tuple.Class);
+ }
+ catch (Exception e)
+ {
+ spc.ReportDiagnostic(Diagnostic.Create(
+ new DiagnosticDescriptor(
+ "ASG001",
+ "Generator Error",
+ "Error generating source: {0}",
+ "SourceGenerator",
+ DiagnosticSeverity.Error,
+ true),
+ Location.None,
+ e.ToString()));
+ }
+ });
+
+ // Collect all generated classes for the GeneratedLogics file
+ var allGeneratedClasses =
+ relevantClasses
+ .Collect()
+ .Select((items, _) =>
+ {
+ var result = new List();
+ if (items.Any())
+ {
+ result.Add(items.First().Interface);
+ result.AddRange(items.Select(i => i.Class));
+ }
+
+ return result.ToImmutableArray();
+ });
+
+ // Generate the GeneratedLogics file
+ context.RegisterSourceOutput(allGeneratedClasses,
+ (spc, classes) =>
{
- Console.Error.WriteLine("uh oh");
- Console.Error.WriteLine(e);
- }
- }
- var source = $$"""
- // Auto-generated code
- // {{DateTime.Now}}
- #nullable enable
+ var source = $$"""
+ // Auto-generated code
+ // {{DateTime.Now}}
+ #nullable enable
- using System;
- using System.Collections.Generic;
-
- namespace AuroraRgb.Settings.Layers
- {
- public static class GeneratedLogics
- {
- private static readonly Dictionary> _innerLogics = new()
- {
- {{string.Join(",\n", generatedClasses.Select(s => s).Where(c => !c.IsGenericType).Select(GetLogicInstanceSource))}}
- };
- public static IReadOnlyDictionary> LogicMap => _innerLogics;
- }
- }
- """;
+ using System;
+ using System.Collections.Generic;
- // Add the generated source to the compilation
- context.AddSource("GeneratedLogics.g.cs", SourceText.From(source, Encoding.UTF8));
- }
+ namespace AuroraRgb.Settings.Layers
+ {
+ public static class GeneratedLogics
+ {
+ private static readonly Dictionary> _innerLogics = new()
+ {
+ {{string.Join(",\n", classes.Where(c => !c.IsGenericType).Select(GetLogicInstanceSource))}}
+ };
+ public static IReadOnlyDictionary> LogicMap => _innerLogics;
+ }
+ }
+ """;
- private static string GetLogicInstanceSource(INamedTypeSymbol arg)
- {
- return $"[\"{arg.Name}\"]\t=\t() => new {arg}Logic()";
+ spc.AddSource("GeneratedLogics.g.cs", SourceText.From(source, Encoding.UTF8));
+ });
}
+ // Rest of the existing helper methods remain the same
+ private static string GetLogicInstanceSource(INamedTypeSymbol arg) => $"[\"{arg.Name}\"]\t=\t() => new {arg}Logic()";
+
private static Func IsSubtypeOf(INamedTypeSymbol upperClass)
{
return classSymbol =>
@@ -110,7 +137,7 @@ private static Func IsSubtypeOf(INamedTypeSymbol upperCl
};
}
- private static void GenerateLogic(GeneratorExecutionContext context, INamedTypeSymbol propertiesClassSymbol)
+ private static void GenerateLogic(SourceProductionContext context, INamedTypeSymbol propertiesClassSymbol)
{
string[] ignore = ["LayerHandlerProperties"];
@@ -119,65 +146,61 @@ private static void GenerateLogic(GeneratorExecutionContext context, INamedTypeS
return;
}
- // Get all properties of the class
var properties = GetClassProperties(propertiesClassSymbol)
.Where(p => p.AccessPath != "Logic")
.ToList();
var logicClassName = AppendClassName(propertiesClassSymbol.Name, "Logic");
- Console.WriteLine(logicClassName);
var genericParams = "";
if (propertiesClassSymbol.IsGenericType)
{
- genericParams = "<" + string.Join(",", propertiesClassSymbol.TypeArguments.Select(t => t.ToString())) + ">";
+ genericParams = "<" + string.Join(",", propertiesClassSymbol.TypeArguments.Select(t => t.ToString())) + ">";
}
var source = $$"""
- // Auto-generated code
- // {{DateTime.Now}}
- // GenerateClassProperties
- #nullable enable
-
- using System;
- using System.Collections.Generic;
-
- namespace {{propertiesClassSymbol.ContainingNamespace}}
- {
- public partial class {{logicClassName}}{{genericParams}} : {{AppendClassName(propertiesClassSymbol.BaseType.ToString(), "Logic")}}
- {
- {{string.Join("\n", properties.Where(p => !p.IsOverride).Select((Func)PropertyDefinitionSource))}}
-
- private static readonly Dictionary> InnerSetters = new()
- {
- {{string.Join(",\n", properties.Select((Func)SetMethodSource))}}
- };
- public override IReadOnlyDictionary> SetterMap => InnerSetters;
- }
- }
- """;
+ // Auto-generated code
+ // {{DateTime.Now}}
+ // GenerateClassProperties
+ #nullable enable
+
+ using System;
+ using System.Collections.Generic;
+
+ namespace {{propertiesClassSymbol.ContainingNamespace}}
+ {
+ public partial class {{logicClassName}}{{genericParams}} : {{AppendClassName(propertiesClassSymbol.BaseType.ToString(), "Logic")}}
+ {
+ {{string.Join("\n", properties.Where(p => !p.IsOverride).Select((Func)PropertyDefinitionSource))}}
+
+ private static readonly Dictionary> InnerSetters = new()
+ {
+ {{string.Join(",\n", properties.Select((Func)SetMethodSource))}}
+ };
+ public override IReadOnlyDictionary> SetterMap => InnerSetters;
+ }
+ }
+ """;
var genericFileSuffix = string.Join(".", propertiesClassSymbol.TypeArguments.Select(t => t.ToString()));
- // Add the generated source to the compilation
context.AddSource(logicClassName + genericFileSuffix + ".g.cs", SourceText.From(source, Encoding.UTF8));
}
- private void GenerateLogicOverridePartial(GeneratorExecutionContext context, INamedTypeSymbol classSymbol)
+ private static void GenerateLogicOverridePartial(SourceProductionContext context, INamedTypeSymbol classSymbol)
{
- // Get all properties of the class
var logicClassName = AppendClassName(classSymbol.ToString(), "Logic");
var genericParams = "";
if (classSymbol.IsGenericType)
{
- genericParams = "<" + string.Join(",", classSymbol.TypeArguments.Select(t => t.ToString())) + ">";
+ genericParams = "<" + string.Join(",", classSymbol.TypeArguments.Select(t => t.ToString())) + ">";
}
var genericConstraints = "";
if (classSymbol.IsGenericType)
{
var constraints = classSymbol.TypeParameters
- .SelectMany(t => t.ConstraintTypes.Select(c => t.Name + " : " + c));
- genericConstraints = "where " + string.Join(",", constraints);
+ .SelectMany(t => t.ConstraintTypes.Select(c => t.Name + " : " + c));
+ genericConstraints = "where " + string.Join(",", constraints);
}
var source = $$"""
@@ -196,14 +219,13 @@ namespace {{classSymbol.ContainingNamespace}}
public partial class {{classSymbol.Name}}{{genericParams}}
{{genericConstraints}}
{
- [GameStateIgnore, JsonIgnore]
- public {{logicClassName}}? Logic { get; set; }
+ [GameStateIgnore, JsonIgnore]
+ public {{logicClassName}}? Logic { get; set; }
}
}
""";
var genericFileSuffix = string.Join(".", classSymbol.TypeArguments.Select(t => t.ToString()));
- // Add the generated source to the compilation
context.AddSource(classSymbol.Name + genericFileSuffix + ".g.cs", SourceText.From(source, Encoding.UTF8));
}
@@ -227,18 +249,19 @@ private static string PropertyDefinitionSource(PropertySetter valueTuple)
var propertyType = valueType.ToString().EndsWith("?") ? valueType.ToString() : valueType + "?";
var firstCharIndex = accessPath.LastIndexOf('_') + 1;
-
+
var lowerPropertyName = char.ToLower(accessPath[firstCharIndex]) + accessPath.Substring(firstCharIndex + 1);
var upperPropertyName = char.ToUpper(accessPath[firstCharIndex]) + accessPath.Substring(firstCharIndex + 1);
- string[] properties = [
+ string[] properties =
+ [
lowerPropertyName,
upperPropertyName,
$"_{lowerPropertyName}",
$"_{upperPropertyName}",
accessPath
];
-
+
var propertySources = properties.Distinct()
.Except([fieldName])
.Select(p => $$"""
@@ -252,13 +275,13 @@ private static string PropertyDefinitionSource(PropertySetter valueTuple)
}
""");
-
+
return $"""
- // field
- public {propertyType} {fieldName};
-
- {string.Join("", propertySources)}
- """;
+ // field
+ public {propertyType} {fieldName};
+
+ {string.Join("", propertySources)}
+ """;
}
private static string SetMethodSource(PropertySetter valueTuple)
@@ -315,10 +338,11 @@ private static string RemoveNullable(string typeName)
private static IEnumerable GetClassProperties(INamedTypeSymbol classSymbol)
{
- return GetBaseTypes(classSymbol)
+ return ClassUtils.GetBaseTypes(classSymbol)
.SelectMany(c => c.GetMembers())
.OfType()
- .Where(property => property.GetMethod?.DeclaredAccessibility.HasFlag(Accessibility.Public) ?? (property.SetMethod?.DeclaredAccessibility.HasFlag(Accessibility.Internal) ?? false))
+ .Where(property => property.GetMethod?.DeclaredAccessibility.HasFlag(Accessibility.Public) ??
+ (property.SetMethod?.DeclaredAccessibility.HasFlag(Accessibility.Internal) ?? false))
.Where(property => !property.IsStatic)
.Where(p => IsLogicOverridable(p) || !p.Name.StartsWith("_"))
.Select(symbol => GetMemberSetter(symbol, classSymbol));
@@ -329,19 +353,9 @@ private static bool IsLogicOverridable(IPropertySymbol propertySymbol)
return propertySymbol.GetAttributes().Any(a => a.AttributeClass?.Name == "LogicOverridableAttribute");
}
- private static IEnumerable GetBaseTypes(INamedTypeSymbol type)
- {
- var currentType = type;
- while (currentType != null)
- {
- yield return currentType;
- currentType = currentType.BaseType;
- }
- }
-
private static PropertySetter GetMemberSetter(IPropertySymbol property, INamedTypeSymbol baseType)
{
- return new PropertySetter(property.Name, property.Type, baseType, !SymbolEqualityComparer.IncludeNullability.Equals(property.ContainingType, baseType));
+ return new PropertySetter(property.Name, property.Type, baseType, !SymbolEqualityComparer.IncludeNullability.Equals(property.ContainingType, baseType));
}
private static bool IsAuroraClass(INamedTypeSymbol? namedTypeSymbol)
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/Properties/launchSettings.json b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/Properties/launchSettings.json
index b26726185..0d4004984 100644
--- a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/Properties/launchSettings.json
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"Generators": {
"commandName": "DebugRoslynComponent",
- "targetProject": "../../Project-Aurora/Project-Aurora.csproj"
+ "targetProject": "..\\..\\Project-Aurora\\Project-Aurora.csproj"
}
},
"$schema": "https://json.schemastore.org/launchsettings.json"
diff --git a/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/WrapperGenerator.cs b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/WrapperGenerator.cs
new file mode 100644
index 000000000..b194e66cb
--- /dev/null
+++ b/Project-Aurora/AuroraSourceGenerator/AuroraSourceGenerator/WrapperGenerator.cs
@@ -0,0 +1,273 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+namespace AuroraSourceGenerator;
+
+[Generator(LanguageNames.CSharp)]
+public class WrapperGenerator : IIncrementalGenerator
+{
+ private const string AttributeNamespace = "AuroraSourceGenerator";
+ private const string DelegateToAttributeClassname = "DelegateToAttribute";
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ // Register the attribute
+ context.RegisterPostInitializationOutput(ctx => ctx.AddSource(
+ "DelegateToAttribute.g.cs",
+ SourceText.From($$"""
+ using System;
+
+ namespace {{AttributeNamespace}}
+ {
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class {{DelegateToAttributeClassname}}(string field) : System.Attribute
+ {
+ public string Field { get; } = field;
+ }
+ }
+ """, Encoding.UTF8)
+ ));
+
+ // Create a pipeline for finding decorated classes
+ var classDeclarations = context.SyntaxProvider
+ .CreateSyntaxProvider(
+ predicate: static (s, _) => s is ClassDeclarationSyntax,
+ transform: static (ctx, _) => GetClassToGenerate(ctx))
+ .Where(static m => m is not null);
+
+ // Register the source output
+ context.RegisterSourceOutput(classDeclarations,
+ static (spc, classInfo) => Execute(spc, classInfo!));
+ }
+
+ private static ClassToGenerate? GetClassToGenerate(GeneratorSyntaxContext context)
+ {
+ var wrappedClass = (ClassDeclarationSyntax)context.Node;
+ var model = context.SemanticModel;
+
+ if (model.GetDeclaredSymbol(wrappedClass) is not INamedTypeSymbol wrapperClass)
+ {
+ return null;
+ }
+
+ var delegateAttribute = wrapperClass.GetAttributes()
+ .FirstOrDefault(attr => DelegateToAttributeClassname == attr.AttributeClass?.Name);
+
+ if (delegateAttribute == null)
+ {
+ return null;
+ }
+
+ var delegateFieldName = delegateAttribute.ConstructorArguments[0].Value?.ToString();
+ if (delegateFieldName == null)
+ {
+ return null;
+ }
+
+ var delegateField = wrapperClass.GetMembers()
+ .OfType()
+ .FirstOrDefault(field => field.Name == delegateFieldName);
+
+ if (delegateField == null)
+ {
+ return null;
+ }
+
+ var definedMethodNames = ClassUtils.GetBaseTypes(wrapperClass)
+ .SelectMany(c => c.GetMembers())
+ .OfType()
+ .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary)
+ .Where(IsPublic)
+ .Select(s => s.Name)
+ .ToImmutableHashSet();
+
+ var definedPropertyNames = ClassUtils.GetBaseTypes(wrapperClass)
+ .SelectMany(c => c.GetMembers())
+ .OfType()
+ .Where(p => !p.IsStatic)
+ .Where(IsPublic)
+ .Select(s => s.Name)
+ .ToImmutableHashSet();
+
+ var delegateClass = delegateField.Type;
+
+ // Collect methods and properties
+ var methods = ClassUtils.GetBaseTypes(delegateClass)
+ .Union(ClassUtils.GetAllInterfaces(wrapperClass), SymbolEqualityComparer.IncludeNullability)
+ .SelectMany(c => c.GetMembers())
+ .OfType()
+ .Distinct(SymbolEqualityComparer.IncludeNullability)
+ .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary)
+ .Where(IsPublic)
+ .Where(m => !definedMethodNames.Contains(m.Name))
+ .Select(GetMethodToGenerate)
+ .ToList();
+
+ var properties = ClassUtils.GetBaseTypes(delegateClass)
+ .SelectMany(c => c.GetMembers())
+ .OfType()
+ .Where(p => !p.IsStatic)
+ .Where(IsPublic)
+ .Where(m => !definedPropertyNames.Contains(m.Name))
+ .Select(GetPropertyToGenerate)
+ .ToList();
+
+ return new ClassToGenerate(
+ wrapperClass.Name,
+ wrapperClass.ContainingNamespace.ToDisplayString(),
+ delegateFieldName,
+ methods,
+ properties);
+ }
+
+ private static void Execute(SourceProductionContext context, ClassToGenerate classInfo)
+ {
+ var source = GenerateWrapperClass(classInfo);
+ context.AddSource($"{classInfo.ClassName}.Wrapper.g.cs",
+ SourceText.From(source, Encoding.UTF8));
+ }
+
+ private static string GenerateWrapperClass(ClassToGenerate classInfo)
+ {
+ var sb = new StringBuilder();
+
+ sb.AppendLine($$"""
+ namespace {{classInfo.Namespace}}
+ {
+ public partial class {{classInfo.ClassName}}
+ {
+ """
+ );
+
+ // Generate delegating methods and properties
+ foreach (var property in classInfo.Properties)
+ {
+ sb.AppendLine($$"""
+ public {{property.Type}} {{property.Name}}
+ {
+ """
+ );
+ if (property.HasGetter)
+ {
+ sb.AppendLine($" get => {classInfo.FieldName}.{property.Name};");
+ }
+ if (property.HasSetter)
+ {
+ sb.AppendLine($" set => {classInfo.FieldName}.{property.Name} = value;");
+ }
+ sb.AppendLine(""" }"""
+ );
+ }
+
+ foreach (var method in classInfo.Methods)
+ {
+ if (method.ReturnType != "void")
+ {
+ sb.AppendLine($$"""
+ public {{method.ReturnType}} {{method.Name}}({{method.Parameters}})
+ {
+ return {{classInfo.FieldName}}.{{method.Name}}({{method.ParameterNames}});
+ }
+ """
+ );
+ }
+ else
+ {
+ sb.AppendLine($$"""
+ public {{method.ReturnType}} {{method.Name}}({{method.Parameters}})
+ {
+ {{classInfo.FieldName}}.{{method.Name}}({{method.ParameterNames}});
+ }
+ """
+ );
+ }
+ }
+
+ sb.AppendLine("""
+ }
+ }
+ """
+ );
+
+ return sb.ToString();
+ }
+
+ private static bool IsPublic(ISymbol m)
+ {
+ return m.DeclaredAccessibility.HasFlag(Accessibility.Public);
+ }
+
+ private static PropertyToGenerate GetPropertyToGenerate(IPropertySymbol p)
+ {
+ return new PropertyToGenerate(p.Name, p.Type.ToDisplayString(), p.GetMethod != null, p.SetMethod != null);
+ }
+
+ private static MethodToGenerate GetMethodToGenerate(IMethodSymbol m)
+ {
+ return new MethodToGenerate(
+ m.Name,
+ m.ReturnType.ToDisplayString(),
+ string.Join(", ", m.Parameters.Select(ParameterNameWithModifiers)),
+ string.Join(", ", m.Parameters.Select(ReferenceName))
+ );
+
+ static string ParameterNameWithModifiers(IParameterSymbol p)
+ {
+ var typeAndName = $"{p.Type.ToDisplayString()} {p.Name}";
+
+ var modifiers = p.RefKind switch
+ {
+ RefKind.None => string.Empty,
+ RefKind.In => "in ",
+ RefKind.Out => "out ",
+ RefKind.Ref => "ref ",
+ RefKind.RefReadOnlyParameter => "ref readonly ",
+ };
+ var defaultPart = DefaultPart(p);
+ return modifiers + typeAndName + defaultPart;
+ }
+
+ static string ReferenceName(IParameterSymbol p)
+ {
+ return p.RefKind switch
+ {
+ RefKind.RefReadOnlyParameter => "in " + p.Name,
+ _ => p.Name,
+ };
+ }
+
+ static string DefaultPart(IParameterSymbol p)
+ {
+ if (!p.HasExplicitDefaultValue) return string.Empty;
+ if (p.Type.TypeKind == TypeKind.Enum)
+ {
+ if (p.ExplicitDefaultValue == null)
+ return " = default";
+ var enumName = p.Type.ToDisplayString();
+ return $" = ({enumName})" + p.ExplicitDefaultValue;
+ }
+ if (p.Type.IsValueType)
+ {
+ return " = " + (p.ExplicitDefaultValue ?? "default").ToString().ToLowerInvariant();
+ }
+
+ return " = " + (p.ExplicitDefaultValue ?? "default");
+ }
+ }
+
+ private sealed record ClassToGenerate(
+ string ClassName,
+ string Namespace,
+ string FieldName,
+ List Methods,
+ List Properties);
+
+ private sealed record MethodToGenerate(string Name, string ReturnType, string Parameters, string ParameterNames);
+
+ private sealed record PropertyToGenerate(string Name, string Type, bool HasGetter, bool HasSetter);
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiBitmap.cs
index 120bd3bff..2dbc2c37c 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiBitmap.cs
@@ -15,14 +15,14 @@ public sealed class GdiBitmap : IAuroraBitmap
//TODO expose SavePng method to interface and remove this
public Bitmap Bitmap { get; }
- private float _opacity = 1;
- public float Opacity
+ private double _opacity = 1;
+ public double Opacity
{
get => _opacity;
set
{
_opacity = value;
- _colorMatrix.Matrix33 = value;
+ _colorMatrix.Matrix33 = (float)value;
_imageAttributes.SetColorMatrix(_colorMatrix);
}
}
@@ -56,10 +56,11 @@ private TextureBrush TextureBrush
}
_textureBrush = new TextureBrush(Bitmap, _dimension, _imageAttributes);
-
return _textureBrush;
}
}
+
+ private static readonly SolidBrush ColorBrush = new(Color.Transparent);
public GdiBitmap(int canvasWidth, int canvasHeight)
{
@@ -85,7 +86,7 @@ private void SetGraphics()
public IBitmapReader CreateReader()
{
- return new GdiPartialCopyBitmapReader(Bitmap);
+ return new GdiPartialCopyBitmapReader(Bitmap, _opacity);
}
public void Reset()
@@ -113,16 +114,11 @@ public void DrawRectangle(Pen pen, RectangleF dimension)
public void DrawRectangle(EffectLayer brush)
{
- var gdiBitmap = GetGdiBitmap(brush.GetBitmap());
+ var bitmapEffectLayer = (BitmapEffectLayer)brush;
+ var gdiBitmap = GetGdiBitmap(bitmapEffectLayer.GetBitmap());
DrawOver(gdiBitmap);
}
- public void DrawRectangle(EffectLayer brush, Rectangle dimension)
- {
- var gdiBitmap = GetGdiBitmap(brush.GetBitmap());
- DrawRectangle(gdiBitmap.TextureBrush, dimension);
- }
-
public void DrawRectangle(IAuroraBrush brush, RectangleF dimension)
{
DrawRectangle(brush.GetBrush(), dimension);
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiPartialCopyBitmapReader.cs b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiPartialCopyBitmapReader.cs
index ee4ba0924..69c41bd6b 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiPartialCopyBitmapReader.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiPartialCopyBitmapReader.cs
@@ -1,103 +1,196 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
using Common.Utils;
namespace AuroraRgb.Bitmaps.GdiPlus;
public sealed class GdiPartialCopyBitmapReader : IBitmapReader
{
- //B, G, R, A
- private static readonly long[] ColorData = [0L, 0L, 0L, 0L];
- private static readonly Dictionary Bitmaps = new(20);
+ private const int SmallestBufferLength = 32;
+ private static readonly Dictionary Bitmaps = new(20);
+
// ReSharper disable once CollectionNeverQueried.Local //to keep reference
- private static readonly Dictionary BitmapBuffers = new(20);
+ private static readonly Dictionary BitmapBuffers = new(20);
private readonly Bitmap _bitmap;
- private readonly Size _bitmapSize = Size.Empty;
private readonly RectangleF _dimension;
+ private readonly double _opacity;
+ private readonly Vector256 _zeroVector = Vector256.Zero;
+
+ private Color _transparentColor = Color.Transparent;
+ private Color _currentColor = Color.Black;
+
+ private readonly int[] _emptySmallestBuffer = new int[SmallestBufferLength];
- public GdiPartialCopyBitmapReader(Bitmap bitmap)
+ public GdiPartialCopyBitmapReader(Bitmap bitmap, double opacity)
{
_bitmap = bitmap;
+ _opacity = opacity;
var graphicsUnit = GraphicsUnit.Pixel;
_dimension = bitmap.GetBounds(ref graphicsUnit);
-
- _bitmapSize = bitmap.Size;
}
/**
- * Gets average color of region, ignoring transparency
- * NOT thread-safe
+ * Optimized with SIMD instructions where available
*/
- public Color GetRegionColor(Rectangle rectangle)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref readonly Color GetRegionColor(Rectangle rectangle)
{
if (rectangle.Width == 0 || rectangle.Height == 0 || !_dimension.Contains(rectangle))
- return Color.Black;
-
- ColorData[0] = 0L;
- ColorData[1] = 0L;
- ColorData[2] = 0L;
- ColorData[3] = 0L;
+ return ref _transparentColor;
- if (!Bitmaps.TryGetValue(rectangle.Size, out var buff))
+ var area = rectangle.Width * rectangle.Height;
+ var bufferArea = Math.Max(area, SmallestBufferLength);
+ if (!Bitmaps.TryGetValue(bufferArea, out var buff))
{
- var bitmapBuffer = new int[rectangle.Width * rectangle.Height];
- BitmapBuffers[rectangle.Size] = bitmapBuffer;
+ buff = CreateBuffer(rectangle);
+ Bitmaps[bufferArea] = buff;
+ }
- var buffer = Marshal.AllocHGlobal(bitmapBuffer.Length * sizeof(int));
- Marshal.Copy(bitmapBuffer, 0, buffer, bitmapBuffer.Length);
- // Create new bitmap data.
- buff = new BitmapData
- {
- Width = rectangle.Width,
- Height = rectangle.Height,
- PixelFormat = PixelFormat.Format32bppArgb,
- Stride = rectangle.Width * sizeof(int),
- Scan0 = buffer
- };
-
- Bitmaps[rectangle.Size] = buff;
+ if (area < SmallestBufferLength)
+ {
+ // clear the padded array
+ Array.Copy(_emptySmallestBuffer, 0, BitmapBuffers[SmallestBufferLength], 0, _emptySmallestBuffer.Length);
}
var srcData = _bitmap.LockBits(
rectangle,
- (ImageLockMode)5, //ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
- PixelFormat.Format32bppRgb, buff);
- var scan0 = srcData.Scan0;
+ (ImageLockMode)5, //ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
+ PixelFormat.Format32bppArgb,
+ buff);
+
+ var totals = ProcessPixels(srcData.Scan0, area);
+
+ _bitmap.UnlockBits(srcData);
+
+ var divider = area / _opacity;
+ _currentColor = CommonColorUtils.FastColor(
+ (byte)(totals.R / divider),
+ (byte)(totals.G / divider),
+ (byte)(totals.B / divider),
+ (byte)(totals.A / divider)
+ );
+ return ref _currentColor;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private unsafe (long R, long G, long B, long A) ProcessPixels(in IntPtr scan0, int area)
+ {
+ var p = (byte*)scan0;
+ long sumB = 0, sumG = 0, sumR = 0, sumA = 0;
- var rectangleHeight = rectangle.Height;
- var rectangleWidth = rectangle.Width;
- unsafe
+ if (Avx2.IsSupported && area >= 32)
{
- var p = (byte*)(void*)scan0;
+ var vectorSumB = _zeroVector;
+ var vectorSumG = _zeroVector;
+ var vectorSumR = _zeroVector;
+ var vectorSumA = _zeroVector;
- var j = 0;
- for (var y = 0; y < rectangleHeight; y++)
+ // Process 32 pixels at a time (32 * 4 bytes = 128 bytes)
+ var fullVector = Vector256.Create(0xFF);
+ var vectorCount = area / 32;
+ for (var i = 0; i < vectorCount; i++)
{
- for (var x = 0; x < rectangleWidth; x++)
- {
- ColorData[0] += p[j++];
- ColorData[1] += p[j++];
- ColorData[2] += p[j++];
- ColorData[3] += p[j++];
- }
+ var offset = i * 128;
+ var vector1 = Avx.LoadVector256((int*)(p + offset));
+ var vector2 = Avx.LoadVector256((int*)(p + offset + 32));
+ var vector3 = Avx.LoadVector256((int*)(p + offset + 64));
+ var vector4 = Avx.LoadVector256((int*)(p + offset + 96));
+
+ vectorSumB = Avx2.Add(vectorSumB, Avx2.And(vector1, fullVector));
+ vectorSumG = Avx2.Add(vectorSumG, Avx2.And(Avx2.ShiftRightLogical(vector1, 8), fullVector));
+ vectorSumR = Avx2.Add(vectorSumR, Avx2.And(Avx2.ShiftRightLogical(vector1, 16), fullVector));
+ vectorSumA = Avx2.Add(vectorSumA, Avx2.And(Avx2.ShiftRightLogical(vector1, 24), fullVector));
+
+ // Repeat for other vectors...
+ vectorSumB = Avx2.Add(vectorSumB, Avx2.And(vector2, fullVector));
+ vectorSumG = Avx2.Add(vectorSumG, Avx2.And(Avx2.ShiftRightLogical(vector2, 8), fullVector));
+ vectorSumR = Avx2.Add(vectorSumR, Avx2.And(Avx2.ShiftRightLogical(vector2, 16), fullVector));
+ vectorSumA = Avx2.Add(vectorSumA, Avx2.And(Avx2.ShiftRightLogical(vector2, 24), fullVector));
+
+ vectorSumB = Avx2.Add(vectorSumB, Avx2.And(vector3, fullVector));
+ vectorSumG = Avx2.Add(vectorSumG, Avx2.And(Avx2.ShiftRightLogical(vector3, 8), fullVector));
+ vectorSumR = Avx2.Add(vectorSumR, Avx2.And(Avx2.ShiftRightLogical(vector3, 16), fullVector));
+ vectorSumA = Avx2.Add(vectorSumA, Avx2.And(Avx2.ShiftRightLogical(vector3, 24), fullVector));
+
+ vectorSumB = Avx2.Add(vectorSumB, Avx2.And(vector4, fullVector));
+ vectorSumG = Avx2.Add(vectorSumG, Avx2.And(Avx2.ShiftRightLogical(vector4, 8), fullVector));
+ vectorSumR = Avx2.Add(vectorSumR, Avx2.And(Avx2.ShiftRightLogical(vector4, 16), fullVector));
+ vectorSumA = Avx2.Add(vectorSumA, Avx2.And(Avx2.ShiftRightLogical(vector4, 24), fullVector));
}
+
+ // Sum up the vector lanes
+ sumB = SumVector256(vectorSumB);
+ sumG = SumVector256(vectorSumG);
+ sumR = SumVector256(vectorSumR);
+ sumA = SumVector256(vectorSumA);
+
+ // Process remaining pixels
+ var processed = vectorCount * 32;
+ var remaining = area - processed;
+ p += processed * 4;
+ area = remaining;
}
- _bitmap.UnlockBits(srcData);
- var area = ColorData[3] / 255;
- if (area == 0)
+ // Process remaining pixels or all pixels if AVX2 is not supported
+ var end = area * 4;
+ for (var j = 0; j < end;)
{
- return Color.Transparent;
+ sumB += p[j++];
+ sumG += p[j++];
+ sumR += p[j++];
+ sumA += p[j++];
}
- return CommonColorUtils.FastColor(
- (byte) (ColorData[2] / area), (byte) (ColorData[1] / area), (byte) (ColorData[0] / area)
- );
+
+ return (sumR, sumG, sumB, sumA);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static long SumVector256(in Vector256 vector)
+ {
+ var sum = 0L;
+ for (var i = 0; i < 8; i++)
+ {
+ sum += vector.GetElement(i);
+ }
+
+ return sum;
+ }
+
+ private static BitmapData CreateBuffer(in Rectangle rectangle)
+ {
+ var area = rectangle.Width * rectangle.Height;
+ var bufferArea = Math.Max(area, SmallestBufferLength);
+ var bitmapBuffer = new int[bufferArea];
+ BitmapBuffers[bufferArea] = bitmapBuffer;
+
+ var buffer = Marshal.AllocHGlobal(bitmapBuffer.Length * sizeof(int));
+ Marshal.Copy(bitmapBuffer, 0, buffer, bitmapBuffer.Length);
+
+ return new BitmapData
+ {
+ Width = rectangle.Width,
+ Height = rectangle.Height,
+ PixelFormat = PixelFormat.Format32bppArgb,
+ Stride = rectangle.Width * sizeof(int),
+ Scan0 = buffer
+ };
}
public void Dispose()
{
+ foreach (var bitmapData in Bitmaps.Values)
+ {
+ Marshal.FreeHGlobal(bitmapData.Scan0);
+ }
+
+ Bitmaps.Clear();
+ BitmapBuffers.Clear();
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiSingleCopyBitmapReader.cs b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiSingleCopyBitmapReader.cs
index 185df4c2b..734cdbdd0 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiSingleCopyBitmapReader.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiSingleCopyBitmapReader.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Common.Utils;
@@ -21,6 +22,9 @@ public sealed class GdiSingleCopyBitmapReader : IBitmapReader
private readonly BitmapData _srcData;
private readonly IntPtr _scan0;
+
+ private Color _transparentColor = Color.Transparent;
+ private Color _currentColor = Color.Black;
public GdiSingleCopyBitmapReader(Bitmap bitmap)
{
@@ -41,7 +45,7 @@ public GdiSingleCopyBitmapReader(Bitmap bitmap)
_srcData = _bitmap.LockBits(
rectangle,
(ImageLockMode)5, //ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
- PixelFormat.Format32bppRgb, buff);
+ PixelFormat.Format32bppArgb, buff);
_scan0 = _srcData.Scan0;
}
@@ -49,10 +53,11 @@ public GdiSingleCopyBitmapReader(Bitmap bitmap)
* Gets average color of region, ignoring transparency
* NOT thread-safe
*/
- public Color GetRegionColor(Rectangle rectangle)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref readonly Color GetRegionColor(Rectangle rectangle)
{
if (rectangle.Width == 0 || rectangle.Height == 0 || !_dimension.Contains(rectangle))
- return Color.Black;
+ return ref _transparentColor;
ColorData[0] = 0L;
ColorData[1] = 0L;
@@ -91,11 +96,12 @@ public Color GetRegionColor(Rectangle rectangle)
var area = ColorData[3] / 255;
if (area == 0)
{
- return Color.Transparent;
+ return ref _transparentColor;
}
- return CommonColorUtils.FastColor(
+ _currentColor = CommonColorUtils.FastColor(
(byte) (ColorData[2] / area), (byte) (ColorData[1] / area), (byte) (ColorData[0] / area)
);
+ return ref _currentColor;
}
private static BitmapData CreateBitmapData(Size size)
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/IAuroraBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/IAuroraBitmap.cs
index ea6a0498d..a2ada8d96 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/IAuroraBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/IAuroraBitmap.cs
@@ -9,7 +9,7 @@ namespace AuroraRgb.Bitmaps;
public interface IAuroraBitmap : IDisposable
{
- float Opacity { get; set; }
+ double Opacity { get; set; }
IBitmapReader CreateReader();
@@ -18,7 +18,6 @@ public interface IAuroraBitmap : IDisposable
void DrawRectangle(Brush brush, RectangleF dimension);
void DrawRectangle(Pen pen, RectangleF dimension);
void DrawRectangle(EffectLayer brush);
- void DrawRectangle(EffectLayer brush, Rectangle dimension);
void DrawRectangle(IAuroraBrush brush, Rectangle dimension);
void DrawRectangle(IAuroraBrush brush, RectangleF dimension);
void ReplaceRectangle(Brush brush, Rectangle dimension);
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/IBitmapReader.cs b/Project-Aurora/Project-Aurora/Bitmaps/IBitmapReader.cs
index c93b350af..a5e43f965 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/IBitmapReader.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/IBitmapReader.cs
@@ -1,9 +1,11 @@
using System;
using System.Drawing;
+using System.Runtime.CompilerServices;
namespace AuroraRgb.Bitmaps;
public interface IBitmapReader : IDisposable
{
- Color GetRegionColor(Rectangle rectangle);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ ref readonly Color GetRegionColor(Rectangle rectangle);
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/RuntimeChangingBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/RuntimeChangingBitmap.cs
index b12846495..22593de54 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/RuntimeChangingBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/RuntimeChangingBitmap.cs
@@ -1,147 +1,19 @@
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using AuroraRgb.Bitmaps.GdiPlus;
+using AuroraRgb.Bitmaps.GdiPlus;
using AuroraRgb.Bitmaps.Skia;
-using AuroraRgb.BrushAdapters;
-using AuroraRgb.EffectsEngine;
-using AuroraRgb.Settings;
+using AuroraSourceGenerator;
namespace AuroraRgb.Bitmaps;
-public sealed class RuntimeChangingBitmap : IAuroraBitmap
+[DelegateTo(nameof(_bitmap))]
+public sealed partial class RuntimeChangingBitmap : IAuroraBitmap
{
private readonly IAuroraBitmap _bitmap;
- public float Opacity
- {
- get => _bitmap.Opacity;
- set => _bitmap.Opacity = value;
- }
-
public RuntimeChangingBitmap(int canvasWidth, int canvasHeight, bool readable)
{
_bitmap = new GdiBitmap(canvasWidth, canvasHeight);
}
- public IBitmapReader CreateReader()
- {
- return _bitmap.CreateReader();
- }
-
- public void Reset()
- {
- _bitmap.Reset();
- }
-
- public void DrawRectangle(Brush brush, Rectangle dimension)
- {
- _bitmap.DrawRectangle(brush, dimension);
- }
-
- public void DrawRectangle(Brush brush, RectangleF dimension)
- {
- _bitmap.DrawRectangle(brush, dimension);
- }
-
- public void DrawRectangle(Pen pen, RectangleF dimension)
- {
- _bitmap.DrawRectangle(pen, dimension);
- }
-
- public void DrawRectangle(IAuroraBrush brush, RectangleF dimension)
- {
- _bitmap.DrawRectangle(brush, dimension);
- }
-
- public void DrawRectangle(EffectLayer brush)
- {
- _bitmap.DrawRectangle(brush);
- }
-
- public void DrawRectangle(EffectLayer brush, Rectangle dimension)
- {
- _bitmap.DrawRectangle(brush, dimension);
- }
-
- public void DrawRectangle(IAuroraBrush brush, Rectangle dimension)
- {
- _bitmap.DrawRectangle(brush, dimension);
- }
-
- public void ReplaceRectangle(Brush brush, Rectangle dimension)
- {
- _bitmap.ReplaceRectangle(brush, dimension);
- }
-
- public void ReplaceRectangle(Brush brush, RectangleF dimension)
- {
- _bitmap.ReplaceRectangle(brush, dimension);
- }
-
- public void ReplaceRectangle(IAuroraBrush brush, Rectangle dimension)
- {
- _bitmap.ReplaceRectangle(brush, dimension);
- }
-
- public void ReplaceRectangle(IAuroraBrush brush, RectangleF dimension)
- {
- _bitmap.ReplaceRectangle(brush, dimension);
- }
-
- public void PerformExclude(KeySequence excludeSequence)
- {
- _bitmap.PerformExclude(excludeSequence);
- }
-
- public void OnlyInclude(KeySequence sequence)
- {
- _bitmap.OnlyInclude(sequence);
- }
-
- public void SetClip(RectangleF boundsRaw) => _bitmap.SetClip(boundsRaw);
-
- public void SetTransform(Matrix value) => _bitmap.SetTransform(value);
-
- public void DrawEllipse(Pen pen, RectangleF dimension)
- {
- _bitmap.DrawEllipse(pen, dimension);
- }
-
- public void FillEllipse(Brush pen, RectangleF dimension)
- {
- _bitmap.FillEllipse(pen, dimension);
- }
-
- public void FillEllipse(IAuroraBrush brush, Rectangle dimension)
- {
- _bitmap.FillEllipse(brush, dimension);
- }
-
- public void FillEllipse(IAuroraBrush brush, RectangleF dimension)
- {
- _bitmap.FillEllipse(brush, dimension);
- }
-
- public void DrawImage(Image image, float x = 0, float y = 0, float width = 0, float height = 0)
- {
- _bitmap.DrawImage(image, x, y, width, height);
- }
-
- public void DrawLine(Pen pen, PointF startPoint, PointF endPoint)
- {
- _bitmap.DrawLine(pen, startPoint, endPoint);
- }
-
- public void Fill(Brush brush)
- {
- _bitmap.Fill(brush);
- }
-
- public void Dispose()
- {
- _bitmap.Dispose();
- }
-
public GdiBitmap GetGdiBitmap()
{
if (_bitmap is GdiBitmap gdiBitmap)
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraCpuSkiaBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraCpuSkiaBitmap.cs
index ddaaafebb..4e1c3cbea 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraCpuSkiaBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraCpuSkiaBitmap.cs
@@ -23,7 +23,8 @@ public override IBitmapReader CreateReader()
public override void DrawRectangle(EffectLayer brush)
{
- var auroraSkiaBitmap = (AuroraCpuSkiaBitmap)GetSkiaBitmap(brush.GetBitmap());
+ var bitmapEffectLayer = (BitmapEffectLayer)brush;
+ var auroraSkiaBitmap = (AuroraCpuSkiaBitmap)GetSkiaBitmap(bitmapEffectLayer.GetBitmap());
SkPaint.Color = new SKColor(255, 255, 255, (byte)(auroraSkiaBitmap.Opacity * 255));
var skiaBitmap = auroraSkiaBitmap._bitmap;
Canvas.DrawBitmap(skiaBitmap, 0, 0, SkPaint);
@@ -31,7 +32,8 @@ public override void DrawRectangle(EffectLayer brush)
public override void DrawRectangle(EffectLayer brush, Rectangle dimension)
{
- var auroraSkiaBitmap = (AuroraCpuSkiaBitmap)GetSkiaBitmap(brush.GetBitmap());
+ var bitmapEffectLayer = (BitmapEffectLayer)brush;
+ var auroraSkiaBitmap = (AuroraCpuSkiaBitmap)GetSkiaBitmap(bitmapEffectLayer.GetBitmap());
SkPaint.Color = new SKColor(255, 255, 255, (byte)(auroraSkiaBitmap.Opacity * 255));
var skiaBitmap = auroraSkiaBitmap._bitmap;
var rectangle = SkiaRectangle(dimension);
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraVulkanSkiaBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraVulkanSkiaBitmap.cs
index 5964ee793..11aa6b7a1 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraVulkanSkiaBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/Skia/AuroraVulkanSkiaBitmap.cs
@@ -46,7 +46,8 @@ public override IBitmapReader CreateReader()
public override void DrawRectangle(EffectLayer brush)
{
- var auroraSkiaBitmap = (AuroraVulkanSkiaBitmap)GetSkiaBitmap(brush.GetBitmap());
+ var bitmapEffectLayer = (BitmapEffectLayer)brush;
+ var auroraSkiaBitmap = (AuroraVulkanSkiaBitmap)GetSkiaBitmap(bitmapEffectLayer.GetBitmap());
SkPaint.Color = new SKColor(255, 255, 255, (byte)(auroraSkiaBitmap.Opacity * 255));
var skiaBitmap = auroraSkiaBitmap._surface;
Canvas.DrawSurface(skiaBitmap, 0, 0, SkPaint);
@@ -54,7 +55,8 @@ public override void DrawRectangle(EffectLayer brush)
public override void DrawRectangle(EffectLayer brush, Rectangle dimension)
{
- var auroraSkiaBitmap = (AuroraVulkanSkiaBitmap)GetSkiaBitmap(brush.GetBitmap());
+ var bitmapEffectLayer = (BitmapEffectLayer)brush;
+ var auroraSkiaBitmap = (AuroraVulkanSkiaBitmap)GetSkiaBitmap(bitmapEffectLayer.GetBitmap());
SkPaint.Color = new SKColor(255, 255, 255, (byte)(auroraSkiaBitmap.Opacity * 255));
var skiaBitmap = auroraSkiaBitmap._surface;
var rectangle = SkiaRectangle(dimension);
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmap.cs b/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmap.cs
index a278a1814..4d8f08e59 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmap.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmap.cs
@@ -31,7 +31,7 @@ protected virtual void Invalidate()
{
}
- public float Opacity { get; set; } = 1.0f;
+ public double Opacity { get; set; } = 1.0;
public abstract IBitmapReader CreateReader();
diff --git a/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmapReader.cs b/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmapReader.cs
index 4a1f0b66b..3253c9e5a 100644
--- a/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmapReader.cs
+++ b/Project-Aurora/Project-Aurora/Bitmaps/Skia/SkiaBitmapReader.cs
@@ -1,4 +1,5 @@
using System.Drawing;
+using System.Runtime.CompilerServices;
using SkiaSharp;
namespace AuroraRgb.Bitmaps.Skia;
@@ -7,18 +8,23 @@ public sealed class SkiaBitmapReader(SKBitmap bitmap) : IBitmapReader
{
private readonly SKColor[] _pixels = bitmap.Pixels;
- public Color GetRegionColor(Rectangle rectangle)
+ private Color _transparentColor = Color.Transparent;
+ private Color _currentColor = Color.Black;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref readonly Color GetRegionColor(Rectangle rectangle)
{
var skiaRectangle = SkiaUtils.SkiaRectangle(rectangle);
- return GetAverageColorInRectangle(skiaRectangle);
+ return ref GetAverageColorInRectangle(skiaRectangle);
}
- private Color GetAverageColorInRectangle(SKRectI rect)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private ref Color GetAverageColorInRectangle(SKRectI rect)
{
// Ensure the rectangle is within the bounds of the bitmap
var bitmapWidth = bitmap.Width;
rect = SKRectI.Intersect(rect, new SKRectI(0, 0, bitmapWidth, bitmap.Height));
- if (rect.IsEmpty) return Color.Transparent;
+ if (rect.IsEmpty) return ref _transparentColor;
// Now calculate the average color from the subset
long red = 0, green = 0, blue = 0, alpha = 0;
@@ -44,7 +50,8 @@ private Color GetAverageColorInRectangle(SKRectI rect)
var avgAlpha = (byte)(alpha / area);
// Return the average color
- return Color.FromArgb(avgAlpha, avgRed, avgGreen, avgBlue);
+ _currentColor = Color.FromArgb(avgAlpha, avgRed, avgGreen, avgBlue);
+ return ref _currentColor;
}
public void Dispose()
diff --git a/Project-Aurora/Project-Aurora/Controls/Control_AnimationMixPresenter.xaml.cs b/Project-Aurora/Project-Aurora/Controls/Control_AnimationMixPresenter.xaml.cs
index 7adcfae67..9c4dc2177 100644
--- a/Project-Aurora/Project-Aurora/Controls/Control_AnimationMixPresenter.xaml.cs
+++ b/Project-Aurora/Project-Aurora/Controls/Control_AnimationMixPresenter.xaml.cs
@@ -261,7 +261,6 @@ private async Task StartUpdate()
private async void UserControl_Unloaded(object? sender, RoutedEventArgs e)
{
await StopUpdate();
- Global.effengine.ForceImageRender(null);
}
private async Task StopUpdate()
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/BitmapRectangle.cs b/Project-Aurora/Project-Aurora/EffectsEngine/BitmapRectangle.cs
index 782e896c5..19e259224 100644
--- a/Project-Aurora/Project-Aurora/EffectsEngine/BitmapRectangle.cs
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/BitmapRectangle.cs
@@ -9,7 +9,7 @@ public sealed class BitmapRectangle : IEqualityComparer, IEquat
public static readonly BitmapRectangle EmptyRectangle = new();
private readonly Rectangle _rectangle;
- public Rectangle Rectangle => _rectangle;
+ public ref readonly Rectangle Rectangle => ref _rectangle;
public bool IsEmpty => _rectangle.IsEmpty;
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/EffectCanvas.cs b/Project-Aurora/Project-Aurora/EffectsEngine/EffectCanvas.cs
index 0bca1feca..1b3732174 100644
--- a/Project-Aurora/Project-Aurora/EffectsEngine/EffectCanvas.cs
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/EffectCanvas.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
+using System.Linq;
using AuroraRgb.Settings;
using Common.Devices;
@@ -23,19 +24,6 @@ public sealed class EffectCanvas : IEqualityComparer, IEquatable bitmapMap)
- {
- Width = width;
- Height = height;
- BiggestSize = Math.Max(width, height);
- BitmapMap = bitmapMap.ToFrozenDictionary();
- CanvasGridProperties = new(0, 0, width, height);
-
- EntireSequence = new(WholeFreeForm);
- }
-
public int Width { get; }
public int Height { get; }
public int BiggestSize { get; }
@@ -45,10 +33,15 @@ public EffectCanvas(int width,
public float GridBaselineY => CanvasGridProperties.GridBaselineY;
public FrozenDictionary BitmapMap { get; }
+ public DeviceKeys[] Keys { get; }
public float WidthCenter { get; init; }
public float HeightCenter { get; init; }
+ private readonly BitmapRectangle[] _keyRectangles = Enumerable.Range(0, Effects.MaxDeviceId + 1)
+ .Select(_ => BitmapRectangle.EmptyRectangle)
+ .ToArray();
+
public CanvasGridProperties CanvasGridProperties
{
get => _canvasGridProperties;
@@ -68,9 +61,27 @@ public CanvasGridProperties CanvasGridProperties
public FreeFormObject WholeFreeForm => new(-CanvasGridProperties.GridBaselineX, -CanvasGridProperties.GridBaselineY, CanvasGridProperties.GridWidth, CanvasGridProperties.GridHeight);
public KeySequence EntireSequence { get; private set; }
- public BitmapRectangle GetRectangle(DeviceKeys key)
+ public EffectCanvas(int width,
+ int height,
+ Dictionary bitmapMap)
+ {
+ Width = width;
+ Height = height;
+ BiggestSize = Math.Max(width, height);
+ BitmapMap = bitmapMap.ToFrozenDictionary();
+ foreach (var (key, value) in bitmapMap)
+ {
+ _keyRectangles[(int)key] = value;
+ }
+ Keys = bitmapMap.Keys.ToArray();
+ CanvasGridProperties = new(0, 0, width, height);
+
+ EntireSequence = new(WholeFreeForm);
+ }
+
+ public ref readonly BitmapRectangle GetRectangle(DeviceKeys key)
{
- return BitmapMap.TryGetValue(key, out var rect) ? rect : BitmapRectangle.EmptyRectangle;
+ return ref _keyRectangles[(int)key];
}
public bool Equals(EffectCanvas? other)
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/EffectLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/EffectLayer.cs
index e929b7900..6a494ebb6 100755
--- a/Project-Aurora/Project-Aurora/EffectsEngine/EffectLayer.cs
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/EffectLayer.cs
@@ -16,18 +16,12 @@
namespace AuroraRgb.EffectsEngine;
-public enum LayerReadability
-{
- None = 0,
- Readable = 1,
-}
-
///
/// A class representing a bitmap layer for effects
///
-public class EffectLayer : IDisposable
+public sealed class BitmapEffectLayer : EffectLayer
{
- public static EffectLayer EmptyLayer { get; } = new("EmptyLayer", true);
+ private static readonly Color TransparentColor = Color.Transparent;
// Yes, this is no thread-safe but Aurora isn't supposed to take up resources
// This is done to prevent memory leaks from creating new brushes
@@ -37,44 +31,56 @@ public class EffectLayer : IDisposable
};
private readonly string _name;
+ //TODO set readability based on GPU or not
private readonly bool _readable = true;
- protected IAuroraBitmap _colormap;
+ private IAuroraBitmap _colormap;
private bool _invalidated = true;
internal Rectangle Dimension;
- [Obsolete("This creates too much garbage memory")]
- public EffectLayer(string name) : this(name, Color.Transparent)
- {
- }
+ private IBitmapReader? _bitmapReader;
+
+ public DeviceKeys[] ActiveKeys => Effects.Canvas.Keys;
[Obsolete("This creates too much garbage memory")]
- public EffectLayer(string name, Color color)
+ public BitmapEffectLayer(string name)
{
_name = name;
_colormap = new RuntimeChangingBitmap(Effects.Canvas.Width, Effects.Canvas.Height, true);
Dimension = new Rectangle(0, 0, Effects.Canvas.Width, Effects.Canvas.Height);
+ }
- FillOver(color);
+ public BitmapEffectLayer(string name, bool persistent) : this(name)
+ {
+ if (!persistent)
+ return;
+ WeakEventManager.AddHandler(null, nameof(Effects.CanvasChanged), InvalidateColorMap);
}
- protected EffectLayer(string name, Color color, LayerReadability readable)
+ ///
+ /// Retrieves a color of the specified DeviceKeys key from the bitmap
+ ///
+ public Color Get(DeviceKeys key)
{
- _readable = readable == LayerReadability.Readable;
- _name = name;
- _colormap = new RuntimeChangingBitmap(Effects.Canvas.Width, Effects.Canvas.Height, true);
- Dimension = new Rectangle(0, 0, Effects.Canvas.Width, Effects.Canvas.Height);
+ var keyRectangle = Effects.Canvas.GetRectangle(key);
- FillOver(color);
- WeakEventManager.AddHandler(null, nameof(Effects.CanvasChanged), InvalidateColorMap);
+ if (keyRectangle.IsEmpty)
+ return TransparentColor;
+ ref readonly var color = ref GetColor(in keyRectangle.Rectangle);
+ return color;
}
- public EffectLayer(string name, bool persistent) : this(name)
+ private ref readonly Color GetColor(ref readonly Rectangle rectangle)
{
- if (!persistent)
- return;
- WeakEventManager.AddHandler(null, nameof(Effects.CanvasChanged), InvalidateColorMap);
+ _bitmapReader ??= _colormap.CreateReader();
+ return ref _bitmapReader.GetRegionColor(rectangle);
+ }
+
+ public void Close()
+ {
+ _bitmapReader?.Dispose();
+ _bitmapReader = null;
}
///
@@ -206,7 +212,7 @@ private void DrawRainbowGradient(float angle, float shift)
rainbowBrush.Dispose();
}
- public virtual void Dispose()
+ public void Dispose()
{
_excludeSequence = new KeySequence();
_keySequence = new KeySequence();
@@ -254,30 +260,27 @@ private LinearGradientBrush CreateRainbowBrush()
return brush;
}
- ///
- /// Fills the entire bitmap of the EffectLayer with a specified brush.
- ///
- /// Brush to be used during bitmap fill
- public void Fill(Brush brush)
+ public void Fill(ref readonly Color color)
{
_colormap.Reset();
- _colormap.ReplaceRectangle(brush, Dimension);
+ _solidBrush.Color = (SimpleColor)color;
+ _colormap.ReplaceRectangle(_solidBrush, Dimension);
Invalidate();
}
- public void Fill(IAuroraBrush brush)
+ ///
+ /// Fills the entire bitmap of the EffectLayer with a specified brush.
+ ///
+ /// Brush to be used during bitmap fill
+ public void Fill(Brush brush)
{
_colormap.Reset();
_colormap.ReplaceRectangle(brush, Dimension);
Invalidate();
}
- ///
- /// Paints over the entire bitmap of the EffectLayer with a specified color.
- ///
- /// Color to be used during bitmap fill
- /// Itself
- public void FillOver(Color color)
+ ///
+ public void FillOver(ref readonly Color color)
{
_colormap.Reset();
_solidBrush.Color = (SimpleColor)color;
@@ -298,13 +301,6 @@ public void FillOver(Brush brush)
Invalidate();
}
- public void FillOver(IAuroraBrush brush)
- {
- _colormap.Reset();
- _colormap.DrawRectangle(brush, Dimension);
- Invalidate();
- }
-
public void Clear()
{
_colormap.Fill(ClearingBrush);
@@ -314,35 +310,22 @@ public void Clear()
private FreeFormObject _lastFreeform = new();
private bool _ksChanged = true;
- ///
- /// Sets a specific DeviceKeys on the bitmap with a specified color.
- ///
- /// DeviceKey to be set
- /// Color to be used
- /// Itself
- public void Set(DeviceKeys key, Color color)
+
+ ///
+ public void Set(DeviceKeys key, ref readonly Color color)
{
- SetOneKey(key, color);
+ SetOneKey(key, in color);
}
- ///
- /// Sets a specific DeviceKeys on the bitmap with a specified color.
- ///
- /// Array of DeviceKeys to be set
- /// Color to be used
- public void Set(DeviceKeys[] keys, Color color)
+ ///
+ public void Set(DeviceKeys[] keys, ref readonly Color color)
{
foreach (var key in keys)
- SetOneKey(key, color);
+ SetOneKey(key, in color);
}
- ///
- /// Sets a specific KeySequence on the bitmap with a specified color.
- ///
- /// KeySequence to specify what regions of the bitmap need to be changed
- /// Color to be used
- /// Itself
- public void Set(KeySequence sequence, Color color)
+ ///
+ public void Set(KeySequence sequence, ref readonly Color color)
{
_solidBrush.Color = (SimpleColor)color;
Set(sequence, _solidBrush);
@@ -591,7 +574,7 @@ public void DrawTransformed(KeySequence sequence, Action render)
///
/// DeviceKey to be set
/// Color to be used
- private void SetOneKey(DeviceKeys key, Color color)
+ private void SetOneKey(DeviceKeys key, ref readonly Color color)
{
_solidBrush.Color = (SimpleColor)color;
SetOneKey(key, _solidBrush);
@@ -607,7 +590,7 @@ private void SetOneKey(DeviceKeys key, Color color)
///
/// DeviceKey to be set
/// Brush to be used
- protected virtual void SetOneKey(DeviceKeys key, Brush brush)
+ private void SetOneKey(DeviceKeys key, Brush brush)
{
var keyRectangle = Effects.Canvas.GetRectangle(key);
_invalidated = true;
@@ -657,52 +640,45 @@ public IAuroraBitmap GetBitmap()
return _colormap;
}
- public void Add(EffectLayer other)
- {
- _ = this + other;
- }
-
- ///
- /// + Operator, sums two EffectLayer together.
- ///
- /// Left Hand Side EffectLayer
- /// Right Hand Side EffectLayer
- /// Left hand side EffectLayer, which is a combination of two passed EffectLayers
- public static EffectLayer operator +(EffectLayer lhs, EffectLayer rhs)
+ ///
+ public EffectLayer Add(EffectLayer other)
{
- if (lhs == EmptyLayer)
- {
- return rhs;
- }
-
- if (rhs == EmptyLayer)
+ if (ReferenceEquals(other, EmptyLayer.Instance))
{
- return lhs;
+ return this;
}
- var g = lhs.GetGraphics();
+ var g = GetGraphics();
+ switch (other)
{
- g.DrawRectangle(rhs);
+ case BitmapEffectLayer bitmapEffectLayer:
+ g.DrawRectangle(bitmapEffectLayer);
+ break;
+ case NoRenderLayer noRenderLayer:
+ var activeKeys = noRenderLayer.ActiveKeys;
+ foreach (var key in activeKeys)
+ {
+ _solidBrush.Color = (SimpleColor)noRenderLayer.Get(key);
+ var bitmapRectangle = Effects.Canvas.GetRectangle(key).Rectangle;
+ g.DrawRectangle(_solidBrush, bitmapRectangle);
+ }
+ break;
+ case EmptyLayer:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(other), other, null);
}
- lhs.Invalidate();
- return lhs;
+ Invalidate();
+ return this;
}
- ///
- /// * Operator, Multiplies an EffectLayer by a double, adjusting opacity and color of the layer bitmap.
- ///
- /// EffectLayer to be adjusted
- /// Double value that each bit in the bitmap will be multiplied by
- /// The passed instance of EffectLayer with adjustments
- public static EffectLayer operator *(EffectLayer layer, double value)
+ ///
+ public void SetOpacity(double value)
{
- if (!MathUtils.NearlyEqual(layer._colormap.Opacity,(float)value, 0.0001f))
- {
- layer._colormap.Opacity = (float) value;
- layer.Invalidate();
- }
- return layer;
+ if (MathUtils.NearlyEqual(_colormap.Opacity, (float)value, 0.0001f)) return;
+ _colormap.Opacity = (float) value;
+ Invalidate();
}
private KeySequenceType _previousSequenceType;
@@ -714,7 +690,7 @@ public void Add(EffectLayer other)
/// The foreground color, used as a "Progress bar color"
/// The current progress value
/// The maxiumum progress value
- public void PercentEffect(Color foregroundColor, Color backgroundColor, KeySequence sequence, double value,
+ public void PercentEffect(Color foregroundColor, ref readonly Color backgroundColor, KeySequence sequence, double value,
double total = 1.0D, PercentEffectType percentEffectType = PercentEffectType.Progressive,
double flashPast = 0.0, bool flashReversed = false, bool blinkBackground = false)
{
@@ -757,7 +733,7 @@ public void PercentEffect(ColorSpectrum spectrum, KeySequence sequence, double v
/// The foreground color, used as a "Progress bar color"
/// The current progress value
/// The maxiumum progress value
- private void PercentEffect(Color foregroundColor, Color backgroundColor, IReadOnlyList keys, double value,
+ public void PercentEffect(Color foregroundColor, Color backgroundColor, IReadOnlyList keys, double value,
double total, PercentEffectType percentEffectType = PercentEffectType.Progressive, double flashPast = 0.0,
bool flashReversed = false, bool blinkBackground = false)
{
@@ -976,8 +952,9 @@ private void PercentEffect(Color foregroundColor, Color backgroundColor, FreeFor
Invalidate();
}
- public virtual void Invalidate()
+ public void Invalidate()
{
+ _bitmapReader = null;
_invalidated = true;
}
private void InvalidateColorMap(object? sender, EventArgs args)
@@ -1065,10 +1042,7 @@ private void PercentEffect(ColorSpectrum spectrum, FreeFormObject freeform, doub
private KeySequence _excludeSequence = new();
- ///
- /// Excludes provided sequence from the layer (Applies a mask)
- ///
- /// The mask to be applied
+ ///
public void Exclude(KeySequence sequence)
{
if (_excludeSequence.Equals(sequence))
@@ -1085,9 +1059,7 @@ public void Exclude(KeySequence sequence)
Invalidate();
}
- ///
- /// Inlcudes provided sequence from the layer (Applies a mask)
- ///
+ ///
public void OnlyInclude(KeySequence sequence)
{
_colormap.OnlyInclude(sequence);
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/Effects.cs b/Project-Aurora/Project-Aurora/EffectsEngine/Effects.cs
index 37784acee..ca229b972 100755
--- a/Project-Aurora/Project-Aurora/EffectsEngine/Effects.cs
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/Effects.cs
@@ -9,6 +9,7 @@
using AuroraRgb.Utils;
using Common;
using Common.Devices;
+using Common.Utils;
namespace AuroraRgb.EffectsEngine;
@@ -104,9 +105,27 @@ public class Effects(Task deviceManager)
DeviceKeys.PERIPHERAL_LIGHT20
];
- public event NewLayerRendered? NewLayerRender = delegate { };
-
- private Bitmap? _forcedFrame;
+ private event NewLayerRendered? _newLayerRender = delegate { };
+
+ public event NewLayerRendered? NewLayerRender
+ {
+ add
+ {
+ if (_newLayerRender?.GetInvocationList().Length < 2)
+ {
+ Background.ChangeToBitmapEffectLayer();
+ }
+ _newLayerRender += value; // Update stored event listeners
+ }
+ remove
+ {
+ _newLayerRender -= value; // Update stored event listeners
+ if (_newLayerRender?.GetInvocationList().Length < 2)
+ {
+ Background.ChangeToNoRenderLayer();
+ }
+ }
+ }
public static event EventHandler? CanvasChanged;
private static readonly object CanvasChangedLock = new();
@@ -136,16 +155,8 @@ public static EffectCanvas Canvas
private readonly Dictionary _keyColors = new(MaxDeviceId, EnumHashGetter.Instance as IEqualityComparer);
- private ReadableEffectLayer Background { get; } = new("Global Background", Color.Black);
-
- private readonly SingleColorBrush _keyboardDarknessBrush = new();
- private readonly SingleColorBrush _blackBrush = new(SimpleColor.Black);
-
- public void ForceImageRender(Bitmap? forcedFrame)
- {
- _forcedFrame?.Dispose();
- _forcedFrame = forcedFrame?.Clone() as Bitmap;
- }
+ private RuntimeChangingLayer Background { get; } = new("Background Layer");
+ private readonly Color _backgroundColor = Color.Black;
public void PushFrame(EffectFrame frame)
{
@@ -159,7 +170,7 @@ public void PushFrame(EffectFrame frame)
private void PushFrameLocked(EffectFrame frame)
{
- Background.Fill(_blackBrush);
+ Background.Fill(in _backgroundColor);
var overLayersArray = frame.GetOverlayLayers();
var layersArray = frame.GetLayers();
@@ -169,17 +180,11 @@ private void PushFrameLocked(EffectFrame frame)
foreach (var layer in overLayersArray)
Background.Add(layer);
- var keyboardDarkness = 1.0f - Global.Configuration.KeyboardBrightness * Global.Configuration.GlobalBrightness;
- _keyboardDarknessBrush.Color = SimpleColor.FromRgba( 0, 0, 0, (byte) (255.0f * keyboardDarkness));
- Background.FillOver(_keyboardDarknessBrush);
+ var keyboardDarknessA = 1.0f - Global.Configuration.KeyboardBrightness * Global.Configuration.GlobalBrightness;
+ var keyboardDarkness = CommonColorUtils.FastColor(0, 0, 0, (byte) (255.0f * keyboardDarknessA));
+ Background.FillOver(in keyboardDarkness);
var renderCanvas = Canvas; // save locally in case it changes between ref calls
- if (_forcedFrame != null)
- {
- var g = Background.GetGraphics();
- g.Fill(Brushes.Black);
- g.DrawImage(_forcedFrame, 0, 0, renderCanvas.Width, renderCanvas.Height);
- }
foreach (var key in renderCanvas.BitmapMap.Keys)
_keyColors[key] = (SimpleColor)Background.Get(key);
@@ -196,7 +201,7 @@ private void PushFrameLocked(EffectFrame frame)
deviceManager.Result.UpdateDevices(_keyColors);
- NewLayerRender?.Invoke(Background.GetBitmap());
+ _newLayerRender?.Invoke(Background.GetBitmap());
frame.Dispose();
}
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/EmptyLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/EmptyLayer.cs
new file mode 100644
index 000000000..8fb805058
--- /dev/null
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/EmptyLayer.cs
@@ -0,0 +1,77 @@
+using System.Collections.Generic;
+using System.Drawing;
+using AuroraRgb.Settings;
+using Common.Devices;
+
+namespace AuroraRgb.EffectsEngine;
+
+public sealed class EmptyLayer : EffectLayer
+{
+ public static readonly EmptyLayer Instance = new();
+ private static readonly Color TransparentColor = Color.Transparent;
+
+ private EmptyLayer()
+ {
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public DeviceKeys[] ActiveKeys { get; } = [];
+
+ public void Fill(ref readonly Color color)
+ {
+ }
+
+ public void FillOver(ref readonly Color color)
+ {
+ }
+
+ public void Clear()
+ {
+ }
+
+ public void Set(DeviceKeys key, ref readonly Color color)
+ {
+ }
+
+ public void Set(DeviceKeys[] keys, ref readonly Color color)
+ {
+ }
+
+ public void Set(KeySequence sequence, ref readonly Color color)
+ {
+ }
+
+ public void PercentEffect(Color foregroundColor, Color backgroundColor, IReadOnlyList keys, double value, double total,
+ PercentEffectType percentEffectType = PercentEffectType.Progressive, double flashPast = 0, bool flashReversed = false, bool blinkBackground = false)
+ {
+ }
+
+ public EffectLayer Add(EffectLayer other)
+ {
+ return other;
+ }
+
+ public void Exclude(KeySequence sequence)
+ {
+ }
+
+ public void OnlyInclude(KeySequence sequence)
+ {
+ }
+
+ public void SetOpacity(double layerOpacity)
+ {
+ }
+
+ public Color Get(DeviceKeys key)
+ {
+ return TransparentColor;
+ }
+
+ public void Close()
+ {
+ }
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/IEffectLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/IEffectLayer.cs
new file mode 100644
index 000000000..c6316d412
--- /dev/null
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/IEffectLayer.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using AuroraRgb.Settings;
+using Common.Devices;
+
+namespace AuroraRgb.EffectsEngine;
+
+public interface EffectLayer : IDisposable
+{
+ DeviceKeys[] ActiveKeys { get; }
+
+ ///
+ /// Fills entire EffectLayer with a specified color.
+ ///
+ /// Color to be used during bitmap fill
+ void Fill(ref readonly Color color);
+
+ ///
+ /// Paints over the entire bitmap of the EffectLayer with a specified color.
+ ///
+ /// Color to be used during bitmap fill
+ /// Itself
+ void FillOver(ref readonly Color color);
+
+ void Clear();
+
+ ///
+ /// Sets a specific DeviceKeys on the bitmap with a specified color.
+ ///
+ /// DeviceKey to be set
+ /// Color to be used
+ /// Itself
+ void Set(DeviceKeys key, ref readonly Color color);
+
+ ///
+ /// Sets a specific DeviceKeys on the bitmap with a specified color.
+ ///
+ /// Array of DeviceKeys to be set
+ /// Color to be used
+ void Set(DeviceKeys[] keys, ref readonly Color color);
+
+ ///
+ /// Sets a specific KeySequence on the bitmap with a specified color.
+ ///
+ /// KeySequence to specify what regions of the bitmap need to be changed
+ /// Color to be used
+ /// Itself
+ void Set(KeySequence sequence, ref readonly Color color);
+
+ void PercentEffect(Color foregroundColor, Color backgroundColor, IReadOnlyList keys, double value,
+ double total, PercentEffectType percentEffectType = PercentEffectType.Progressive, double flashPast = 0.0,
+ bool flashReversed = false, bool blinkBackground = false);
+
+ ///
+ /// + Operator, sums two EffectLayer together.
+ ///
+ /// Left Hand Side EffectLayer
+ /// Right Hand Side EffectLayer
+ /// Left hand side EffectLayer, which is a combination of two passed EffectLayers
+ EffectLayer Add(EffectLayer other);
+
+ ///
+ /// Excludes provided sequence from the layer (Applies a mask)
+ ///
+ /// The mask to be applied
+ void Exclude(KeySequence sequence);
+
+ ///
+ /// Inlcudes provided sequence from the layer (Applies a mask)
+ ///
+ void OnlyInclude(KeySequence sequence);
+
+ void SetOpacity(double layerOpacity);
+
+ ///
+ /// Retrieves a color of the specified DeviceKeys key from the bitmap
+ ///
+ Color Get(DeviceKeys key);
+
+ void Close();
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/NoRenderLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/NoRenderLayer.cs
new file mode 100644
index 000000000..147c08173
--- /dev/null
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/NoRenderLayer.cs
@@ -0,0 +1,273 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using AuroraRgb.Settings;
+using AuroraRgb.Utils;
+using Common.Devices;
+using Common.Utils;
+
+namespace AuroraRgb.EffectsEngine;
+
+public sealed class NoRenderLayer : EffectLayer
+{
+ private readonly Color[] _keyColors = new Color[Effects.MaxDeviceId + 1];
+ private readonly Color _transparent = Color.Transparent;
+ private double _opacity = 1;
+ private bool _isOpaque = true;
+
+ private Color _lastColor = Color.Transparent;
+ private double _percentProgress = -1;
+ private Color _colorCache;
+
+ // TODO optimize a lot by reducing the result of this
+ public DeviceKeys[] ActiveKeys => Effects.Canvas.Keys;
+ private DeviceKeys[] AllKeys => Effects.Canvas.Keys;
+
+ public void Fill(ref readonly Color color)
+ {
+ // set all _keyColors to Transparent
+ foreach (var key in AllKeys)
+ Set(key, in color);
+ }
+
+ public void FillOver(ref readonly Color color)
+ {
+ foreach (var deviceKey in AllKeys)
+ {
+ SetOver(deviceKey, in color);
+ }
+ }
+
+ public void Clear()
+ {
+ Fill(Color.Transparent);
+ }
+
+ public void Set(DeviceKeys key, ref readonly Color color)
+ {
+ if (key == DeviceKeys.NONE)
+ {
+ return;
+ }
+
+ _keyColors[(int)key] = color;
+ }
+
+ public void Set(DeviceKeys[] keys, ref readonly Color color)
+ {
+ foreach (var deviceKeys in keys)
+ {
+ Set(deviceKeys, in color);
+ }
+ }
+
+ public void Set(IEnumerable keys, ref readonly Color color)
+ {
+ foreach (var deviceKeys in keys)
+ {
+ Set(deviceKeys, in color);
+ }
+ }
+
+ public void Set(KeySequence sequence, ref readonly Color color)
+ {
+ var keys = GetKeys(sequence);
+ Set(keys, in color);
+ }
+
+ private IEnumerable GetKeys(KeySequence sequence)
+ {
+ switch (sequence.Type)
+ {
+ case KeySequenceType.Sequence:
+ {
+ return sequence.Keys;
+ }
+ case KeySequenceType.FreeForm:
+ {
+ return GetKeys(sequence.Freeform);
+ }
+ }
+
+ return [];
+ }
+
+ private IEnumerable GetKeys(FreeFormObject sequenceFreeform)
+ {
+ //TODO implement getting keys inside the rectangle
+ return [];
+ }
+
+ public EffectLayer Add(EffectLayer other)
+ {
+ if (other == EmptyLayer.Instance)
+ {
+ return this;
+ }
+
+ // magic iteration from https://blog.ndepend.com/c-array-and-list-fastest-loop/
+ Span span = other.ActiveKeys;
+ ref var start = ref MemoryMarshal.GetReference(span);
+ ref var end = ref Unsafe.Add(ref start, span.Length);
+
+ while (Unsafe.IsAddressLessThan(ref start, ref end)) {
+ var foregroundColor = other.Get(start);
+ SetOver(start, in foregroundColor);
+ start = ref Unsafe.Add(ref start, 1);
+ }
+
+ return this;
+ }
+
+ private void SetOver(DeviceKeys key, ref readonly Color foregroundColor)
+ {
+ switch (foregroundColor.A)
+ {
+ // If the drawn color is fully opaque, draw it directly
+ case 255:
+ {
+ Set(key, in foregroundColor);
+ return;
+ }
+ // If the drawn color is fully transparent, do nothing
+ case 0:
+ {
+ return;
+ }
+ }
+
+ var backgroundColor = Get(key);
+ ref var newColor = ref CommonColorUtils.AddColors(in backgroundColor, in foregroundColor, ref _colorCache);
+ Set(key, in newColor);
+ }
+
+ ///
+ /// Draws a percent effect on the layer bitmap using an array of DeviceKeys keys and solid colors.
+ ///
+ /// The foreground color, used as a "Progress bar color"
+ /// The current progress value
+ /// The maxiumum progress value
+ public void PercentEffect(Color foregroundColor, Color backgroundColor, IReadOnlyList keys, double value,
+ double total, PercentEffectType percentEffectType = PercentEffectType.Progressive, double flashPast = 0.0,
+ bool flashReversed = false, bool blinkBackground = false)
+ {
+ var progressTotal = value / total;
+ if (progressTotal < 0.0)
+ progressTotal = 0.0;
+ else if (progressTotal > 1.0)
+ progressTotal = 1.0;
+
+ var progress = progressTotal * keys.Count;
+
+ if (flashPast > 0.0 && ((flashReversed && progressTotal >= flashPast) || (!flashReversed && progressTotal <= flashPast)))
+ {
+ var percent = Math.Sin(Time.GetMillisecondsSinceEpoch() % 1000.0D / 1000.0D * Math.PI);
+ if (blinkBackground)
+ backgroundColor = ColorUtils.BlendColors(backgroundColor, Color.Empty, percent);
+ else
+ foregroundColor = ColorUtils.BlendColors(backgroundColor, foregroundColor, percent);
+ }
+
+ if (percentEffectType is PercentEffectType.Highest_Key or PercentEffectType.Highest_Key_Blend && keys.Count > 0)
+ {
+ var activeKey = (int)Math.Ceiling(Math.Clamp(value, 0, 1) / (total / keys.Count)) - 1;
+ var col = percentEffectType == PercentEffectType.Highest_Key ?
+ foregroundColor : ColorUtils.BlendColors(backgroundColor, foregroundColor, progressTotal);
+ for (var i = 0; i < keys.Count; i++)
+ {
+ if (i != activeKey)
+ {
+ Set(keys[i], Color.Transparent);
+ }
+ }
+ Set(keys[activeKey], in col);
+
+ }
+ else
+ {
+ for (var i = 0; i < keys.Count; i++)
+ {
+ var currentKey = keys[i];
+
+ switch (percentEffectType)
+ {
+ case PercentEffectType.AllAtOnce:
+ Set(currentKey, ColorUtils.BlendColors(backgroundColor, foregroundColor, progressTotal));
+ break;
+ case PercentEffectType.Progressive_Gradual:
+ if (i == (int)progress)
+ {
+ var percent = progress - i;
+ Set(currentKey, ColorUtils.BlendColors(backgroundColor, foregroundColor, percent));
+ }
+ else if (i < (int)progress)
+ Set(currentKey, foregroundColor);
+ else
+ Set(currentKey, backgroundColor);
+ break;
+ default:
+ Set(currentKey, i < (int) progress ? foregroundColor : backgroundColor);
+ break;
+ }
+ }
+ }
+ }
+
+ public void Exclude(KeySequence sequence)
+ {
+ Exclude(GetKeys(sequence));
+ }
+
+ private void Exclude(IEnumerable exclusion)
+ {
+ foreach (var deviceKey in exclusion)
+ {
+ Set(deviceKey, Color.Transparent);
+ }
+ }
+
+ public void OnlyInclude(KeySequence sequence)
+ {
+ var exclusion = ActiveKeys.Except(GetKeys(sequence));
+ Exclude(exclusion);
+ }
+
+ public void SetOpacity(double layerOpacity)
+ {
+ _opacity = layerOpacity;
+ _isOpaque = _opacity > 0.999;
+ }
+
+ public Color Get(DeviceKeys key)
+ {
+ if (_isOpaque)
+ {
+ return GetCurrentColor(key);
+ }
+
+ var color = GetCurrentColor(key);
+ var a = (byte)(color.A * _opacity);
+ return CommonColorUtils.FastColor(color.R, color.G, color.B, a);
+ }
+
+ public void Close()
+ {
+ }
+
+ public void Dispose()
+ {
+ }
+
+ private Color GetCurrentColor(DeviceKeys deviceKey)
+ {
+ if (deviceKey == DeviceKeys.NONE)
+ {
+ return _transparent;
+ }
+
+ return _keyColors[(int)deviceKey];
+ }
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/ReadableEffectLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/ReadableEffectLayer.cs
deleted file mode 100644
index bcf244bd7..000000000
--- a/Project-Aurora/Project-Aurora/EffectsEngine/ReadableEffectLayer.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System.Drawing;
-using AuroraRgb.Bitmaps;
-using Common.Devices;
-
-namespace AuroraRgb.EffectsEngine;
-
-public class ReadableEffectLayer(string name, Color color) : EffectLayer(name, color, LayerReadability.Readable)
-{
- private IBitmapReader? _bitmapReader;
-
- ///
- /// Retrieves a color of the specified DeviceKeys key from the bitmap
- ///
- public Color Get(DeviceKeys key)
- {
- var keyRectangle = Effects.Canvas.GetRectangle(key);
-
- var keyColor = keyRectangle.IsEmpty switch
- {
- true => Color.Black,
- false => GetColor(keyRectangle.Rectangle)
- };
- return keyColor;
- }
-
- private Color GetColor(Rectangle rectangle)
- {
- _bitmapReader ??= _colormap.CreateReader();
- return _bitmapReader.GetRegionColor(rectangle);
- }
-
- public void Close()
- {
- _bitmapReader?.Dispose();
- _bitmapReader = null;
- }
-}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/EffectsEngine/RuntimeChangingLayer.cs b/Project-Aurora/Project-Aurora/EffectsEngine/RuntimeChangingLayer.cs
new file mode 100644
index 000000000..a6729d80c
--- /dev/null
+++ b/Project-Aurora/Project-Aurora/EffectsEngine/RuntimeChangingLayer.cs
@@ -0,0 +1,34 @@
+using AuroraRgb.Bitmaps;
+using AuroraSourceGenerator;
+
+namespace AuroraRgb.EffectsEngine;
+
+[DelegateTo(nameof(_effectLayer))]
+public sealed partial class RuntimeChangingLayer : EffectLayer
+{
+ private readonly NoRenderLayer _noRenderLayer = new();
+ private readonly BitmapEffectLayer _bitmapEffectLayer;
+
+ private EffectLayer _effectLayer;
+
+ public RuntimeChangingLayer(string name)
+ {
+ _bitmapEffectLayer = new BitmapEffectLayer(name, true);
+ _effectLayer = _noRenderLayer;
+ }
+
+ public void ChangeToNoRenderLayer()
+ {
+ _effectLayer = _noRenderLayer;
+ }
+
+ public void ChangeToBitmapEffectLayer()
+ {
+ _effectLayer = _bitmapEffectLayer;
+ }
+
+ public IAuroraBitmap GetBitmap()
+ {
+ return _bitmapEffectLayer.GetBitmap();
+ }
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBackgroundLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBackgroundLayerHandler.cs
index 4cee54934..d190d5fb4 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBackgroundLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBackgroundLayerHandler.cs
@@ -84,7 +84,8 @@ public class CSGOBackgroundLayerHandler() : LayerHandler -1 and < 100
|| (csgostate.Round.WinTeam == RoundWinTeam.Undefined && csgostate.Previously?.Round.WinTeam != RoundWinTeam.Undefined);
@@ -125,9 +126,9 @@ public override EffectLayer Render(IGameState gameState)
}
}
- if (_solidBrush.Color == bgColor) return EffectLayer;
- _solidBrush.Color = bgColor;
- EffectLayer.Fill(_solidBrush);
+ if (_currentColor == bgColor) return EffectLayer;
+ _currentColor = bgColor;
+ EffectLayer.Fill(bgColor);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBombLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBombLayerHandler.cs
index 63015b4f4..2b506a4b6 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBombLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBombLayerHandler.cs
@@ -75,14 +75,14 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameStateCsgo csgostate) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateCsgo csgostate) return EmptyLayer.Instance;
if (csgostate.Round.Bomb != BombState.Planted)
{
- if (!_bombTimer.IsRunning) return EffectLayer.EmptyLayer;
+ if (!_bombTimer.IsRunning) return EmptyLayer.Instance;
Reset();
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
if (!_bombTimer.IsRunning)
{
@@ -129,12 +129,12 @@ public override EffectLayer Render(IGameState gameState)
if (flashAmount < 0.01)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
var bombColor = ColorUtils.MultiplyColorByScalar(isCritical ? Properties.PrimedColor : Properties.FlashColor, Math.Min(flashAmount, 1.0));
- EffectLayer.Set(Properties.Sequence, bombColor);
+ EffectLayer.Set(Properties.Sequence, in bombColor);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBurningLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBurningLayerHandler.cs
index d050bd5f4..d426b7e32 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBurningLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOBurningLayerHandler.cs
@@ -41,7 +41,7 @@ public override void Default()
public class CSGOBurningLayerHandler() : LayerHandler("CSGO - Burning")
{
private readonly Random _randomizer = new();
- private readonly SolidBrush _solidBrush = new(Color.Empty);
+ private Color _currentColor = Color.Transparent;
protected override UserControl CreateControl()
{
@@ -50,11 +50,11 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameStateCsgo csgostate) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateCsgo csgostate) return EmptyLayer.Instance;
//Update Burning
- if (csgostate.Player.State.Burning <= 0) return EffectLayer.EmptyLayer;
+ if (csgostate.Player.State.Burning <= 0) return EmptyLayer.Instance;
var burnColor = Properties.BurningColor;
if (Properties.Animated)
@@ -89,9 +89,9 @@ public override EffectLayer Render(IGameState gameState)
burnColor = Color.FromArgb(csgostate.Player.State.Burning, red, green, blue);
}
- if (_solidBrush.Color == burnColor) return EffectLayer;
- _solidBrush.Color = burnColor;
- EffectLayer.Fill(_solidBrush);
+ if (_currentColor == burnColor) return EffectLayer;
+ _currentColor = burnColor;
+ EffectLayer.Fill(in _currentColor);
return EffectLayer;
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGODeathLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGODeathLayerHandler.cs
index 1297d6c80..bc9513cac 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGODeathLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGODeathLayerHandler.cs
@@ -45,7 +45,6 @@ public class CSGODeathLayerHandler() : LayerHandler 0)
@@ -70,18 +69,18 @@ public override EffectLayer Render(IGameState state)
if (!_isDead)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
var fadeAlpha = GetFadeAlpha();
if (fadeAlpha <= 0)
{
_isDead = false;
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
- _solidBrush.Color = CommonColorUtils.FastColor(deathColor.R, deathColor.G, deathColor.B, (byte)fadeAlpha);
- EffectLayer.Fill(_solidBrush);
+ var color = CommonColorUtils.FastColor(deathColor.R, deathColor.G, deathColor.B, (byte)fadeAlpha);
+ EffectLayer.Fill(in color);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOKillsIndicatorLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOKillsIndicatorLayerHandler.cs
index b0e3c0bed..f4557f4d4 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOKillsIndicatorLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOKillsIndicatorLayerHandler.cs
@@ -73,7 +73,7 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameStateCsgo csgostate) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateCsgo csgostate) return EmptyLayer.Instance;
if (!csgostate.Provider.SteamID.Equals(csgostate.Player.SteamID)) return EffectLayer;
if (csgostate.Round.Phase == RoundPhase.FreezeTime) return EffectLayer;
@@ -96,7 +96,7 @@ public override EffectLayer Render(IGameState gameState)
EffectLayer.Set(Properties.Sequence.Keys[pos], Properties.HeadshotKillColor);
break;
case RoundKillType.None:
- EffectLayer.Set(Properties.Sequence.Keys[pos], Color.Empty);
+ EffectLayer.Set(Properties.Sequence.Keys[pos], in Color.Empty);
break;
}
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOTypingIndicatorLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOTypingIndicatorLayerHandler.cs
index 79afa78e4..e722a17e6 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOTypingIndicatorLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOTypingIndicatorLayerHandler.cs
@@ -47,8 +47,8 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameStateCsgo csgostate) return EffectLayer.EmptyLayer;
- if (csgostate.Player.Activity != PlayerActivity.TextInput) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateCsgo csgostate) return EmptyLayer.Instance;
+ if (csgostate.Player.Activity != PlayerActivity.TextInput) return EmptyLayer.Instance;
//Update Typing Keys
EffectLayer.Set(Properties.Sequence, Properties.TypingKeysColor);
diff --git a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOWinningTeamLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOWinningTeamLayerHandler.cs
index b7e5ccd6d..cd7c8ffde 100644
--- a/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOWinningTeamLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/CSGO/Layers/CSGOWinningTeamLayerHandler.cs
@@ -36,24 +36,22 @@ public override void Default()
public class CSGOWinningTeamLayerHandler() : LayerHandler("CSGO - Winning Team Effect")
{
- private readonly SolidBrush _solidBrush = new(Color.Empty);
-
protected override UserControl CreateControl()
{
return new Control_CSGOWinningTeamLayer(this);
}
- public override EffectLayer Render(IGameState state)
+ public override EffectLayer Render(IGameState gameState)
{
- if (state is not GameStateCsgo csgostate) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateCsgo csgostate) return EmptyLayer.Instance;
// Block animations after end of round
if (csgostate.Map.Phase == MapPhase.Undefined || csgostate.Round.Phase != RoundPhase.Over)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
- _solidBrush.Color = Color.White;
+ var color = Color.White;
// Triggers directly after a team wins a round
if (csgostate.Round.WinTeam != RoundWinTeam.Undefined && csgostate.Previously?.Round.WinTeam == RoundWinTeam.Undefined)
@@ -67,26 +65,26 @@ public override EffectLayer Render(IGameState state)
if (tScore > ctScore)
{
- _solidBrush.Color = Properties.TColor;
+ color = Properties.TColor;
}
else if (ctScore > tScore)
{
- _solidBrush.Color = Properties.CtColor;
+ color = Properties.CtColor;
}
}
else
{
- _solidBrush.Color = csgostate.Round.WinTeam switch
+ color = csgostate.Round.WinTeam switch
{
// End of round
RoundWinTeam.T => Properties.TColor,
RoundWinTeam.CT => Properties.CtColor,
- _ => _solidBrush.Color
+ _ => color
};
}
}
- EffectLayer.Fill(_solidBrush);
+ EffectLayer.Fill(in color);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/Desktop/DesktopProfile.cs b/Project-Aurora/Project-Aurora/Profiles/Desktop/DesktopProfile.cs
index 990a4ff0f..a9d1a6413 100755
--- a/Project-Aurora/Project-Aurora/Profiles/Desktop/DesktopProfile.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Desktop/DesktopProfile.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
@@ -41,10 +40,9 @@ private void AddVolumeOverlay()
{
Properties = new PercentGradientLayerHandlerProperties
{
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.VOLUME_MUTE, DeviceKeys.VOLUME_UP, DeviceKeys.VOLUME_DOWN
- }),
+ ]),
PercentType = PercentEffectType.AllAtOnce,
Gradient = new EffectBrush(EffectBrush.BrushType.Linear)
{
@@ -65,15 +63,14 @@ private void AddVolumeOverlay()
private void AddPause()
{
- OverlayLayers.Add(new Layer("Media Pause", new SolidColorLayerHandler()
+ OverlayLayers.Add(new Layer("Media Pause", new SolidColorLayerHandler
{
Properties = new LayerHandlerProperties
{
_PrimaryColor = Color.Yellow,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.MEDIA_PLAY, DeviceKeys.MEDIA_PLAY_PAUSE
- }),
+ ]),
},
}, new OverrideLogicBuilder().SetDynamicBoolean("_Enabled",
new BooleanGSIBoolean("LocalPCInfo/Media/MediaPlaying")
@@ -87,10 +84,9 @@ private void AddPlay()
Properties = new LayerHandlerProperties
{
_PrimaryColor = Color.Lime,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.MEDIA_PLAY, DeviceKeys.MEDIA_PLAY_PAUSE
- }),
+ ]),
},
}, new OverrideLogicBuilder().SetDynamicBoolean("_Enabled",
new BooleanAnd(
@@ -107,10 +103,9 @@ private void AddNext()
Properties = new LayerHandlerProperties
{
_PrimaryColor = Color.Lime,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.MEDIA_NEXT
- }),
+ ]),
},
}, new OverrideLogicBuilder().SetDynamicBoolean("_Enabled",
new BooleanGSIBoolean("LocalPCInfo/Media/HasNextMedia")
@@ -124,10 +119,9 @@ private void AddPrevious()
Properties = new LayerHandlerProperties
{
_PrimaryColor = Color.Lime,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.MEDIA_PREVIOUS
- }),
+ ]),
},
}, new OverrideLogicBuilder().SetDynamicBoolean("_Enabled",
new BooleanGSIBoolean("LocalPCInfo/Media/HasPreviousMedia")
@@ -141,14 +135,13 @@ private void AddHasMedia()
Properties = new LayerHandlerProperties
{
_PrimaryColor = Color.Red,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.VOLUME_MUTE,
DeviceKeys.MEDIA_PREVIOUS,
DeviceKeys.MEDIA_PLAY, DeviceKeys.MEDIA_PLAY_PAUSE,
DeviceKeys.MEDIA_STOP,
- DeviceKeys.MEDIA_NEXT,
- }),
+ DeviceKeys.MEDIA_NEXT
+ ]),
},
}, new OverrideLogicBuilder().SetDynamicBoolean("_Enabled",
new BooleanGSIBoolean("LocalPCInfo/Media/HasMedia")
@@ -178,8 +171,8 @@ public override void Reset()
new NumberMathsOperation(new NumberGSINumeric("LocalPCInfo/Desktop/AccentB"), MathsOperator.Div, new NumberConstant(255))
);
- Layers = new ObservableCollection
- {
+ Layers =
+ [
new("Num Lock", new LockColourLayerHandler
{
Properties = new LockColourLayerHandlerProperties
@@ -187,9 +180,10 @@ public override void Reset()
_ToggledKey = Keys.NumLock,
_PrimaryColor = CommonColorUtils.FastColor(108, 20, 255),
SecondaryColor = CommonColorUtils.FastColor(255, 0, 4, 120),
- _Sequence = new KeySequence(new[] { DeviceKeys.NUM_LOCK }),
+ _Sequence = new KeySequence([DeviceKeys.NUM_LOCK]),
}
}),
+
new("Caps", new LockColourLayerHandler
{
Properties = new LockColourLayerHandlerProperties
@@ -197,104 +191,107 @@ public override void Reset()
_ToggledKey = Keys.Capital,
_PrimaryColor = CommonColorUtils.FastColor(164, 45, 69),
SecondaryColor = CommonColorUtils.FastColor(0, 0, 0, 0),
- _Sequence = new KeySequence(new[] { DeviceKeys.CAPS_LOCK }),
+ _Sequence = new KeySequence([DeviceKeys.CAPS_LOCK]),
}
}),
+
new("Ctrl Shortcuts", new ShortcutAssistantLayerHandler
{
Properties = new ShortcutAssistantLayerHandlerProperties
{
_PrimaryColor = Color.Red,
- ShortcutKeys = new Keybind[]
- {
- new(new[] { Keys.LControlKey, Keys.X }),
- new(new[] { Keys.LControlKey, Keys.C }),
- new(new[] { Keys.LControlKey, Keys.V }),
- new(new[] { Keys.LControlKey, Keys.Z }),
- new(new[] { Keys.LControlKey, Keys.F4 }),
- new(new[] { Keys.LControlKey, Keys.A }),
- new(new[] { Keys.LControlKey, Keys.D }),
- new(new[] { Keys.LControlKey, Keys.R }),
- new(new[] { Keys.LControlKey, Keys.Y }),
- new(new[] { Keys.LControlKey, Keys.Right }),
- new(new[] { Keys.LControlKey, Keys.Left }),
- new(new[] { Keys.LControlKey, Keys.Down }),
- new(new[] { Keys.LControlKey, Keys.Up }),
- new(new[] { Keys.LControlKey, Keys.LMenu, Keys.Tab }),
- new(new[] { Keys.LControlKey, Keys.LMenu, Keys.Delete }),
- new(new[] { Keys.LControlKey, Keys.LShiftKey, Keys.Up }),
- new(new[] { Keys.LControlKey, Keys.LShiftKey, Keys.Down }),
- new(new[] { Keys.LControlKey, Keys.LShiftKey, Keys.Left }),
- new(new[] { Keys.LControlKey, Keys.LShiftKey, Keys.Right }),
- new(new[] { Keys.LControlKey, Keys.Escape }),
- new(new[] { Keys.LControlKey, Keys.LShiftKey, Keys.Escape }),
- new(new[] { Keys.LControlKey, Keys.Escape }),
- new(new[] { Keys.LControlKey, Keys.F })
- },
+ ShortcutKeys =
+ [
+ new([Keys.LControlKey, Keys.X]),
+ new([Keys.LControlKey, Keys.C]),
+ new([Keys.LControlKey, Keys.V]),
+ new([Keys.LControlKey, Keys.Z]),
+ new([Keys.LControlKey, Keys.F4]),
+ new([Keys.LControlKey, Keys.A]),
+ new([Keys.LControlKey, Keys.D]),
+ new([Keys.LControlKey, Keys.R]),
+ new([Keys.LControlKey, Keys.Y]),
+ new([Keys.LControlKey, Keys.Right]),
+ new([Keys.LControlKey, Keys.Left]),
+ new([Keys.LControlKey, Keys.Down]),
+ new([Keys.LControlKey, Keys.Up]),
+ new([Keys.LControlKey, Keys.LMenu, Keys.Tab]),
+ new([Keys.LControlKey, Keys.LMenu, Keys.Delete]),
+ new([Keys.LControlKey, Keys.LShiftKey, Keys.Up]),
+ new([Keys.LControlKey, Keys.LShiftKey, Keys.Down]),
+ new([Keys.LControlKey, Keys.LShiftKey, Keys.Left]),
+ new([Keys.LControlKey, Keys.LShiftKey, Keys.Right]),
+ new([Keys.LControlKey, Keys.Escape]),
+ new([Keys.LControlKey, Keys.LShiftKey, Keys.Escape]),
+ new([Keys.LControlKey, Keys.Escape]),
+ new([Keys.LControlKey, Keys.F])
+ ],
PresentationType = ShortcutAssistantPresentationType.ProgressiveSuggestion,
}
}, accentColorOverride),
+
new("Win Shortcuts", new ShortcutAssistantLayerHandler
{
Properties = new ShortcutAssistantLayerHandlerProperties
{
_PrimaryColor = Color.Blue,
- ShortcutKeys = new Keybind[]
- {
- new(new[] { Keys.LWin, Keys.L }),
- new(new[] { Keys.LWin, Keys.D }),
- new(new[] { Keys.LWin, Keys.B }),
- new(new[] { Keys.LWin, Keys.A }),
- new(new[] { Keys.LWin, Keys.LMenu, Keys.D }),
- new(new[] { Keys.LWin, Keys.E }),
- new(new[] { Keys.LWin, Keys.G }),
- new(new[] { Keys.LWin, Keys.I }),
- new(new[] { Keys.LWin, Keys.M }),
- new(new[] { Keys.LWin, Keys.P }),
- new(new[] { Keys.LWin, Keys.R }),
- new(new[] { Keys.LWin, Keys.S }),
- new(new[] { Keys.LWin, Keys.Up }),
- new(new[] { Keys.LWin, Keys.Down }),
- new(new[] { Keys.LWin, Keys.Left }),
- new(new[] { Keys.LWin, Keys.Right }),
- new(new[] { Keys.LWin, Keys.Home }),
- new(new[] { Keys.LWin, Keys.D })
- },
+ ShortcutKeys =
+ [
+ new([Keys.LWin, Keys.L]),
+ new([Keys.LWin, Keys.D]),
+ new([Keys.LWin, Keys.B]),
+ new([Keys.LWin, Keys.A]),
+ new([Keys.LWin, Keys.LMenu, Keys.D]),
+ new([Keys.LWin, Keys.E]),
+ new([Keys.LWin, Keys.G]),
+ new([Keys.LWin, Keys.I]),
+ new([Keys.LWin, Keys.M]),
+ new([Keys.LWin, Keys.P]),
+ new([Keys.LWin, Keys.R]),
+ new([Keys.LWin, Keys.S]),
+ new([Keys.LWin, Keys.Up]),
+ new([Keys.LWin, Keys.Down]),
+ new([Keys.LWin, Keys.Left]),
+ new([Keys.LWin, Keys.Right]),
+ new([Keys.LWin, Keys.Home]),
+ new([Keys.LWin, Keys.D])
+ ],
PresentationType = ShortcutAssistantPresentationType.ProgressiveSuggestion,
}
}, accentColorOverride),
+
new("Alt Shortcuts", new ShortcutAssistantLayerHandler
{
Properties = new ShortcutAssistantLayerHandlerProperties
{
_PrimaryColor = Color.Yellow,
- ShortcutKeys = new Keybind[]
- {
- new(new[] { Keys.LMenu, Keys.Tab }),
- new(new[] { Keys.LMenu, Keys.F4 }),
- new(new[] { Keys.LMenu, Keys.Space }),
- new(new[] { Keys.LMenu, Keys.Left }),
- new(new[] { Keys.LMenu, Keys.Right }),
- new(new[] { Keys.LMenu, Keys.PageUp }),
- new(new[] { Keys.LMenu, Keys.PageDown }),
- new(new[] { Keys.LMenu, Keys.Tab }),
- },
+ ShortcutKeys =
+ [
+ new([Keys.LMenu, Keys.Tab]),
+ new([Keys.LMenu, Keys.F4]),
+ new([Keys.LMenu, Keys.Space]),
+ new([Keys.LMenu, Keys.Left]),
+ new([Keys.LMenu, Keys.Right]),
+ new([Keys.LMenu, Keys.PageUp]),
+ new([Keys.LMenu, Keys.PageDown]),
+ new([Keys.LMenu, Keys.Tab])
+ ],
PresentationType = ShortcutAssistantPresentationType.ProgressiveSuggestion,
}
}, accentColorOverride),
+
new("Accent", new SolidColorLayerHandler
{
Properties = new LayerHandlerProperties
{
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.ESC, DeviceKeys.TILDE, DeviceKeys.TAB, DeviceKeys.CAPS_LOCK, DeviceKeys.LEFT_SHIFT,
DeviceKeys.LEFT_CONTROL,
DeviceKeys.LEFT_WINDOWS, DeviceKeys.LEFT_ALT, DeviceKeys.RIGHT_ALT, DeviceKeys.FN_Key, DeviceKeys.LEFT_FN,
DeviceKeys.APPLICATION_SELECT,
DeviceKeys.RIGHT_CONTROL, DeviceKeys.RIGHT_SHIFT, DeviceKeys.ENTER, DeviceKeys.BACKSPACE,
DeviceKeys.NUM_LOCK_LED, DeviceKeys.CAPS_LOCK_LED, DeviceKeys.SCROLL_LOCK_LED
- })
+ ])
}
},
accentColorOverride.SetLookupTable(nameof(LayerHandlerProperties._Enabled),
@@ -302,8 +299,9 @@ public override void Reset()
.AddEntry(false, new BooleanKeyDown(Keys.LControlKey))
.AddEntry(false, new BooleanKeyDown(Keys.LWin))
.AddEntry(false, new BooleanKeyDown(Keys.LMenu))
- )
- ),
+ )
+ ),
+
new("CPU Usage", new PercentLayerHandler
{
Properties = new PercentLayerHandlerProperties
@@ -311,12 +309,11 @@ public override void Reset()
_PrimaryColor = Color.FromArgb(0, 205, 255),
SecondaryColor = Color.FromArgb(0, 65, 80),
PercentType = PercentEffectType.Progressive_Gradual,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.F1, DeviceKeys.F2, DeviceKeys.F3, DeviceKeys.F4,
DeviceKeys.F5, DeviceKeys.F6, DeviceKeys.F7, DeviceKeys.F8,
DeviceKeys.F9, DeviceKeys.F10, DeviceKeys.F11, DeviceKeys.F12
- }),
+ ]),
BlinkThreshold = 0.0,
BlinkDirection = false,
VariablePath = new VariablePath("LocalPCInfo/CPU/Usage"),
@@ -326,6 +323,7 @@ public override void Reset()
{
Enabled = false,
},
+
new("RAM Usage", new PercentLayerHandler
{
Properties = new PercentLayerHandlerProperties
@@ -333,12 +331,11 @@ public override void Reset()
_PrimaryColor = Color.FromArgb(255, 80, 0),
SecondaryColor = Color.FromArgb(90, 30, 0),
PercentType = PercentEffectType.Progressive_Gradual,
- _Sequence = new KeySequence(new[]
- {
+ _Sequence = new KeySequence([
DeviceKeys.ONE, DeviceKeys.TWO, DeviceKeys.THREE, DeviceKeys.FOUR,
DeviceKeys.FIVE, DeviceKeys.SIX, DeviceKeys.SEVEN, DeviceKeys.EIGHT,
DeviceKeys.NINE, DeviceKeys.ZERO, DeviceKeys.MINUS, DeviceKeys.EQUALS
- }),
+ ]),
BlinkThreshold = 0.0,
BlinkDirection = false,
VariablePath = new VariablePath("LocalPCInfo/RAM/Used"),
@@ -348,6 +345,7 @@ public override void Reset()
{
Enabled = false,
},
+
new("Interactive Layer", new InteractiveLayerHandler
{
Properties = new InteractiveLayerHandlerProperties
@@ -359,6 +357,7 @@ public override void Reset()
EffectWidth = 4
}
}),
+
new("Gradient Wave", new GradientLayerHandler
{
Properties = new GradientLayerHandlerProperties
@@ -381,23 +380,24 @@ public override void Reset()
End = new PointF(1, 1),
ColorGradients = new SortedDictionary
{
- {0, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.06593407690525055, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.1538461595773697, CommonColorUtils.FastColor(153, 59, 237) },
- {0.24337075650691986, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.4263019561767578, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.5358933806419373, CommonColorUtils.FastColor(151, 183, 63) },
- {0.6483517289161682, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.7614668011665344, CommonColorUtils.FastColor(0, 24, 24, 51) },
- {0.8626373410224915, CommonColorUtils.FastColor(129, 255, 239, 48) },
- {0.9395604133605957, CommonColorUtils.FastColor(0, 24, 24, 51) },
- {1, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.06593407690525055, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.1538461595773697, CommonColorUtils.FastColor(153, 59, 237) },
+ { 0.24337075650691986, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.4263019561767578, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.5358933806419373, CommonColorUtils.FastColor(151, 183, 63) },
+ { 0.6483517289161682, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.7614668011665344, CommonColorUtils.FastColor(0, 24, 24, 51) },
+ { 0.8626373410224915, CommonColorUtils.FastColor(129, 255, 239) },
+ { 0.9395604133605957, CommonColorUtils.FastColor(0, 24, 24, 51) },
+ { 1, CommonColorUtils.FastColor(0, 0, 0, 0) },
},
},
},
- _LayerOpacity = 0.5f,
+ _LayerOpacity = 0.33f,
}
}),
+
new("Gradient Wave 2", new GradientLayerHandler
{
Properties = new GradientLayerHandlerProperties
@@ -421,28 +421,38 @@ public override void Reset()
End = new PointF(1, 1),
ColorGradients = new SortedDictionary
{
- {0, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.03296704590320587, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.1538461595773697, CommonColorUtils.FastColor(153, 58, 249, 159) },
- {0.2983158230781555, CommonColorUtils.FastColor(10, 0, 0, 0) },
- {0.39333492517471313, CommonColorUtils.FastColor(0, 0, 0, 0) },
- {0.5358933806419373, CommonColorUtils.FastColor(151, 87, 63) },
- {0.6868132948875427, CommonColorUtils.FastColor(4, 0, 0, 0) },
- {0.7230052351951599, CommonColorUtils.FastColor(0, 24, 24, 51) },
- {0.8626373410224915, CommonColorUtils.FastColor(129, 255, 135, 48) },
- {0.9725274443626404, CommonColorUtils.FastColor(0, 24, 24, 51) },
- {1, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.03296704590320587, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.1538461595773697, CommonColorUtils.FastColor(153, 58, 249) },
+ { 0.2983158230781555, CommonColorUtils.FastColor(10, 0, 0, 0) },
+ { 0.39333492517471313, CommonColorUtils.FastColor(0, 0, 0, 0) },
+ { 0.5358933806419373, CommonColorUtils.FastColor(151, 87, 63) },
+ { 0.6868132948875427, CommonColorUtils.FastColor(4, 0, 0, 0) },
+ { 0.7230052351951599, CommonColorUtils.FastColor(0, 24, 24, 51) },
+ { 0.8626373410224915, CommonColorUtils.FastColor(129, 255, 135) },
+ { 0.9725274443626404, CommonColorUtils.FastColor(0, 24, 24, 51) },
+ { 1, CommonColorUtils.FastColor(0, 0, 0, 0) },
},
},
},
- _LayerOpacity = 0.5f,
+ _LayerOpacity = 0.33f,
}
}),
+
+ new("Brightness", new SolidFillLayerHandler
+ {
+ Properties = new SolidFillLayerHandlerProperties
+ {
+ _PrimaryColor = Color.FromArgb(255, 255, 255, 255),
+ _LayerOpacity = 0.1f,
+ }
+ }),
+
new("Background", new GradientLayerHandler
{
Properties = new GradientLayerHandlerProperties
{
- _LayerOpacity = 0.08f,
+ _LayerOpacity = 0.20f,
Sequence =
{
Freeform = new FreeFormObject(0, 0, 1200, 260),
@@ -467,7 +477,7 @@ public override void Reset()
}
}
}
- }),
- };
+ })
+ ];
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Idle.cs b/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Idle.cs
index 462b2ca6c..3894c3eb5 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Idle.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Desktop/Event_Idle.cs
@@ -13,7 +13,7 @@ namespace AuroraRgb.Profiles.Desktop;
public sealed class EventIdle : LightEvent
{
- private readonly EffectLayer _layer = new("IDLE", true);
+ private readonly BitmapEffectLayer _layer = new("IDLE", true);
private DateTime _previousTime = DateTime.UtcNow;
internal DateTime CurrentTime = DateTime.UtcNow;
@@ -103,12 +103,12 @@ public abstract class AwayEffect
protected readonly Color IdleEffectPrimaryColor = Global.Configuration.IdleEffectPrimaryColor;
protected readonly SolidBrush IdEffectSecondaryColorBrush = new(Global.Configuration.IdleEffectSecondaryColor);
- public abstract void Update(EffectLayer layer);
+ public abstract void Update(BitmapEffectLayer layer);
}
internal class NoneEffect : AwayEffect
{
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
//noop
}
@@ -123,7 +123,7 @@ private DimEffect()
{
}
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
layer.Fill(_dimBrush);
}
@@ -131,7 +131,7 @@ public override void Update(EffectLayer layer)
internal class ColorBreathingEffect(EventIdle eventIdle) : AwayEffect
{
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
layer.Fill(IdEffectSecondaryColorBrush);
var sine = (float) Math.Pow(
@@ -143,7 +143,7 @@ public override void Update(EffectLayer layer)
internal class RainbowShiftHorizontal(EventIdle eventIdle) : AwayEffect
{
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
layer.DrawGradient(LayerEffects.RainbowShift_Horizontal, eventIdle.EffectCfg);
}
@@ -151,7 +151,7 @@ public override void Update(EffectLayer layer)
internal class RainbowShiftVertical(EventIdle eventIdle) : AwayEffect
{
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
layer.DrawGradient(LayerEffects.RainbowShift_Vertical, eventIdle.EffectCfg);
}
@@ -163,7 +163,7 @@ internal class StarFall(EventIdle eventIdle) : AwayEffect
private readonly Dictionary _stars = new();
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
if (_nextStarSet < eventIdle.CurrentTime)
{
@@ -198,7 +198,7 @@ internal class RainFall(EventIdle eventIdle) : AwayEffect
private readonly Pen _pen = new(Color.Transparent, 2);
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
if (_nextStarSet < eventIdle.CurrentTime)
{
@@ -235,7 +235,7 @@ public override void Update(EffectLayer layer)
internal class Blackout : AwayEffect
{
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
layer.Fill(Brushes.Black);
}
@@ -246,7 +246,7 @@ public class Matrix(EventIdle eventIdle) : AwayEffect
private readonly AnimationMix _matrixLines = new AnimationMix().SetAutoRemove(true); //This will be an infinite Mix
private DateTime _nextStarSet;
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
var span = eventIdle.CurrentTime - DateTime.UnixEpoch;
var ms = (long)span.TotalMilliseconds;
@@ -312,7 +312,7 @@ internal class RainFallSmooth(EventIdle eventIdle) : AwayEffect
private DateTime _nextStarSet;
- public override void Update(EffectLayer layer)
+ public override void Update(BitmapEffectLayer layer)
{
if (_nextStarSet < eventIdle.CurrentTime)
{
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2AbilityLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2AbilityLayerHandler.cs
index a5dd4ce7b..4409ca50f 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2AbilityLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2AbilityLayerHandler.cs
@@ -59,10 +59,10 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState state)
{
- if (state is not GameStateDota2 dota2State) return EffectLayer.EmptyLayer;
+ if (state is not GameStateDota2 dota2State) return EmptyLayer.Instance;
if (dota2State.Map.GameState != DOTA_GameState.DOTA_GAMERULES_STATE_PRE_GAME &&
dota2State.Map.GameState != DOTA_GameState.DOTA_GAMERULES_STATE_GAME_IN_PROGRESS)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
for (var index = 0; index < dota2State.Abilities.Count; index++)
{
var ability = dota2State.Abilities[index];
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2BackgroundLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2BackgroundLayerHandler.cs
index 39c62af6f..7b843eaae 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2BackgroundLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2BackgroundLayerHandler.cs
@@ -80,10 +80,10 @@ protected override UserControl CreateControl()
return new Control_Dota2BackgroundLayer(this);
}
- private SolidBrush _currentColor = new(Color.Empty);
+ private Color _currentColor = Color.Transparent;
public override EffectLayer Render(IGameState state)
{
- if (state is not GameStateDota2 dota2State) return EffectLayer.EmptyLayer;
+ if (state is not GameStateDota2 dota2State) return EmptyLayer.Instance;
if (dota2State.Previously?.Hero.HealthPercent == 0 && dota2State.Hero.HealthPercent == 100 && !dota2State.Previously.Hero.IsAlive && dota2State.Hero.IsAlive)
{
@@ -113,11 +113,11 @@ public override EffectLayer Render(IGameState state)
}
}
- if (!Invalidated && _currentColor.Color == bgColor) return EffectLayer;
+ if (!Invalidated && _currentColor == bgColor) return EffectLayer;
- _currentColor = new SolidBrush(bgColor);
+ _currentColor = bgColor;
EffectLayer.Clear();
- EffectLayer.Fill(_currentColor);
+ EffectLayer.Fill(in _currentColor);
Invalidated = false;
return EffectLayer;
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2HeroAbiltiyEffectsLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2HeroAbiltiyEffectsLayerHandler.cs
index 0d50baa0f..5eacae1f6 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2HeroAbiltiyEffectsLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2HeroAbiltiyEffectsLayerHandler.cs
@@ -12,7 +12,7 @@
namespace AuroraRgb.Profiles.Dota_2.Layers
{
- public class Dota2HeroAbilityEffectsLayerHandler : LayerHandler
+ public class Dota2HeroAbilityEffectsLayerHandler : LayerHandler
{
private enum Dota2AbilityEffects
{
@@ -131,7 +131,7 @@ public override EffectLayer Render(IGameState state)
_previousTime = _currentTime;
_currentTime = Time.GetMillisecondsSinceEpoch();
- if (state is not GameStateDota2 dota2State) return EffectLayer.EmptyLayer;
+ if (state is not GameStateDota2 dota2State) return EmptyLayer.Instance;
//Preparations
if (_abilities != null && dota2State.Abilities.Count == _abilities.Count)
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2ItemLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2ItemLayerHandler.cs
index 14624e003..e85ec7ead 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2ItemLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2ItemLayerHandler.cs
@@ -419,23 +419,23 @@ public override EffectLayer Render(IGameState state)
{
itemColor = Properties.ItemsColor;
}
- EffectLayer.Set(key, itemColor);
+ EffectLayer.Set(key, in itemColor);
//Cooldown
if (item.Cooldown > 5)
- EffectLayer.Set(key, ColorUtils.BlendColors(itemColor, Properties.ItemCooldownColor, 1.0));
+ EffectLayer.Set(key, ColorUtils.BlendColors(in itemColor, Properties.ItemCooldownColor, 1.0));
else if (item.Cooldown is > 0 and <= 5)
- EffectLayer.Set(key, ColorUtils.BlendColors(itemColor, Properties.ItemCooldownColor, item.Cooldown / 5.0));
+ EffectLayer.Set(key, ColorUtils.BlendColors(in itemColor, Properties.ItemCooldownColor, item.Cooldown / 5.0));
//Charges
if (item.Charges == 0)
- EffectLayer.Set(key, ColorUtils.BlendColors(itemColor, Properties.ItemNoChargersColor, 0.7));
+ EffectLayer.Set(key, ColorUtils.BlendColors(in itemColor, Properties.ItemNoChargersColor, 0.7));
}
}
}
else
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
return EffectLayer;
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2KillstreakLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2KillstreakLayerHandler.cs
index 2c2d05cb4..9731c2a99 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2KillstreakLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2KillstreakLayerHandler.cs
@@ -124,8 +124,6 @@ public class Dota2KillstreakLayerHandler() : LayerHandler 0)) return EffectLayer.EmptyLayer;
+ if (!(ksEffectValue > 0)) return EmptyLayer.Instance;
EffectLayer.Clear();
- _solidBrush.Color = ColorUtils.BlendColors(Color.Transparent, ksColor, ksEffectValue);
- EffectLayer.Fill(_solidBrush);
+ var color = ColorUtils.BlendColors(Color.Transparent, ksColor, ksEffectValue);
+ EffectLayer.Fill(in color);
_empty = false;
return EffectLayer;
diff --git a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2RespawnLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2RespawnLayerHandler.cs
index 967747f8d..133a41f08 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2RespawnLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Dota 2/Layers/Dota2RespawnLayerHandler.cs
@@ -57,7 +57,7 @@ public override void Default()
}
-public class Dota2RespawnLayerHandler() : LayerHandler("Dota 2 - Respawn")
+public class Dota2RespawnLayerHandler() : LayerHandler("Dota 2 - Respawn")
{
private readonly SolidBrush _solidBrush = new(Color.Empty);
@@ -66,14 +66,14 @@ protected override UserControl CreateControl()
return new Control_Dota2RespawnLayer(this);
}
- public override EffectLayer Render(IGameState state)
+ public override EffectLayer Render(IGameState gameState)
{
- if (state is not GameStateDota2 dota2State) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateDota2 dota2State) return EmptyLayer.Instance;
if (dota2State.Player.Team is DotaPlayerTeam.Undefined or DotaPlayerTeam.None ||
- dota2State.Hero.IsAlive) return EffectLayer.EmptyLayer;
+ dota2State.Hero.IsAlive) return EmptyLayer.Instance;
var percent = dota2State.Hero.SecondsToRespawn > 5 ? 0.0 : 1.0 - dota2State.Hero.SecondsToRespawn / 5.0;
- if (percent <= 0) return EffectLayer.EmptyLayer;
+ if (percent <= 0) return EmptyLayer.Instance;
_solidBrush.Color = ColorUtils.BlendColors(Color.Transparent, Properties.BackgroundColor, percent);
EffectLayer.Fill(_solidBrush);
diff --git a/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BeaconLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BeaconLayerHandler.cs
index 90824125f..0c1be5338 100644
--- a/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BeaconLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BeaconLayerHandler.cs
@@ -52,7 +52,7 @@ public override void Default() {
}
}
-public class ETS2BeaconLayerHandler : LayerHandler {
+public class ETS2BeaconLayerHandler() : LayerHandler("ETS2BeaconLayerHandler") {
private int _frame;
@@ -67,7 +67,8 @@ private Color PrimaryColorAlpha(double a) {
}
public override EffectLayer Render(IGameState gamestate) {
- var layer = new EffectLayer("ETS2 Beacon Layer");
+ var layer = EffectLayer;
+ layer.Clear();
if (gamestate is GameState_ETS2 { Truck.lightsBeaconOn: true }) {
switch (Properties.BeaconStyle) {
diff --git a/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BlinkerLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BlinkerLayerHandler.cs
index 0e4e89806..0b174644f 100644
--- a/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BlinkerLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/ETS2/Layers/ETS2BlinkerLayerHandler.cs
@@ -52,22 +52,21 @@ public override void Default() {
}
}
- public class ETS2BlinkerLayerHandler : LayerHandler {
+ public class ETS2BlinkerLayerHandler() : LayerHandler("Ets2BlinkerLayerHandler") {
protected override UserControl CreateControl() {
return new Control_ETS2BlinkerLayer(this);
}
public override EffectLayer Render(IGameState gamestate) {
- var blinker_layer = new EffectLayer("ETS2 - Blinker Layer");
- if (gamestate is not GameState_ETS2 stateEts2) return blinker_layer;
+ if (gamestate is not GameState_ETS2 stateEts2) return EmptyLayer.Instance;
// Left blinker
var trgColor = stateEts2.Truck.blinkerLeftOn ? Properties.BlinkerOnColor : Properties.BlinkerOffColor;
- blinker_layer.Set(Properties.LeftBlinkerSequence, trgColor);
+ EffectLayer.Set(Properties.LeftBlinkerSequence, trgColor);
// Right blinker
trgColor = stateEts2.Truck.blinkerRightOn ? Properties.BlinkerOnColor : Properties.BlinkerOffColor;
- blinker_layer.Set(Properties.RightBlinkerSequence, trgColor);
- return blinker_layer;
+ EffectLayer.Set(Properties.RightBlinkerSequence, trgColor);
+ return EffectLayer;
}
}
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousAnimationLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousAnimationLayerHandler.cs
index 7e4f806e5..c10503681 100644
--- a/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousAnimationLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousAnimationLayerHandler.cs
@@ -19,7 +19,7 @@ public enum EliteAnimation
HyperspaceExit,
}
-public class EliteDangerousAnimationLayerHandler : LayerHandler
+public class EliteDangerousAnimationLayerHandler : LayerHandler
{
private AnimationMix _fsdCountdownMix;
private AnimationMix _hyperspaceMix;
diff --git a/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousBackgroundLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousBackgroundLayerHandler.cs
index fd5cbc5c7..5ca4ec8ff 100644
--- a/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousBackgroundLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/EliteDangerous/Layers/EliteDangerousBackgroundLayerHandler.cs
@@ -37,8 +37,6 @@ public override void Default()
}
public class EliteDangerousBackgroundLayerHandler() : LayerHandler("Elite: Dangerous - Background")
{
- private readonly SolidBrush _bg = new(Color.Transparent);
-
protected override UserControl CreateControl()
{
return new Control_EliteDangerousBackgroundLayer(this);
@@ -48,8 +46,8 @@ public override EffectLayer Render(IGameState state)
{
var gameState = state as GameState_EliteDangerous;
- _bg.Color = gameState.Status.IsFlagSet(Flag.HUD_DISCOVERY_MODE) ? Properties.DiscoveryModeColor : Properties.CombatModeColor;
- EffectLayer.FillOver(_bg);
+ var color = gameState.Status.IsFlagSet(Flag.HUD_DISCOVERY_MODE) ? Properties.DiscoveryModeColor : Properties.CombatModeColor;
+ EffectLayer.FillOver(color);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Profiles/Guild Wars 2/Control_GW2.xaml.cs b/Project-Aurora/Project-Aurora/Profiles/Guild Wars 2/Control_GW2.xaml.cs
index 52186533e..61a4e7229 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Guild Wars 2/Control_GW2.xaml.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Guild Wars 2/Control_GW2.xaml.cs
@@ -1,5 +1,4 @@
-using System;
-using System.IO;
+using System.IO;
using System.Windows;
using System.Windows.Forms;
using MessageBox = System.Windows.MessageBox;
diff --git a/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs b/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs
index 153e9c22e..3b0af5615 100755
--- a/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/LightingStateManager.cs
@@ -338,7 +338,7 @@ public bool RegisterLayer() where T : ILayerHandler
return Events[value];
}
- private SingleConcurrentThread _updateTimer;
+ private readonly SingleConcurrentThread _updateTimer;
private long _nextProcessNameUpdate;
private long _currentTick;
diff --git a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftBurnLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftBurnLayerHandler.cs
index 11f31f96f..b60af047e 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftBurnLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftBurnLayerHandler.cs
@@ -10,7 +10,7 @@
namespace AuroraRgb.Profiles.Minecraft.Layers;
[Obsolete("This layer is obselete and has been replaced by the Overrides system.")]
-public class MinecraftBurnLayerHandler : LayerHandler {
+public class MinecraftBurnLayerHandler : LayerHandler {
private List particles = new();
private Random rnd = new();
@@ -40,7 +40,7 @@ private void CreateFireParticle() {
public override EffectLayer Render(IGameState gamestate) {
// Render nothing if invalid gamestate or player isn't on fire
if (gamestate is not GameStateMinecraft minecraft || !minecraft.Player.IsBurning)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
// Set the background to red
EffectLayer.FillOver(Brushes.Red);
diff --git a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftHealthBarLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftHealthBarLayerHandler.cs
index 18a006042..0a7060149 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftHealthBarLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftHealthBarLayerHandler.cs
@@ -64,19 +64,15 @@ public override void Default() {
}
}
- public class MinecraftHealthBarLayerHandler : LayerHandler
+ public class MinecraftHealthBarLayerHandler() : LayerHandler("Minecraft Health Bar Layer")
{
- public MinecraftHealthBarLayerHandler() : base("Minecraft Health Bar Layer")
- {
- }
-
protected override UserControl CreateControl() {
return new Control_MinecraftHealthBarLayer(this);
}
public override EffectLayer Render(IGameState gamestate) {
// Ensure the gamestate is for Minecraft, and store a casted reference to it
- if (gamestate is not GameStateMinecraft minecraftState) return EffectLayer.EmptyLayer;
+ if (gamestate is not GameStateMinecraft minecraftState) return EmptyLayer.Instance;
// Choose the main healthbar's color depending on whether the player is withered/poisoned/regen/normal.
var barColor = Properties.NormalHealthColor; // Default normal color
diff --git a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftKeyConflictLayer.cs b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftKeyConflictLayer.cs
index 4a240a7d8..dfc951316 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftKeyConflictLayer.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftKeyConflictLayer.cs
@@ -28,13 +28,8 @@ public override void Default() {
}
- public class MinecraftKeyConflictLayerHandler : LayerHandler {
- private readonly SolidBrush _backgroundBrush = new(Color.Black);
-
- public MinecraftKeyConflictLayerHandler() : base("Minecraft Key Conflict Layer")
- {
- }
-
+ public class MinecraftKeyConflictLayerHandler() : LayerHandler("Minecraft Key Conflict Layer")
+ {
protected override UserControl CreateControl() {
return new Control_MinecraftKeyConflictLayer(this);
}
@@ -42,10 +37,10 @@ protected override UserControl CreateControl() {
public override EffectLayer Render(IGameState gameState) {
if (gameState is not GameStateMinecraft minecraftState || !minecraftState.Game.ControlsGuiOpen)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
- EffectLayer.Fill(_backgroundBrush); // Hide any other layers behind this one
+ EffectLayer.Fill(Color.Black); // Hide any other layers behind this one
// Set all keys in use by any binding to be the no-conflict colour
foreach (var kb in minecraftState.Game.KeyBindings)
if(kb!=null)
diff --git a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftRainLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftRainLayerHandler.cs
index d9122a8f2..3acb9634c 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftRainLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Minecraft/Layers/MinecraftRainLayerHandler.cs
@@ -29,62 +29,58 @@ public override void Default() {
}
}
-public class MinecraftRainLayerHandler : LayerHandler {
-
- private List raindrops = new();
- private Random rnd = new();
- private int frame;
-
- public MinecraftRainLayerHandler() : base("Minecraft Rain Layer")
- {
- }
+public class MinecraftRainLayerHandler() : LayerHandler("Minecraft Rain Layer")
+{
+ private readonly List _raindrops = new();
+ private readonly Random _rnd = new();
+ private int _frame;
protected override UserControl CreateControl() {
return new Control_MinecraftRainLayer(this);
}
private void CreateRainDrop() {
- var randomX = (float)rnd.NextDouble() * Effects.Canvas.Width;
- raindrops.Add(new Droplet() {
- mix = new AnimationMix(new[] {
+ var randomX = (float)_rnd.NextDouble() * Effects.Canvas.Width;
+ _raindrops.Add(new Droplet(
+ new AnimationMix([
new AnimationTrack("raindrop", 0)
.SetFrame(0, new AnimationFilledRectangle(randomX, 0, 3, 6, Properties.PrimaryColor))
.SetFrame(1, new AnimationFilledRectangle(randomX + 5, Effects.Canvas.Height, 2, 4, Properties.PrimaryColor))
- }),
- time = 0
- });
+ ])
+ ));
}
public override EffectLayer Render(IGameState gamestate) {
- if (!(gamestate is GameStateMinecraft)) return EffectLayer.EmptyLayer;
+ if (gamestate is not GameStateMinecraft minecraft) return EmptyLayer.Instance;
// Add more droplets based on the intensity
- float strength = (gamestate as GameStateMinecraft).World.RainStrength;
+ float strength = minecraft.World.RainStrength;
if (strength > 0) {
- if (frame <= 0) {
+ if (_frame <= 0) {
// calculate time (in frames) until next droplet is created
float min = Properties.MinimumInterval, max = Properties.MaximumInterval; // Store as floats so C# doesn't prematurely round numbers
- frame = (int)Math.Round(min - (min - max) * strength); // https://www.desmos.com/calculator/uak73e5eub
+ _frame = (int)Math.Round(min - (min - max) * strength); // https://www.desmos.com/calculator/uak73e5eub
CreateRainDrop();
} else
- frame--;
+ _frame--;
}
// Render all droplets
var graphics = EffectLayer.GetGraphics();
- foreach (var droplet in raindrops) {
- droplet.mix.Draw(graphics, droplet.time);
- droplet.time += .1f;
+ foreach (var droplet in _raindrops) {
+ droplet.Mix.Draw(graphics, droplet.Time);
+ droplet.Time += .1f;
}
// Remove any expired droplets
- raindrops.RemoveAll(droplet => droplet.time >= 1);
+ _raindrops.RemoveAll(droplet => droplet.Time >= 1);
return EffectLayer;
}
}
-internal class Droplet {
- internal AnimationMix mix;
- internal float time;
+internal class Droplet(AnimationMix mix)
+{
+ internal AnimationMix Mix = mix;
+ internal float Time;
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2BackgroundLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2BackgroundLayerHandler.cs
index e55442919..4e7b16077 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2BackgroundLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2BackgroundLayerHandler.cs
@@ -93,7 +93,7 @@ public override void Default()
}
}
-public class PD2BackgroundLayerHandler : LayerHandler
+public class PD2BackgroundLayerHandler : LayerHandler
{
private float _noReturnFlashamount = 1.0f;
private float _noReturnTimeleft;
@@ -105,7 +105,7 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState state)
{
- if (state is not GameState_PD2 pd2) return EffectLayer.EmptyLayer;
+ if (state is not GameState_PD2 pd2) return EmptyLayer.Instance;
var bgColor = Properties.AmbientColor;
var currenttime = Time.GetMillisecondsSinceEpoch();
@@ -174,10 +174,10 @@ public override EffectLayer Render(IGameState state)
*/
}
- EffectLayer.FillOver(bgColor);
+ EffectLayer.FillOver(in bgColor);
if (Properties.PeripheralUse)
- EffectLayer.Set(DeviceKeys.Peripheral, bgColor);
+ EffectLayer.Set(DeviceKeys.Peripheral, in bgColor);
}
else if (pd2.Level.Phase == LevelPhase.Stealth && pd2.Game.State == GameStates.Ingame)
{
@@ -211,17 +211,17 @@ public override EffectLayer Render(IGameState state)
if (_noReturnFlashamount < 0.0f)
_noReturnFlashamount = 0.0f;
- EffectLayer.FillOver(noReturnColor);
+ EffectLayer.FillOver(in noReturnColor);
if (Properties.PeripheralUse)
- EffectLayer.Set(DeviceKeys.Peripheral, noReturnColor);
+ EffectLayer.Set(DeviceKeys.Peripheral, in noReturnColor);
}
else
{
- EffectLayer.FillOver(bgColor);
+ EffectLayer.FillOver(in bgColor);
if (Properties.PeripheralUse)
- EffectLayer.Set(DeviceKeys.Peripheral, bgColor);
+ EffectLayer.Set(DeviceKeys.Peripheral, in bgColor);
}
return EffectLayer;
diff --git a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2FlashbangLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2FlashbangLayerHandler.cs
index b45da6c8a..3ac34488a 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2FlashbangLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2FlashbangLayerHandler.cs
@@ -29,7 +29,7 @@ public override void Default()
}
-public class PD2FlashbangLayerHandler : LayerHandler
+public class PD2FlashbangLayerHandler() : LayerHandler("PD2FlashbangLayerHandler")
{
protected override UserControl CreateControl()
{
@@ -38,13 +38,13 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameState_PD2 pd2State) return EffectLayer.EmptyLayer;
+ if (gameState is not GameState_PD2 pd2State) return EmptyLayer.Instance;
//Update Flashed
- if (pd2State.Game.State != GameStates.Ingame || pd2State.Players.LocalPlayer.FlashAmount <= 0) return EffectLayer.EmptyLayer;
+ if (pd2State.Game.State != GameStates.Ingame || pd2State.Players.LocalPlayer.FlashAmount <= 0) return EmptyLayer.Instance;
var flashColor = ColorUtils.MultiplyColorByScalar(Properties.FlashbangColor, pd2State.Players.LocalPlayer.FlashAmount);
- EffectLayer.FillOver(flashColor);
+ EffectLayer.FillOver(in flashColor);
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2StatesLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2StatesLayerHandler.cs
index 6b429eff5..367d557c3 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2StatesLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Payday 2/Layers/PD2StatesLayerHandler.cs
@@ -72,9 +72,9 @@ public override void Default()
}
-public class PD2StatesLayerHandler : LayerHandler
+public class PD2StatesLayerHandler() : LayerHandler("PD2StatesLayerHandler")
{
- private readonly EffectLayer _swansongLayer = new("Payday 2 - Swansong", true);
+ private readonly EffectLayer _swansongLayer = new BitmapEffectLayer("Payday 2 - Swansong", true);
protected override UserControl CreateControl()
{
@@ -83,9 +83,9 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameState_PD2 pd2State) return EffectLayer.EmptyLayer;
+ if (gameState is not GameState_PD2 pd2State) return EmptyLayer.Instance;
- if (pd2State.Game.State != GameStates.Ingame) return EffectLayer.EmptyLayer;
+ if (pd2State.Game.State != GameStates.Ingame) return EmptyLayer.Instance;
switch (pd2State.LocalPlayer.State)
{
case PlayerState.Incapacitated or PlayerState.Bleed_out or PlayerState.Fatal:
@@ -99,8 +99,8 @@ public override EffectLayer Render(IGameState gameState)
var incapColor = Color.FromArgb(incapAlpha, Properties.DownedColor);
- EffectLayer.FillOver(incapColor);
- EffectLayer.Set(DeviceKeys.Peripheral, incapColor);
+ EffectLayer.FillOver(in incapColor);
+ EffectLayer.Set(DeviceKeys.Peripheral, in incapColor);
break;
}
case PlayerState.Arrested:
@@ -116,7 +116,8 @@ public override EffectLayer Render(IGameState gameState)
_swansongLayer.Set(DeviceKeys.Peripheral, swansongColor);
- return EffectLayer + _swansongLayer;
+ EffectLayer.Add(_swansongLayer);
+ return EffectLayer;
}
protected override void PropertiesChanged(object? sender, PropertyChangedEventArgs args)
diff --git a/Project-Aurora/Project-Aurora/Profiles/RocketLeague/Layers/RocketLeagueGoalExplosionLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/RocketLeague/Layers/RocketLeagueGoalExplosionLayerHandler.cs
index edc326fbf..e369a738b 100644
--- a/Project-Aurora/Project-Aurora/Profiles/RocketLeague/Layers/RocketLeagueGoalExplosionLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/RocketLeague/Layers/RocketLeagueGoalExplosionLayerHandler.cs
@@ -48,7 +48,7 @@ public override void Default()
}
}
-public class RocketLeagueGoalExplosionLayerHandler() : LayerHandler("Goal Explosion")
+public class RocketLeagueGoalExplosionLayerHandler() : LayerHandler("Goal Explosion")
{
private int _previousOwnTeamGoals;
private int _previousOpponentGoals;
@@ -77,10 +77,10 @@ public override EffectLayer Render(IGameState gameState)
var goalExplosionMix = new AnimationMix();
if (gameState is not GameStateRocketLeague state)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
if (state.Game.Status == RLStatus.Undefined)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
if (state.YourTeam.Goals == -1 || state.OpponentTeam.Goals == -1 || _previousOwnTeamGoals > state.YourTeam.Goals || _previousOpponentGoals > state.OpponentTeam.Goals)
{
diff --git a/Project-Aurora/Project-Aurora/Profiles/Witcher3/Layers/Witcher3BackgroundLayerHandler.cs b/Project-Aurora/Project-Aurora/Profiles/Witcher3/Layers/Witcher3BackgroundLayerHandler.cs
index 37873174a..dd4a17ab6 100644
--- a/Project-Aurora/Project-Aurora/Profiles/Witcher3/Layers/Witcher3BackgroundLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Profiles/Witcher3/Layers/Witcher3BackgroundLayerHandler.cs
@@ -87,7 +87,7 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- if (gameState is not GameStateWitcher3 witcher3State) return EffectLayer.EmptyLayer;
+ if (gameState is not GameStateWitcher3 witcher3State) return EmptyLayer.Instance;
var bgColor = witcher3State.Player.ActiveSign switch
{
diff --git a/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml b/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml
index 65b7fa86e..c95861bbc 100644
--- a/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml
+++ b/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml
@@ -7,44 +7,39 @@
xmlns:overrides="clr-namespace:AuroraRgb.Settings.Overrides"
x:Class="AuroraRgb.Settings.Controls.Control_LayerControlPresenter"
mc:Ignorable="d" d:DesignWidth="602" d:DesignHeight="201.525">
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
diff --git a/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml.cs b/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml.cs
index 012d92760..863d368e0 100644
--- a/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Controls/Control_LayerControlPresenter.xaml.cs
@@ -2,7 +2,9 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Media;
using System.Windows.Media.Effects;
+using AuroraRgb.EffectsEngine;
using AuroraRgb.Settings.Layers;
namespace AuroraRgb.Settings.Controls;
@@ -31,25 +33,45 @@ private async void SetLayer(Layer layer)
DataContext = layer;
- cmbLayerType.ItemsSource = layer.AssociatedApplication.AllowedLayers.OrderBy(l => l.Order).ThenBy(l => l.Name);
- cmbLayerType.SelectedValue = Layer.Handler.GetType();
-
- ctrlLayerTypeConfig.Content = EmptyContent;
- ctrlLayerTypeConfig.Content = await layer.Control;
- chk_ExcludeMask.IsChecked = Layer.Handler._EnableExclusionMask ?? false;
- keyseq_ExcludeMask.Sequence = Layer.Handler._ExclusionMask;
- sldr_Opacity.Value = (Layer.Handler._Opacity ?? 1d) * 100.0;
- lbl_Opacity_Text.Text = $"{(int)sldr_Opacity.Value} %";
-
- grdLayerConfigs.Visibility = Visibility.Hidden;
- overridesEditor.Visibility = Visibility.Hidden;
- btnConfig.Visibility = Visibility.Visible;
- btnOverrides.Visibility = Visibility.Visible;
- grd_LayerControl.IsHitTestVisible = true;
- grd_LayerControl.Effect = null;
+ CmbLayerType.ItemsSource = layer.AssociatedApplication.AllowedLayers.OrderBy(l => l.Order).ThenBy(l => l.Name);
+ CmbLayerType.SelectedValue = Layer.Handler.GetType();
+
+ CtrlLayerTypeConfig.Content = EmptyContent;
+ CtrlLayerTypeConfig.Content = await layer.Control;
+ ChkExcludeMask.IsChecked = Layer.Handler._EnableExclusionMask ?? false;
+ KeyseqExcludeMask.Sequence = Layer.Handler._ExclusionMask;
+ SldrOpacity.Value = (Layer.Handler._Opacity ?? 1d) * 100.0;
+ LblOpacityText.Text = $"{(int)SldrOpacity.Value} %";
+
+ GrdLayerConfigs.Visibility = Visibility.Hidden;
+ OverridesEditor.Visibility = Visibility.Hidden;
+ BtnConfig.Visibility = Visibility.Visible;
+ BtnOverrides.Visibility = Visibility.Visible;
+ GrdLayerControl.IsHitTestVisible = true;
+ GrdLayerControl.Effect = null;
_isSettingNewLayer = false;
- overridesEditor.Layer = layer;
+ OverridesEditor.Layer = layer;
+
+ var effectLayerType = layer.Handler.GetEffectLayerType();
+ if (effectLayerType == typeof(NoRenderLayer))
+ {
+ PowerTooltip.Visibility = Visibility.Visible;
+ PowerTooltip.Text = "\ud83c\udf43";
+ PowerTooltip.CircleBackground = Brushes.Green;
+ PowerTooltip.HintTooltip = "Non-rendering layer. Minimum background usage";
+ }else if (effectLayerType == typeof(BitmapEffectLayer))
+ {
+ PowerTooltip.Visibility = Visibility.Visible;
+ PowerTooltip.Text = "\ud83c\udf42";
+ PowerTooltip.CircleBackground = Brushes.Chocolate;
+ PowerTooltip.HintTooltip = "Rendering layer. Background usage may be high depending how often the visual changes";
+ }
+ else
+ {
+ PowerTooltip.Visibility = Visibility.Hidden;
+ }
+ HighUsageTooltip.Visibility = layer.Handler.HighResource() ? Visibility.Visible : Visibility.Hidden;
}
private void cmbLayerType_SelectionChanged(object? sender, SelectionChangedEventArgs e)
@@ -65,22 +87,22 @@ private async void ResetLayer(Type type)
_Layer.Handler = (ILayerHandler)Activator.CreateInstance(type);
- ctrlLayerTypeConfig.Content = EmptyContent;
- ctrlLayerTypeConfig.Content = await _Layer.Control;
- chk_ExcludeMask.IsChecked = Layer.Handler._EnableExclusionMask ?? false;
- keyseq_ExcludeMask.Sequence = Layer.Handler._ExclusionMask;
- sldr_Opacity.Value = (int)(Layer.Handler.Opacity * 100.0f);
- lbl_Opacity_Text.Text = $"{(int)sldr_Opacity.Value} %";
+ CtrlLayerTypeConfig.Content = EmptyContent;
+ CtrlLayerTypeConfig.Content = await _Layer.Control;
+ ChkExcludeMask.IsChecked = Layer.Handler._EnableExclusionMask ?? false;
+ KeyseqExcludeMask.Sequence = Layer.Handler._ExclusionMask;
+ SldrOpacity.Value = (int)(Layer.Handler.Opacity * 100.0f);
+ LblOpacityText.Text = $"{(int)SldrOpacity.Value} %";
_Layer.AssociatedApplication.SaveProfiles();
- overridesEditor.ForcePropertyListUpdate();
+ OverridesEditor.ForcePropertyListUpdate();
}
private void btnReset_Click(object? sender, RoutedEventArgs e)
{
if (IsLoaded && !_isSettingNewLayer && sender is Button)
{
- ResetLayer((Type)cmbLayerType.SelectedValue);
+ ResetLayer((Type)CmbLayerType.SelectedValue);
}
}
@@ -88,11 +110,11 @@ private void btnConfig_Click(object? sender, RoutedEventArgs e)
{
if (!IsLoaded || _isSettingNewLayer || sender is not Button) return;
- var v = grdLayerConfigs.IsVisible;
- grdLayerConfigs.Visibility = v ? Visibility.Hidden : Visibility.Visible;
- grd_LayerControl.IsHitTestVisible = v;
- grd_LayerControl.Effect = v ? null : new BlurEffect();
- btnOverrides.Visibility = v ? Visibility.Visible : Visibility.Collapsed;
+ var v = GrdLayerConfigs.IsVisible;
+ GrdLayerConfigs.Visibility = v ? Visibility.Hidden : Visibility.Visible;
+ GrdLayerControl.IsHitTestVisible = v;
+ GrdLayerControl.Effect = v ? null : new BlurEffect();
+ BtnOverrides.Visibility = v ? Visibility.Visible : Visibility.Collapsed;
}
private void chk_ExcludeMask_Checked(object? sender, RoutedEventArgs e)
@@ -112,16 +134,16 @@ private void sldr_Opacity_ValueChanged(object? sender, RoutedPropertyChangedEven
if (!IsLoaded || _isSettingNewLayer) return;
Layer.Handler._Opacity = (float)e.NewValue / 100.0f;
- lbl_Opacity_Text.Text = $"{(int)e.NewValue} %";
+ LblOpacityText.Text = $"{(int)e.NewValue} %";
}
private void btnOverrides_Click(object? sender, RoutedEventArgs e)
{
if (!IsLoaded || _isSettingNewLayer) return;
- var v = overridesEditor.IsVisible;
- overridesEditor.Visibility = v ? Visibility.Hidden : Visibility.Visible;
- grd_LayerControl.IsHitTestVisible = v;
- btnConfig.Visibility = v ? Visibility.Visible : Visibility.Collapsed;
+ var v = OverridesEditor.IsVisible;
+ OverridesEditor.Visibility = v ? Visibility.Hidden : Visibility.Visible;
+ GrdLayerControl.IsHitTestVisible = v;
+ BtnConfig.Visibility = v ? Visibility.Visible : Visibility.Collapsed;
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/AmbilightLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/AmbilightLayerHandler.cs
index c75639ac4..a20ab418e 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/AmbilightLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/AmbilightLayerHandler.cs
@@ -211,7 +211,7 @@ public override void Default()
[LogicOverrideIgnoreProperty("SecondaryColor")]
[LogicOverrideIgnoreProperty("_Sequence")]
[DoNotNotify]
-public sealed class AmbilightLayerHandler : LayerHandler
+public sealed class AmbilightLayerHandler : LayerHandler
{
private readonly Temporary _screenCapture;
@@ -258,7 +258,7 @@ public AmbilightLayerHandler() : base("Ambilight Layer")
public override EffectLayer Render(IGameState gameState)
{
if (Properties.Sequence.GetAffectedRegion().IsEmpty)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
if (_captureWorker.WaitingCallbacks < 1)
{
@@ -326,6 +326,11 @@ protected override UserControl CreateControl()
return new Control_AmbilightLayer(this);
}
+ public override bool HighResource()
+ {
+ return true;
+ }
+
private object? TakeScreenshot(object? sender)
{
try
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/AnimationLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/AnimationLayerHandler.cs
index 8550a92b3..e5916bd83 100755
--- a/Project-Aurora/Project-Aurora/Settings/Layers/AnimationLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/AnimationLayerHandler.cs
@@ -100,7 +100,7 @@ public override void Default() {
[LogicOverrideIgnoreProperty("PrimaryColor")]
[LogicOverrideIgnoreProperty("SecondaryColor")]
- public sealed class AnimationLayerHandler() : LayerHandler("Animation Layer")
+ public sealed class AnimationLayerHandler() : LayerHandler("Animation Layer")
{
private readonly List _runningAnimations = [];
private readonly Stopwatch _animTimeStopwatch = new();
@@ -122,6 +122,11 @@ protected override UserControl CreateControl() {
return new Control_AnimationLayer(this);
}
+ public override bool HighResource()
+ {
+ return true;
+ }
+
public override void Dispose()
{
InputsModule.InputEvents.Result.KeyDown -= InputEvents_KeyDown;
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/DefaultLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/DefaultLayerHandler.cs
index 2132577f2..e2945aa8a 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/DefaultLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/DefaultLayerHandler.cs
@@ -1,20 +1,20 @@
using System.Windows.Controls;
+using AuroraRgb.EffectsEngine;
using AuroraRgb.Profiles;
using AuroraRgb.Settings.Layers.Controls;
using AuroraRgb.Settings.Overrides;
-namespace AuroraRgb.Settings.Layers
+namespace AuroraRgb.Settings.Layers;
+
+[LogicOverrideIgnoreProperty("_PrimaryColor")]
+[LogicOverrideIgnoreProperty("_Opacity")]
+[LogicOverrideIgnoreProperty("_Enabled")]
+[LogicOverrideIgnoreProperty("_Sequence")]
+[LayerHandlerMeta(Order = -1, IsDefault = true)]
+public class DefaultLayerHandler : LayerHandler
{
- [LogicOverrideIgnoreProperty("_PrimaryColor")]
- [LogicOverrideIgnoreProperty("_Opacity")]
- [LogicOverrideIgnoreProperty("_Enabled")]
- [LogicOverrideIgnoreProperty("_Sequence")]
- [LayerHandlerMeta(Order = -1, IsDefault = true)]
- public class DefaultLayerHandler : LayerHandler
+ protected override UserControl CreateControl()
{
- protected override UserControl CreateControl()
- {
- return new Control_DefaultLayer();
- }
+ return new Control_DefaultLayer();
}
-}
+}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/EqualizerLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/EqualizerLayerHandler.cs
index fedc79a80..3085eaa4e 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/EqualizerLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/EqualizerLayerHandler.cs
@@ -17,6 +17,7 @@
using NAudio.Dsp;
using NAudio.Wave;
using Newtonsoft.Json;
+using Complex = NAudio.Dsp.Complex;
namespace AuroraRgb.Settings.Layers;
@@ -192,7 +193,7 @@ public override void Default()
}
[LayerHandlerMeta(Name = "Audio Visualizer", IsDefault = true)]
-public sealed class EqualizerLayerHandler : LayerHandler
+public sealed class EqualizerLayerHandler : LayerHandler
{
public event NewLayerRendered? NewLayerRender = delegate { };
@@ -238,7 +239,6 @@ public EqualizerLayerHandler(): base("EqualizerLayer")
_ffts = new Complex[FftLength];
_sampleAggregator.FftCalculated += FftCalculated;
- _sampleAggregator.PerformFft = true;
_deviceProxy = new Temporary(() =>
{
@@ -265,7 +265,7 @@ protected override UserControl CreateControl()
}
public override EffectLayer Render(IGameState gamestate)
{
- if (_disposed) return EffectLayer.EmptyLayer;
+ if (_disposed) return EmptyLayer.Instance;
var deviceProxy = _deviceProxy.Value;
var deviceProxyFlow = Properties.DeviceFlow switch
@@ -277,7 +277,7 @@ public override EffectLayer Render(IGameState gamestate)
deviceProxy.DeviceId = Properties.DeviceId;
if (deviceProxy.Device == null)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
// The system sound as a value between 0.0 and 1.0
var systemSoundNormalized = deviceProxy.Device?.AudioMeterInformation?.MasterPeakValue ?? 1f;
@@ -295,6 +295,14 @@ public override EffectLayer Render(IGameState gamestate)
var localFft = _ffts;
+ // do transformations before using them
+ for (var position = 0; position < localFft.Length; position++)
+ {
+ var complex = localFft[position];
+ var val = complex.X;
+ complex.X = val * (float)FastFourierTransform.HannWindow(position, localFft.Length);
+ }
+
var bgEnabled = false;
switch (Properties.BackgroundMode)
{
@@ -418,17 +426,20 @@ private void OnDataAvailable(object? sender, WaveInEventArgs e)
var fftIndexRatio = (double)FftLength / bufferCount;
var buffer = waveBuffer.FloatBuffer;
- for (var freq = 0; freq < bufferCount; freq += _channels)
+ for (var freqPlusChannel = 0; freqPlusChannel < bufferCount; freqPlusChannel += _channels)
{
- var fftIndex = (int)Math.Floor(freq * fftIndexRatio);
-
- var max = 0d;
- for (var c = 0; c < _channels; c++)
+ var max = 0f;
+ var nextFreq = freqPlusChannel + _channels;
+
+ for (var i = freqPlusChannel; i < nextFreq; i++)
{
- max = Math.Max(max, buffer[freq + c]);
+ max = Math.Max(max, buffer[i]);
}
+
+ var fftIndex = (int)Math.Floor(freqPlusChannel * fftIndexRatio);
_sampleAggregator.Add(max, fftIndex);
}
+ waveBuffer.Clear();
_sampleAggregator.Complete();
}
@@ -513,23 +524,23 @@ public override void Dispose()
public class SampleAggregator
{
+ private readonly int _fftLength;
+
// FFT
public event EventHandler? FftCalculated;
- public bool PerformFft { get; set; }
// This Complex is NAudio's own!
private readonly Complex[] _fftBuffer;
private readonly FftEventArgs _fftArgs;
- private readonly int _fftLength;
public SampleAggregator(int fftLength)
{
+ _fftLength = fftLength;
if (!IsPowerOfTwo(fftLength))
{
throw new ArgumentException("FFT Length must be a power of two");
}
- _fftLength = fftLength;
_fftBuffer = new Complex[fftLength];
_fftArgs = new FftEventArgs(_fftBuffer);
}
@@ -539,16 +550,20 @@ private bool IsPowerOfTwo(int x)
return (x & (x - 1)) == 0;
}
- public void Add(double value, int position)
+ public void Add(float value, int position)
{
- if (!PerformFft || FftCalculated == null) return;
+ if (FftCalculated == null) return;
// Remember the window function! There are many others as well.
- if (float.IsNaN(_fftBuffer[position].X))
+ var p = _fftBuffer[position];
+ if (float.IsNaN(p.X))
{
- _fftBuffer[position].X = 0;
+ p.X = 0;
}
- _fftBuffer[position].X = Math.Max(_fftBuffer[position].X, (float)(value * FastFourierTransform.HannWindow(position, _fftLength)));
- _fftBuffer[position].Y = 0; // This is always zero with audio.
+
+ // just save the max value. Transformations will be done when they are needed
+ p.X = Math.Max(p.X, value);
+ p.Y = 0; // This is always zero with audio.
+ _fftBuffer[position] = p;
}
public void Complete()
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/GlitchLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/GlitchLayerHandler.cs
index 78292224d..afc6f148c 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/GlitchLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/GlitchLayerHandler.cs
@@ -91,7 +91,6 @@ protected override void PropertiesChanged(object? sender, PropertyChangedEventAr
{
base.PropertiesChanged(sender, args);
_glitchColors.Clear();
- EffectLayer.Invalidate();
}
}
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/GradientLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/GradientLayerHandler.cs
index c7de3e87b..73a3c6ff1 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/GradientLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/GradientLayerHandler.cs
@@ -37,9 +37,9 @@ private static LayerEffectConfig DefaultGradientConfig()
[LogicOverrideIgnoreProperty("_PrimaryColor")]
[LogicOverrideIgnoreProperty("SecondaryColor")]
-public class GradientLayerHandler : LayerHandler
+public class GradientLayerHandler : LayerHandler
{
- private readonly EffectLayer _tempLayerBitmap = new("GradientLayer - Colors", true);
+ private readonly BitmapEffectLayer _tempLayerWrapped = new("GradientLayer - Colors", true);
private readonly Action _gradientRenderFunc;
public GradientLayerHandler(): base("GradientLayer")
@@ -47,7 +47,7 @@ public GradientLayerHandler(): base("GradientLayer")
Properties.PropertyChanged += PropertiesChanged;
_gradientRenderFunc = g =>
{
- g.DrawRectangle(_tempLayerBitmap, _tempLayerBitmap.Dimension);
+ g.DrawRectangle(_tempLayerWrapped);
};
}
@@ -75,7 +75,7 @@ public override EffectLayer Render(IGameState gameState)
}
else
{
- _tempLayerBitmap.DrawGradient(LayerEffects.GradientShift_Custom_Angle, Properties.GradientConfig);
+ _tempLayerWrapped.DrawGradient(LayerEffects.GradientShift_Custom_Angle, Properties.GradientConfig);
EffectLayer.Clear();
EffectLayer.DrawTransformed(
Properties.Sequence,
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ILayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ILayerHandler.cs
index 6ce542bb9..dd0de60e1 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ILayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ILayerHandler.cs
@@ -27,4 +27,7 @@ public interface ILayerHandler: IDisposable
void SetApplication(Application profile);
void SetGameState(IGameState gamestate);
+
+ Type GetEffectLayerType();
+ bool HighResource();
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ImageLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ImageLayerHandler.cs
index 79d45e0a0..bddf04e11 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ImageLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ImageLayerHandler.cs
@@ -30,7 +30,7 @@ public override void Default()
[LogicOverrideIgnoreProperty("_PrimaryColor")]
[LogicOverrideIgnoreProperty("SecondaryColor")]
-public class ImageLayerHandler() : LayerHandler("ImageLayer")
+public class ImageLayerHandler() : LayerHandler("ImageLayer")
{
private Image? _loadedImage;
private string? _loadedImagePath = "";
@@ -42,13 +42,13 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gamestate)
{
- if (string.IsNullOrWhiteSpace(Properties.ImagePath)) return EffectLayer.EmptyLayer;
+ if (string.IsNullOrWhiteSpace(Properties.ImagePath)) return EmptyLayer.Instance;
if (_loadedImagePath != Properties.ImagePath)
{
//Not loaded, load it!
if (!File.Exists(Properties.ImagePath))
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
_loadedImage?.Dispose();
_loadedImage = new Bitmap(Properties.ImagePath);
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/InteractiveLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/InteractiveLayerHandler.cs
index a1da8a5ac..f4cd58fb2 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/InteractiveLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/InteractiveLayerHandler.cs
@@ -137,7 +137,7 @@ public override void Default()
}
}
-public sealed class InteractiveLayerHandler : LayerHandler
+public sealed class InteractiveLayerHandler : LayerHandler
{
private readonly Func, bool> _keysToRemove;
private readonly ConcurrentDictionary _inputDictionary = new(new Dictionary(Effects.MaxDeviceId));
@@ -349,7 +349,7 @@ public override EffectLayer Render(IGameState gamestate)
if (_inputDictionary.Values.Count == 0)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
EffectLayer.Clear();
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/Layer.cs b/Project-Aurora/Project-Aurora/Settings/Layers/Layer.cs
index c018b794a..d920b9985 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/Layer.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/Layer.cs
@@ -93,7 +93,7 @@ public EffectLayer Render(IGameState gs)
}
if (!Handler.Properties.Enabled)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
try
{
var effectLayer = Handler.PostRenderFX(Handler.Render(gs));
@@ -110,12 +110,12 @@ public EffectLayer Render(IGameState gs)
var controlInterface = appAuroraApp.ControlInterface;
controlInterface.ShowErrorNotification($"Layer \'{Name}\" fails to render. Check logs for details");
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
Global.logger.Error(e, "Layer render error");
}
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
public void SetProfile(Application profile) {
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/LayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/LayerHandler.cs
index 3e99273b8..aff21fc21 100755
--- a/Project-Aurora/Project-Aurora/Settings/Layers/LayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/LayerHandler.cs
@@ -16,10 +16,12 @@
namespace AuroraRgb.Settings.Layers;
[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
-public abstract class LayerHandler : ILayerHandler where TProperty : LayerHandlerProperties
+public abstract class LayerHandler : ILayerHandler
+ where TProperty : LayerHandlerProperties
+ where LayerType : EffectLayer
{
private readonly Temporary> _control;
-
+
[JsonIgnore]
public Application Application { get; protected set; }
@@ -70,7 +72,7 @@ public double? _Opacity {
private readonly Temporary _effectLayer;
private static readonly PropertyChangedEventArgs ConstPropertyChangedEventArgs = new("");
- protected EffectLayer EffectLayer
+ protected LayerType EffectLayer
{
get
{
@@ -79,7 +81,7 @@ protected EffectLayer EffectLayer
var _ = _effectLayer.Value;
PropertiesChanged(this, ConstPropertyChangedEventArgs);
}
- return _effectLayer.Value;
+ return (LayerType)_effectLayer.Value;
}
}
@@ -89,7 +91,7 @@ protected LayerHandler(): this("Unoptimized Layer"){}
protected LayerHandler(string name)
{
- _effectLayer = new(() => new EffectLayer(name, true));
+ _effectLayer = new(() => CreateLayer(name));
_ExclusionMask = new KeySequence();
Properties.PropertyChanged += PropertiesChanged;
WeakEventManager.AddHandler(null, nameof(Effects.CanvasChanged), PropertiesChanged);
@@ -97,9 +99,23 @@ protected LayerHandler(string name)
_control = new Temporary>(CreateControlOnMain, false);
}
+ private EffectLayer CreateLayer(string name)
+ {
+ if (typeof(LayerType) == typeof(BitmapEffectLayer))
+ {
+ return new BitmapEffectLayer(name, true);
+ }
+ if (typeof(LayerType) == typeof(NoRenderLayer))
+ {
+ return new NoRenderLayer();
+ }
+
+ throw new NotImplementedException();
+ }
+
public virtual EffectLayer Render(IGameState gameState)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
public virtual void SetGameState(IGameState gamestate)
@@ -107,13 +123,22 @@ public virtual void SetGameState(IGameState gamestate)
}
- public EffectLayer PostRenderFX(EffectLayer renderedLayer)
+ public Type GetEffectLayerType()
{
+ return typeof(LayerType);
+ }
+
+ public virtual bool HighResource()
+ {
+ return false;
+ }
+ public EffectLayer PostRenderFX(EffectLayer renderedLayer)
+ {
//Last PostFX is exclusion
renderedLayer.Exclude(EnableExclusionMask ? ExclusionMask : KeySequence.Empty);
- renderedLayer *= Properties.LayerOpacity;
+ renderedLayer.SetOpacity(Properties.LayerOpacity);
return renderedLayer;
}
@@ -187,4 +212,8 @@ public virtual void Dispose()
}
[LayerHandlerMeta(Exclude = true)]
-public abstract class LayerHandler(string name) : LayerHandler(name);
\ No newline at end of file
+public abstract class LayerHandler(string name) : LayerHandler(name);
+
+[LayerHandlerMeta(Exclude = true)]
+public abstract class LayerHandler(string name) : LayerHandler(name)
+ where Props : LayerHandlerProperties;
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/LogitechLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/LogitechLayerHandler.cs
index cc7ea90c9..a7a121995 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/LogitechLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/LogitechLayerHandler.cs
@@ -71,8 +71,6 @@ public override void Default()
[LayerHandlerMeta(Name = "Logitech Lightsync", IsDefault = true)]
public sealed class LogitechLayerHandler : LayerHandler
{
- private readonly SingleColorBrush _background = new(SimpleColor.Transparent);
-
public LogitechLayerHandler() : base("Logitech Layer")
{
LogitechSdkModule.LogitechSdkListener.ColorsUpdated += LogitechSdkListenerOnColorsUpdated;
@@ -88,12 +86,12 @@ private void LogitechSdkListenerOnColorsUpdated(object? sender, EventArgs e)
Invalidated = true;
}
- public override EffectLayer Render(IGameState gamestate)
+ public override EffectLayer Render(IGameState gameState)
{
var logitechSdk = LogitechSdkModule.LogitechSdkListener;
if (logitechSdk.State != LightsyncSdkState.Connected)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
if (!Invalidated)
@@ -101,8 +99,7 @@ public override EffectLayer Render(IGameState gamestate)
return EffectLayer;
}
- _background.Color = logitechSdk.BackgroundColor;
- EffectLayer.Fill(_background);
+ EffectLayer.Fill((Color)logitechSdk.BackgroundColor);
foreach (var kv in logitechSdk.Colors)
{
var color = Properties.ColorPostProcessEnabled ? PostProcessColor(kv.Value) : kv.Value;
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ParticleLayerHandlerBase.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ParticleLayerHandlerBase.cs
index 516d9bbc4..badd77ccc 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ParticleLayerHandlerBase.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ParticleLayerHandlerBase.cs
@@ -40,7 +40,7 @@ public override void Default() {
///
///
///
- public abstract class ParticleLayerHandlerBase : LayerHandler, INotifyRender
+ public abstract class ParticleLayerHandlerBase : LayerHandler, INotifyRender
where TParticle : IParticle
where TProperties : ParticleLayerPropertiesBase {
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/PercentGradientLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/PercentGradientLayerHandler.cs
index 2dea9628e..1cdc9ee63 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/PercentGradientLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/PercentGradientLayerHandler.cs
@@ -31,7 +31,6 @@ public override void Default()
[LayerHandlerMeta(Name = "Percent (Gradient)", IsDefault = true)]
public class PercentGradientLayerHandler : PercentLayerHandler
{
-
protected override UserControl CreateControl()
{
return new Control_PercentGradientLayer(this);
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/PercentLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/PercentLayerHandler.cs
index a4a43814d..c6331acf7 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/PercentLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/PercentLayerHandler.cs
@@ -1,4 +1,6 @@
-using System.Globalization;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
using System.Windows.Controls;
using AuroraRgb.EffectsEngine;
using AuroraRgb.Profiles;
@@ -84,29 +86,45 @@ public override void Default()
}
}
-public class PercentLayerHandler() : LayerHandler("PercentLayer")
+public class PercentLayerHandler() : LayerHandler("PercentLayer")
where TProperty : PercentLayerHandlerProperties
{
private double _value;
- public override EffectLayer Render(IGameState state)
+ private readonly NoRenderLayer NoRenderLayer = new();
+
+ public override EffectLayer Render(IGameState gameState)
{
+ var keySequence = Properties.Sequence;
+ EffectLayer layer = keySequence.Type switch
+ {
+ KeySequenceType.Sequence => NoRenderLayer,
+ _ => EffectLayer,
+ };
+
+
if (Invalidated)
{
- EffectLayer.Clear();
+ layer.Clear();
Invalidated = false;
_value = -1;
}
- var value = Properties.Logic?._Value ?? state.GetNumber(Properties.VariablePath);
+ var value = Properties.Logic?._Value ?? gameState.GetNumber(Properties.VariablePath);
if (MathUtils.NearlyEqual(_value, value, 0.000001))
{
- return EffectLayer;
+ return layer;
}
_value = value;
- var maxvalue = Properties.Logic?._MaxValue ?? state.GetNumber(Properties.MaxVariablePath);
+ var maxvalue = Properties.Logic?._MaxValue ?? gameState.GetNumber(Properties.MaxVariablePath);
- EffectLayer.PercentEffect(Properties.PrimaryColor, Properties.SecondaryColor, Properties.Sequence, value, maxvalue,
+ if (keySequence.Type == KeySequenceType.Sequence)
+ {
+ NoRenderLayer.PercentEffect(Properties.PrimaryColor, Properties.SecondaryColor, keySequence.Keys, value, maxvalue,
+ Properties.PercentType, Properties.BlinkThreshold, Properties.BlinkDirection, Properties.BlinkBackground);
+ return NoRenderLayer;
+ }
+ EffectLayer.PercentEffect(Properties.PrimaryColor, Properties.SecondaryColor, keySequence, value, maxvalue,
Properties.PercentType, Properties.BlinkThreshold, Properties.BlinkDirection, Properties.BlinkBackground);
return EffectLayer;
}
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/RadialLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/RadialLayerHandler.cs
index f0e5b8956..e7fd5fffb 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/RadialLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/RadialLayerHandler.cs
@@ -37,7 +37,7 @@ public override void Default() {
}
}
-public class RadialLayerHandler() : LayerHandler("RadialLayer")
+public class RadialLayerHandler() : LayerHandler("RadialLayer")
{
private readonly Stopwatch _sw = new();
private float _angle;
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/RazerLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/RazerLayerHandler.cs
index 8dc0ae6f4..e16b04b44 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/RazerLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/RazerLayerHandler.cs
@@ -95,7 +95,7 @@ public override EffectLayer Render(IGameState gamestate)
{
if (!RzHelper.IsCurrentAppValid())
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
if (RzHelper.IsStale())
return EffectLayer;
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ScriptLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ScriptLayerHandler.cs
index 9ba999171..3da8ce798 100755
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ScriptLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ScriptLayerHandler.cs
@@ -46,7 +46,7 @@ public override void Default()
[LogicOverrideIgnoreProperty("_PrimaryColor")]
[LogicOverrideIgnoreProperty("_Sequence")]
-public class ScriptLayerHandler : LayerHandler, INotifyPropertyChanged
+public class ScriptLayerHandler : LayerHandler, INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
@@ -56,7 +56,7 @@ public class ScriptLayerHandler : LayerHandler, IN
public override EffectLayer Render(IGameState gamestate)
{
- if (!IsScriptValid) return EffectLayer.EmptyLayer;
+ if (!IsScriptValid) return EmptyLayer.Instance;
try
{
var script = Application.EffectScripts[Properties.Script];
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ShortcutAssistantLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ShortcutAssistantLayerHandler.cs
index 569515cdf..650c712c9 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ShortcutAssistantLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ShortcutAssistantLayerHandler.cs
@@ -216,7 +216,7 @@ public override EffectLayer Render(IGameState gamestate)
{
if (!IsLayerActive(out var heldKeys))
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
// The layer is active. At this point we have at least 1 key to highlight
@@ -225,7 +225,7 @@ public override EffectLayer Render(IGameState gamestate)
var currentShortcutNode = Properties.ShortcutKeysTree.GetNodeByPath(heldKeysToHighlight);
if (currentShortcutNode == null)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
if (Properties.LeafShortcutAlwaysOn.GetValueOrDefault(false) && currentShortcutNode.IsLeaf)
{
@@ -233,7 +233,7 @@ public override EffectLayer Render(IGameState gamestate)
currentShortcutNode = Properties.ShortcutKeysTree.GetNodeByPath(heldKeysToHighlight.Take(heldKeysToHighlight.Length - 1).ToArray());
if (currentShortcutNode == null)
{
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
}
}
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/SolidColorLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/SolidColorLayerHandler.cs
index 1639eaa3f..a902f8beb 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/SolidColorLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/SolidColorLayerHandler.cs
@@ -10,7 +10,6 @@ namespace AuroraRgb.Settings.Layers;
public class SolidColorLayerHandler() : LayerHandler("SolidColorLayer")
{
- private readonly SingleColorBrush _brush = new();
private KeySequence _propertiesSequence = new();
protected override UserControl CreateControl()
@@ -20,22 +19,13 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- EffectLayer.Set(_propertiesSequence, _brush);
+ EffectLayer.Set(_propertiesSequence, Properties.PrimaryColor);
return EffectLayer;
}
protected override void PropertiesChanged(object? sender, PropertyChangedEventArgs args)
{
base.PropertiesChanged(sender, args);
- _brush.Color = (SimpleColor)Properties.PrimaryColor;
_propertiesSequence = Properties.Sequence;
- EffectLayer.Invalidate();
- }
-
- public override void Dispose()
- {
- base.Dispose();
-
- _brush.Dispose();
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/SolidFillLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/SolidFillLayerHandler.cs
index 815152d75..f14201a4e 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/SolidFillLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/SolidFillLayerHandler.cs
@@ -20,10 +20,8 @@ public override void Default()
}
[LogicOverrideIgnoreProperty("_Sequence")]
-public sealed class SolidFillLayerHandler : LayerHandler
+public sealed class SolidFillLayerHandler() : LayerHandler("SolidFillLayerHandler")
{
- private readonly SingleColorBrush _solidBrush = new(SimpleColor.Transparent);
-
protected override UserControl CreateControl()
{
return new Control_SolidFillLayer(this);
@@ -31,8 +29,7 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gameState)
{
- _solidBrush.Color = (SimpleColor)Properties.PrimaryColor;
- EffectLayer.Set(Effects.Canvas.EntireSequence, _solidBrush);
+ EffectLayer.Fill(Properties.PrimaryColor);
return EffectLayer;
}
}
\ No newline at end of file
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/TimerLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/TimerLayerHandler.cs
index 771826f61..64fea3c77 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/TimerLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/TimerLayerHandler.cs
@@ -60,7 +60,7 @@ public override void Default() {
}
}
-public class TimerLayerHandler : LayerHandler {
+public class TimerLayerHandler : LayerHandler {
private readonly CustomTimer _timer;
private bool _isActive;
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/ToggleKeyLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/ToggleKeyLayerHandler.cs
index a908a0de0..414dff60c 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/ToggleKeyLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/ToggleKeyLayerHandler.cs
@@ -28,17 +28,9 @@ public override void Default() {
}
}
-public sealed class ToggleKeyLayerHandler : LayerHandler
+public sealed class ToggleKeyLayerHandler() : LayerHandler("ToggleKeyLayer")
{
private bool _state = true;
- private readonly SingleColorBrush _primaryBrush;
- private readonly SingleColorBrush _secondaryBrush;
-
- public ToggleKeyLayerHandler(): base("ToggleKeyLayer")
- {
- _primaryBrush = new SingleColorBrush((SimpleColor)Properties.PrimaryColor);
- _secondaryBrush = new SingleColorBrush((SimpleColor)Properties.SecondaryColor);
- }
protected override async Task Initialize()
{
@@ -50,8 +42,6 @@ protected override async Task Initialize()
public override void Dispose()
{
InputsModule.InputEvents.Result.KeyDown -= InputEvents_KeyDown;
- _primaryBrush.Dispose();
- _secondaryBrush.Dispose();
base.Dispose();
}
@@ -67,18 +57,10 @@ public override EffectLayer Render(IGameState gameState)
EffectLayer.Clear();
Invalidated = false;
}
- EffectLayer.Set(Properties.Sequence, _state ? _primaryBrush : _secondaryBrush);
+ EffectLayer.Set(Properties.Sequence, _state ? Properties.PrimaryColor : Properties.SecondaryColor);
return EffectLayer;
}
- protected override void PropertiesChanged(object? sender, PropertyChangedEventArgs args)
- {
- base.PropertiesChanged(sender, args);
-
- _primaryBrush.Color = (SimpleColor)Properties.PrimaryColor;
- _secondaryBrush.Color = (SimpleColor)Properties.SecondaryColor;
- }
-
private void InputEvents_KeyDown(object? sender, EventArgs e)
{
foreach (var kb in Properties.TriggerKeys)
diff --git a/Project-Aurora/Project-Aurora/Settings/Layers/WrapperLightsLayerHandler.cs b/Project-Aurora/Project-Aurora/Settings/Layers/WrapperLightsLayerHandler.cs
index 5791023ef..5aec00ccc 100644
--- a/Project-Aurora/Project-Aurora/Settings/Layers/WrapperLightsLayerHandler.cs
+++ b/Project-Aurora/Project-Aurora/Settings/Layers/WrapperLightsLayerHandler.cs
@@ -93,7 +93,6 @@ public class WrapperLightsLayerHandler() : LayerHandler _extraKeys = new();
private Color _lastFillColor = Color.Black;
private EntireEffect? _currentEffect;
- private readonly SingleColorBrush _fillBrush = new(SimpleColor.Transparent);
protected override UserControl CreateControl()
{
@@ -103,10 +102,9 @@ protected override UserControl CreateControl()
public override EffectLayer Render(IGameState gamestate)
{
if (gamestate is not GameState_Wrapper)
- return EffectLayer.EmptyLayer;
+ return EmptyLayer.Instance;
- _fillBrush.Color = (SimpleColor)GetBoostedColor(_lastFillColor);
- EffectLayer.Fill(_fillBrush);
+ EffectLayer.Fill(GetBoostedColor(_lastFillColor));
var allKeys = Enum.GetValues(typeof(DeviceKeys)).Cast().ToArray();
foreach (var key in allKeys)
diff --git a/Project-Aurora/Project-Aurora/Utils/ColorUtils.cs b/Project-Aurora/Project-Aurora/Utils/ColorUtils.cs
index 60a49e650..8b748574a 100644
--- a/Project-Aurora/Project-Aurora/Utils/ColorUtils.cs
+++ b/Project-Aurora/Project-Aurora/Utils/ColorUtils.cs
@@ -37,8 +37,6 @@ public static DrawingColor Clone(this DrawingColor clr)
///
public static class ColorUtils
{
- private static readonly Random Randomizer = new();
-
///
/// Converts from System.Windows.Media.Color to System.Drawing.Color
///
@@ -98,7 +96,7 @@ public static DrawingColor GetAverageColor(BitmapSource bitmap)
return CommonColorUtils.FastColor((byte)(red / numPixels), (byte)(green / numPixels), (byte)(blue / numPixels));
}
- public static DrawingColor BlendColors(DrawingColor background, DrawingColor foreground, double percent)
+ public static DrawingColor BlendColors(in DrawingColor background, DrawingColor foreground, double percent)
{
return CommonColorUtils.BlendColors(background, foreground, percent);
}
diff --git a/Project-Aurora/Project-Aurora/Vorons/PerfEffect.cs b/Project-Aurora/Project-Aurora/Vorons/PerfEffect.cs
index f953c7bd5..e51bbe12c 100644
--- a/Project-Aurora/Project-Aurora/Vorons/PerfEffect.cs
+++ b/Project-Aurora/Project-Aurora/Vorons/PerfEffect.cs
@@ -119,7 +119,7 @@ public PerformanceEffect()
Properties.RegProp("Cycled Gradient Shift Full Speed", 100L, "Cycled gradient shifting speed at 100%", -1000L, 1000L);
- _effectLayer = new EffectLayer(ID, true);
+ _effectLayer = new BitmapEffectLayer(ID, true);
}
private static readonly MathParser MathParser = new();
@@ -132,7 +132,7 @@ public PerformanceEffect()
private static readonly ConcurrentDictionary
CircleShidtStates = new();
- private readonly EffectLayer _effectLayer;
+ private readonly BitmapEffectLayer _effectLayer;
private KeySequence Keys { get; set; }
private EffectTypes EffectType { get; set; }
diff --git a/Project-Aurora/Project-Aurora/Vorons/PingEffect.cs b/Project-Aurora/Project-Aurora/Vorons/PingEffect.cs
index 10e343925..fdb226de8 100644
--- a/Project-Aurora/Project-Aurora/Vorons/PingEffect.cs
+++ b/Project-Aurora/Project-Aurora/Vorons/PingEffect.cs
@@ -95,13 +95,13 @@ public PingEffect()
Properties.RegProp("Number of Pings in graph mode", 10L, "Amount of last pings that will be used to display graph.", 1, 50);
//Properties.RegProp("BrightMode", false);
- _layer = new EffectLayer(ID, true);
+ _layer = new BitmapEffectLayer(ID, true);
}
private static readonly ConcurrentDictionary, KeyValuePair> PingAnimations = new();
private static readonly ConcurrentDictionary Gradients = new();
- private readonly EffectLayer _layer;
+ private readonly BitmapEffectLayer _layer;
private KeySequence Keys { get; set; }
private EffectTypes EffectType { get; set; }
@@ -184,7 +184,7 @@ public object UpdateLights(VariableRegistry properties, IGameState state = null)
return _layer;
}
- public void Render(EffectLayer effectLayer)
+ public void Render(BitmapEffectLayer effectLayer)
{
// layers | |
// 0.OldReplyPingBar |==========> |
@@ -496,7 +496,7 @@ public void Add(ColorSpectrum spectrum, float gradientStart, float gradientEnd,
}
}
- public void Draw(FreeFormObject freeform, EffectLayer effectLayer)
+ public void Draw(FreeFormObject freeform, BitmapEffectLayer effectLayer)
{
var g = effectLayer.GetGraphics();
var xPos = (float)Math.Round((freeform.X + Effects.Canvas.GridBaselineX) * Effects.Canvas.EditorToCanvasWidth);