@@ -7,9 +7,10 @@ namespace AssetRipper.TextureDecoder.ColorGenerator;
77
88internal static partial class Program
99{
10- private const string AttributeNamespace = "AssetRipper.TextureDecoder.Attributes" ;
11- private const string OutputNamespace = "AssetRipper.TextureDecoder.Rgb.Formats" ;
12- private const string OutputFolder = "../../../../AssetRipper.TextureDecoder/Rgb/Formats/" ;
10+ private const string RgbNamespace = "AssetRipper.TextureDecoder.Rgb" ;
11+ private const string RgbFolder = "../../../../AssetRipper.TextureDecoder/Rgb/" ;
12+ private const string FormatsNamespace = "AssetRipper.TextureDecoder.Rgb.Formats" ;
13+ private const string FormatsFolder = "../../../../AssetRipper.TextureDecoder/Rgb/Formats/" ;
1314
1415 /// <summary>
1516 /// Name, Type, Red, Blue, Green, Alpha, Fully Utilized
@@ -46,6 +47,10 @@ static void Main()
4647 {
4748 WriteGenericColor ( genericColor ) ;
4849 }
50+ for ( int i = 1 ; i <= 4 ; i ++ )
51+ {
52+ WriteSuperGenericColor ( i ) ;
53+ }
4954 NumericConversionGenerator . Run ( ) ;
5055 Console . WriteLine ( "Done!" ) ;
5156 }
@@ -54,24 +59,32 @@ private static void WriteCustomColor((string, Type, bool, bool, bool, bool, bool
5459 {
5560 ( string name , Type type , bool hasRed , bool hasGreen , bool hasBlue , bool hasAlpha , bool fullyUtilized ) = details ;
5661 Console . WriteLine ( name ) ;
57- using IndentedTextWriter writer = IndentedTextWriterFactory . Create ( OutputFolder , name ) ;
62+ using IndentedTextWriter writer = IndentedTextWriterFactory . Create ( FormatsFolder , name ) ;
5863 WriteCustomColor ( writer , name , type , hasRed , hasGreen , hasBlue , hasAlpha , fullyUtilized ) ;
5964 }
6065
6166 private static void WriteGenericColor ( ( string , bool , bool , bool , bool ) details )
6267 {
6368 ( string name , bool hasRed , bool hasGreen , bool hasBlue , bool hasAlpha ) = details ;
6469 Console . WriteLine ( name ) ;
65- using IndentedTextWriter writer = IndentedTextWriterFactory . Create ( OutputFolder , name ) ;
70+ using IndentedTextWriter writer = IndentedTextWriterFactory . Create ( FormatsFolder , name ) ;
6671 WriteGenericColor ( writer , name , hasRed , hasGreen , hasBlue , hasAlpha ) ;
6772 }
6873
74+ private static void WriteSuperGenericColor ( int channelCount )
75+ {
76+ string name = $ "Color`{ channelCount } ";
77+ Console . WriteLine ( name ) ;
78+ using IndentedTextWriter writer = IndentedTextWriterFactory . Create ( RgbFolder , name ) ;
79+ WriteSuperGenericColor ( writer , channelCount ) ;
80+ }
81+
6982 private static void WriteCustomColor ( IndentedTextWriter writer , string name , Type type , bool hasRed , bool hasGreen , bool hasBlue , bool hasAlpha , bool fullyUtilized )
7083 {
7184 string typeName = CSharpPrimitives . Dictionary [ type ] . LangName ;
7285 writer . WriteGeneratedCodeWarning ( ) ;
7386 writer . WriteLine ( ) ;
74- using ( new Namespace ( writer , OutputNamespace ) )
87+ using ( new Namespace ( writer , FormatsNamespace ) )
7588 {
7689 writer . WriteLine ( $ "public partial struct { name } : IColor<{ typeName } >") ;
7790 using ( new CurlyBrackets ( writer ) )
@@ -129,11 +142,16 @@ private static void WriteToString(IndentedTextWriter writer, bool hasRed, bool h
129142
130143 private static void WriteNonGenericStaticProperties ( IndentedTextWriter writer , bool hasRed , bool hasGreen , bool hasBlue , bool hasAlpha , bool fullyUtilized , string typeName )
131144 {
132- writer . WriteLine ( $ "static bool IColor.HasRedChannel => { hasRed . ToLowerString ( ) } ;") ;
133- writer . WriteLine ( $ "static bool IColor.HasGreenChannel => { hasGreen . ToLowerString ( ) } ;") ;
134- writer . WriteLine ( $ "static bool IColor.HasBlueChannel => { hasBlue . ToLowerString ( ) } ;") ;
135- writer . WriteLine ( $ "static bool IColor.HasAlphaChannel => { hasAlpha . ToLowerString ( ) } ;") ;
136- writer . WriteLine ( $ "static bool IColor.ChannelsAreFullyUtilized => { fullyUtilized . ToLowerString ( ) } ;") ;
145+ WriteNonGenericStaticProperties ( writer , hasRed . ToLowerString ( ) , hasGreen . ToLowerString ( ) , hasBlue . ToLowerString ( ) , hasAlpha . ToLowerString ( ) , fullyUtilized . ToLowerString ( ) , typeName ) ;
146+ }
147+
148+ private static void WriteNonGenericStaticProperties ( IndentedTextWriter writer , string hasRed , string hasGreen , string hasBlue , string hasAlpha , string fullyUtilized , string typeName )
149+ {
150+ writer . WriteLine ( $ "static bool IColor.HasRedChannel => { hasRed } ;") ;
151+ writer . WriteLine ( $ "static bool IColor.HasGreenChannel => { hasGreen } ;") ;
152+ writer . WriteLine ( $ "static bool IColor.HasBlueChannel => { hasBlue } ;") ;
153+ writer . WriteLine ( $ "static bool IColor.HasAlphaChannel => { hasAlpha } ;") ;
154+ writer . WriteLine ( $ "static bool IColor.ChannelsAreFullyUtilized => { fullyUtilized } ;") ;
137155 writer . WriteLine ( $ "static Type IColor.ChannelType => typeof({ typeName } );") ;
138156 }
139157
@@ -205,7 +223,7 @@ private static void WriteGenericColor(IndentedTextWriter writer, string name, bo
205223 writer . WriteGeneratedCodeWarning ( ) ;
206224 writer . WriteLineNoTabs ( ) ;
207225
208- writer . WriteFileScopedNamespace ( OutputNamespace ) ;
226+ writer . WriteFileScopedNamespace ( FormatsNamespace ) ;
209227 writer . WriteLineNoTabs ( ) ;
210228
211229 writer . WriteLine ( $ "public partial struct { name } <T> : IColor<{ name } <T>, T> where T : unmanaged, INumberBase<T>, IMinMaxValue<T>") ;
@@ -234,6 +252,165 @@ private static void WriteGenericColor(IndentedTextWriter writer, string name, bo
234252 }
235253 }
236254
255+ private static void WriteSuperGenericColor ( IndentedTextWriter writer , int channelCount )
256+ {
257+ const string typeName = "TChannelValue" ;
258+ const string minValue = $ "NumericConversion.GetMinimumValueSafe<{ typeName } >()";
259+ const string maxValue = $ "NumericConversion.GetMaximumValueSafe<{ typeName } >()";
260+
261+ string [ ] channelTypeParameters = channelCount switch
262+ {
263+ 1 => [ "TChannel" ] ,
264+ 2 => [ "TChannel1" , "TChannel2" ] ,
265+ 3 => [ "TChannel1" , "TChannel2" , "TChannel3" ] ,
266+ 4 => [ "TChannel1" , "TChannel2" , "TChannel3" , "TChannel4" ] ,
267+ _ => throw new ( ) ,
268+ } ;
269+
270+ string [ ] fieldNames = channelCount switch
271+ {
272+ 1 => [ "value" ] ,
273+ 2 => [ "value1" , "value2" ] ,
274+ 3 => [ "value1" , "value2" , "value3" ] ,
275+ 4 => [ "value1" , "value2" , "value3" , "value4" ] ,
276+ _ => throw new ( ) ,
277+ } ;
278+
279+
280+
281+ writer . WriteGeneratedCodeWarning ( ) ;
282+ writer . WriteLineNoTabs ( ) ;
283+
284+ writer . WriteUsing ( "AssetRipper.TextureDecoder.Rgb.Channels" ) ;
285+ writer . WriteLineNoTabs ( ) ;
286+
287+ writer . WriteFileScopedNamespace ( "AssetRipper.TextureDecoder.Rgb" ) ;
288+ writer . WriteLineNoTabs ( ) ;
289+
290+ string structName ;
291+ {
292+ StringBuilder sb = new ( ) ;
293+ sb . Append ( "Color<" ) ;
294+ sb . Append ( typeName ) ;
295+ for ( int i = 0 ; i < channelTypeParameters . Length ; i ++ )
296+ {
297+ sb . Append ( ", " ) ;
298+ sb . Append ( channelTypeParameters [ i ] ) ;
299+ }
300+ sb . Append ( '>' ) ;
301+ structName = sb . ToString ( ) ;
302+ }
303+
304+ writer . WriteLine ( $ "public partial struct { structName } : IColor<{ structName } , { typeName } >") ;
305+ using ( new Indented ( writer ) )
306+ {
307+ writer . WriteLine ( $ "where { typeName } : unmanaged, INumberBase<{ typeName } >, IMinMaxValue<{ typeName } >") ;
308+ foreach ( string channel in channelTypeParameters )
309+ {
310+ writer . WriteLine ( $ "where { channel } : IChannel") ;
311+ }
312+ }
313+
314+ using ( new CurlyBrackets ( writer ) )
315+ {
316+ foreach ( string fieldName in fieldNames )
317+ {
318+ writer . WriteLine ( $ "private { typeName } { fieldName } ;") ;
319+ }
320+ writer . WriteLineNoTabs ( ) ;
321+
322+ WriteProperty ( writer , 'R' , "Red" , channelTypeParameters , fieldNames , minValue , typeName ) ;
323+ writer . WriteLineNoTabs ( ) ;
324+ WriteProperty ( writer , 'G' , "Green" , channelTypeParameters , fieldNames , minValue , typeName ) ;
325+ writer . WriteLineNoTabs ( ) ;
326+ WriteProperty ( writer , 'B' , "Blue" , channelTypeParameters , fieldNames , minValue , typeName ) ;
327+ writer . WriteLineNoTabs ( ) ;
328+ WriteProperty ( writer , 'A' , "Alpha" , channelTypeParameters , fieldNames , maxValue , typeName ) ;
329+ writer . WriteLineNoTabs ( ) ;
330+
331+ writer . Write ( "public Color(" ) ;
332+ for ( int i = 0 ; i < fieldNames . Length ; i ++ )
333+ {
334+ if ( i != 0 )
335+ {
336+ writer . Write ( ", " ) ;
337+ }
338+
339+ writer . Write ( typeName ) ;
340+ writer . Write ( ' ' ) ;
341+ writer . Write ( fieldNames [ i ] ) ;
342+ }
343+ writer . WriteLine ( ')' ) ;
344+ using ( new CurlyBrackets ( writer ) )
345+ {
346+ foreach ( string fieldName in fieldNames )
347+ {
348+ writer . WriteLine ( $ "this.{ fieldName } = { fieldName } ;") ;
349+ }
350+ }
351+ writer . WriteLineNoTabs ( ) ;
352+ WriteGetChannels ( writer , typeName ) ;
353+ writer . WriteLineNoTabs ( ) ;
354+ WriteSetChannels ( writer , typeName , true , true , true , true ) ;
355+ writer . WriteLineNoTabs ( ) ;
356+ WriteNonGenericStaticProperties (
357+ writer ,
358+ string . Join ( " || " , channelTypeParameters . Select ( c => $ "{ c } .IsRed") ) ,
359+ string . Join ( " || " , channelTypeParameters . Select ( c => $ "{ c } .IsGreen") ) ,
360+ string . Join ( " || " , channelTypeParameters . Select ( c => $ "{ c } .IsBlue") ) ,
361+ string . Join ( " || " , channelTypeParameters . Select ( c => $ "{ c } .IsAlpha") ) ,
362+ string . Join ( " && " , channelTypeParameters . Select ( c => $ "{ c } .FullyUtilized") ) ,
363+ typeName ) ;
364+ writer . WriteLineNoTabs ( ) ;
365+
366+ writer . WriteLine ( $ "public static { structName } Black") ;
367+ using ( new CurlyBrackets ( writer ) )
368+ {
369+ writer . WriteLine ( $ "get => new({ string . Join ( ", " , channelTypeParameters . Select ( c => $ "{ c } .GetBlack<{ typeName } >()") ) } );") ;
370+ }
371+ writer . WriteLineNoTabs ( ) ;
372+
373+ writer . WriteLine ( $ "public static { structName } White") ;
374+ using ( new CurlyBrackets ( writer ) )
375+ {
376+ writer . WriteLine ( $ "get => new({ string . Join ( ", " , channelTypeParameters . Select ( c => $ "{ c } .GetWhite<{ typeName } >()") ) } );") ;
377+ }
378+ writer . WriteLineNoTabs ( ) ;
379+
380+ WriteToString ( writer , true , true , true , true ) ;
381+ }
382+
383+ static void WriteProperty ( IndentedTextWriter writer , char property , string channel , string [ ] channels , string [ ] fields , string defaultValue , string typeName )
384+ {
385+ writer . WriteLine ( $ "public { typeName } { property } ") ;
386+ using ( new CurlyBrackets ( writer ) )
387+ {
388+ writer . WriteLine ( "readonly get" ) ;
389+ using ( new CurlyBrackets ( writer ) )
390+ {
391+ If . Write (
392+ writer ,
393+ Enumerable . Range ( 0 , channels . Length ) . Select ( i => new ValueTuple < string , Action < IndentedTextWriter > ? > ( $ "{ channels [ i ] } .Is{ channel } ", ( writer ) =>
394+ {
395+ writer . WriteLine ( $ "return { channels [ i ] } .Get{ channel } ({ fields [ i ] } );") ;
396+ } ) ) ,
397+ ( writer ) =>
398+ {
399+ writer . WriteLine ( $ "return { defaultValue } ;") ;
400+ } ) ;
401+ }
402+ writer . WriteLine ( "set" ) ;
403+ using ( new CurlyBrackets ( writer ) )
404+ {
405+ for ( int i = 0 ; i < channels . Length ; i ++ )
406+ {
407+ writer . WriteLine ( $ "Channel.SetIf{ channel } <{ channels [ i ] } , { typeName } >(ref { fields [ i ] } , value);") ;
408+ }
409+ }
410+ }
411+ }
412+ }
413+
237414 private static void WriteConstructor ( IndentedTextWriter writer , string declaringTypeName , bool hasRed , bool hasGreen , bool hasBlue , bool hasAlpha , string channelTypeName )
238415 {
239416 writer . Write ( $ "public { declaringTypeName } (") ;
0 commit comments