Skip to content

Commit 07002c7

Browse files
committed
Static properties for black and white
1 parent bed45ee commit 07002c7

7 files changed

Lines changed: 131 additions & 11 deletions

File tree

AssetRipper.TextureDecoder.ColorGenerator/Program.cs

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,22 +137,78 @@ private static void WriteNonGenericStaticProperties(IndentedTextWriter writer, b
137137
writer.WriteLine($"static Type IColor.ChannelType => typeof({typeName});");
138138
}
139139

140+
private static void WriteBlackWhiteStaticProperties(IndentedTextWriter writer, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha, string colorTypeName, string channelTypeName)
141+
{
142+
string minValue = $"NumericConversion.GetMinimumValueSafe<{channelTypeName}>()";
143+
string maxValue = $"NumericConversion.GetMaximumValueSafe<{channelTypeName}>()";
144+
145+
//Black
146+
{
147+
writer.Write($"public static {colorTypeName}<{channelTypeName}> Black => new(");
148+
int rgbCount = CountRGB(hasRed, hasGreen, hasBlue);
149+
for (int i = 0; i < rgbCount; i++)
150+
{
151+
if (i != 0)
152+
{
153+
writer.Write(", ");
154+
}
155+
writer.Write(minValue);
156+
}
157+
if (hasAlpha)
158+
{
159+
if (rgbCount != 0)
160+
{
161+
writer.Write(", ");
162+
}
163+
writer.Write(maxValue);
164+
}
165+
writer.WriteLine(");");
166+
}
167+
168+
//White
169+
if (hasRed || hasGreen || hasBlue)
170+
{
171+
writer.Write($"public static {colorTypeName}<{channelTypeName}> White => new(");
172+
int rgbaCount = CountRGBA(hasRed, hasGreen, hasBlue, hasAlpha);
173+
for (int i = 0; i < rgbaCount; i++)
174+
{
175+
if (i != 0)
176+
{
177+
writer.Write(", ");
178+
}
179+
writer.Write(maxValue);
180+
}
181+
writer.WriteLine(");");
182+
}
183+
else
184+
{
185+
writer.WriteLine($"static {colorTypeName}<{channelTypeName}> IColor<{colorTypeName}<{channelTypeName}>, {channelTypeName}>.White => throw new NotSupportedException();");
186+
}
187+
188+
static int CountRGB(bool hasRed, bool hasGreen, bool hasBlue)
189+
{
190+
return (hasRed ? 1 : 0) + (hasGreen ? 1 : 0) + (hasBlue ? 1 : 0);
191+
}
192+
193+
static int CountRGBA(bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha)
194+
{
195+
return CountRGB(hasRed, hasGreen, hasBlue) + (hasAlpha ? 1 : 0);
196+
}
197+
}
198+
140199
private static void WriteGenericColor(IndentedTextWriter writer, string name, bool hasRed, bool hasGreen, bool hasBlue, bool hasAlpha)
141200
{
142201
const string typeName = "T";
143-
const string minValue = $"NumericConversion.GetMinimumValueSafe<T>()";
144-
const string maxValue = $"NumericConversion.GetMaximumValueSafe<T>()";
202+
const string minValue = "NumericConversion.GetMinimumValueSafe<T>()";
203+
const string maxValue = "NumericConversion.GetMaximumValueSafe<T>()";
145204

146205
writer.WriteGeneratedCodeWarning();
147206
writer.WriteLineNoTabs();
148207

149208
writer.WriteFileScopedNamespace(OutputNamespace);
150209
writer.WriteLineNoTabs();
151210

152-
string constraints = hasRed && hasGreen && hasBlue && hasAlpha
153-
? "unmanaged"
154-
: "unmanaged, INumberBase<T>, IMinMaxValue<T>";
155-
writer.WriteLine($"public partial struct {name}<T> : IColor<{typeName}> where T : {constraints}");
211+
writer.WriteLine($"public partial struct {name}<T> : IColor<{name}<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>");
156212
using (new CurlyBrackets(writer))
157213
{
158214
WriteProperty(writer, hasRed, typeName, 'R', minValue);
@@ -172,6 +228,8 @@ private static void WriteGenericColor(IndentedTextWriter writer, string name, bo
172228
writer.WriteLineNoTabs();
173229
WriteNonGenericStaticProperties(writer, hasRed, hasGreen, hasBlue, hasAlpha, true, typeName);
174230
writer.WriteLineNoTabs();
231+
WriteBlackWhiteStaticProperties(writer, hasRed, hasGreen, hasBlue, hasAlpha, name, typeName);
232+
writer.WriteLineNoTabs();
175233
WriteToString(writer, hasRed, hasGreen, hasBlue, hasAlpha);
176234
}
177235
}

AssetRipper.TextureDecoder/Rgb/Formats/ColorA.g.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AssetRipper.TextureDecoder.Rgb.Formats;
44

5-
public partial struct ColorA<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
5+
public partial struct ColorA<T> : IColor<ColorA<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
66
{
77
public readonly T R
88
{
@@ -49,6 +49,9 @@ public void SetChannels(T r, T g, T b, T a)
4949
static bool IColor.ChannelsAreFullyUtilized => true;
5050
static Type IColor.ChannelType => typeof(T);
5151

52+
public static ColorA<T> Black => new(NumericConversion.GetMaximumValueSafe<T>());
53+
static ColorA<T> IColor<ColorA<T>, T>.White => throw new NotSupportedException();
54+
5255
public override string ToString()
5356
{
5457
return $"{{ A: {A} }}";

AssetRipper.TextureDecoder/Rgb/Formats/ColorR.g.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AssetRipper.TextureDecoder.Rgb.Formats;
44

5-
public partial struct ColorR<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
5+
public partial struct ColorR<T> : IColor<ColorR<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
66
{
77
public T R { get; set; }
88

@@ -49,6 +49,9 @@ public void SetChannels(T r, T g, T b, T a)
4949
static bool IColor.ChannelsAreFullyUtilized => true;
5050
static Type IColor.ChannelType => typeof(T);
5151

52+
public static ColorR<T> Black => new(NumericConversion.GetMinimumValueSafe<T>());
53+
public static ColorR<T> White => new(NumericConversion.GetMaximumValueSafe<T>());
54+
5255
public override string ToString()
5356
{
5457
return $"{{ R: {R} }}";

AssetRipper.TextureDecoder/Rgb/Formats/ColorRG.g.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AssetRipper.TextureDecoder.Rgb.Formats;
44

5-
public partial struct ColorRG<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
5+
public partial struct ColorRG<T> : IColor<ColorRG<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
66
{
77
public T R { get; set; }
88

@@ -47,6 +47,9 @@ public void SetChannels(T r, T g, T b, T a)
4747
static bool IColor.ChannelsAreFullyUtilized => true;
4848
static Type IColor.ChannelType => typeof(T);
4949

50+
public static ColorRG<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>());
51+
public static ColorRG<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
52+
5053
public override string ToString()
5154
{
5255
return $"{{ R: {R}, G: {G} }}";

AssetRipper.TextureDecoder/Rgb/Formats/ColorRGB.g.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AssetRipper.TextureDecoder.Rgb.Formats;
44

5-
public partial struct ColorRGB<T> : IColor<T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
5+
public partial struct ColorRGB<T> : IColor<ColorRGB<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
66
{
77
public T R { get; set; }
88

@@ -45,6 +45,9 @@ public void SetChannels(T r, T g, T b, T a)
4545
static bool IColor.ChannelsAreFullyUtilized => true;
4646
static Type IColor.ChannelType => typeof(T);
4747

48+
public static ColorRGB<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>());
49+
public static ColorRGB<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
50+
4851
public override string ToString()
4952
{
5053
return $"{{ R: {R}, G: {G}, B: {B} }}";

AssetRipper.TextureDecoder/Rgb/Formats/ColorRGBA.g.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace AssetRipper.TextureDecoder.Rgb.Formats;
44

5-
public partial struct ColorRGBA<T> : IColor<T> where T : unmanaged
5+
public partial struct ColorRGBA<T> : IColor<ColorRGBA<T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>
66
{
77
public T R { get; set; }
88

@@ -43,6 +43,9 @@ public void SetChannels(T r, T g, T b, T a)
4343
static bool IColor.ChannelsAreFullyUtilized => true;
4444
static Type IColor.ChannelType => typeof(T);
4545

46+
public static ColorRGBA<T> Black => new(NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMinimumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
47+
public static ColorRGBA<T> White => new(NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>(), NumericConversion.GetMaximumValueSafe<T>());
48+
4649
public override string ToString()
4750
{
4851
return $"{{ R: {R}, G: {G}, B: {B}, A: {A} }}";
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace AssetRipper.TextureDecoder.Rgb;
2+
3+
/// <summary>
4+
/// An <see langword="interface"/> for handling color formats with up to 4 channels.
5+
/// </summary>
6+
/// <remarks>
7+
/// When used as a generic type constraint, the methods and properties get devirtualized by the JIT compiler.
8+
/// This prevents boxing when the implementing type is a <see langword="struct"/>.
9+
/// </remarks>
10+
/// <typeparam name="TSelf">
11+
/// The implementing type.
12+
/// </typeparam>
13+
/// <typeparam name="TChannel">
14+
/// Supported types are:
15+
/// <list type="bullet">
16+
/// <item><see cref="sbyte"/></item>
17+
/// <item><see cref="byte"/></item>
18+
/// <item><see cref="short"/></item>
19+
/// <item><see cref="ushort"/></item>
20+
/// <item><see cref="int"/></item>
21+
/// <item><see cref="uint"/></item>
22+
/// <item><see cref="nint"/></item>
23+
/// <item><see cref="nuint"/></item>
24+
/// <item><see cref="long"/></item>
25+
/// <item><see cref="ulong"/></item>
26+
/// <item><see cref="Int128"/></item>
27+
/// <item><see cref="UInt128"/></item>
28+
/// <item><see cref="Half"/></item>
29+
/// <item><see cref="float"/></item>
30+
/// <item><see cref="NFloat"/></item>
31+
/// <item><see cref="double"/></item>
32+
/// <item><see cref="decimal"/></item>
33+
/// </list>
34+
/// </typeparam>
35+
public interface IColor<TSelf, TChannel> : IColor<TChannel>
36+
where TSelf : unmanaged, IColor<TSelf, TChannel>
37+
where TChannel : unmanaged
38+
{
39+
/// <summary>
40+
/// A black pixel.
41+
/// </summary>
42+
static abstract TSelf Black { get; }
43+
/// <summary>
44+
/// A white pixel.
45+
/// </summary>
46+
static abstract TSelf White { get; }
47+
}

0 commit comments

Comments
 (0)