// Written in the D programming language. /** Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-. License: $(WEB http://www.gnu.org/licenses/lgpl.html, LGPLv3). Authors: $(WEB zoadian.de, Felix 'Zoadian' Hufnagel) */ module three.primitives.color; import std.typecons; import std.typetuple; import std.conv; struct RedColorComponent(T) { T r; alias r this; this(T t){r=t;} } struct GreenColorComponent(T) { T g; alias g this; this(T t){g=t;} } struct BlueColorComponent(T) { T b; alias b this; this(T t){b=t;} } struct AlphaColorComponent(T) { T a; alias a this; this(T t){a=t;} } /// enum isRedColorComponent(T) = is(typeof(_isRedColorComponent(T.init))); private void _isRedColorComponent(T)(RedColorComponent!(T) t) {} /// enum isGreenColorComponent(T) = is(typeof(_isGreenColorComponent(T.init))); private void _isGreenColorComponent(T)(GreenColorComponent!(T) t) {} /// enum isBlueColorComponent(T) = is(typeof(_isBlueColorComponent(T.init))); private void _isBlueColorComponent(T)(BlueColorComponent!(T) t) {} /// enum isAlphaColorComponent(T) = is(typeof(_isAlphaColorComponent(T.init))); private void _isAlphaColorComponent(T)(AlphaColorComponent!(T) t) {} enum isRGBColorComponent(T) = isRedColorComponent!T || isGreenColorComponent!T || isBlueColorComponent!T; enum isRGBAColorComponent(T) = isRGBColorComponent!T || isAlphaColorComponent!T; enum hasRedColorComponent(T...) = anySatisfy!(isRedColorComponent, T); enum hasGreenColorComponent(T...) = anySatisfy!(isGreenColorComponent, T); enum hasBlueColorComponent(T...) = anySatisfy!(isBlueColorComponent, T); enum hasAlphaColorComponent(T...) = anySatisfy!(isAlphaColorComponent, T); enum isRGB(T...) = T.length == 3 && isRedColorComponent!(T[0]) && isGreenColorComponent!(T[1]) && isBlueColorComponent!(T[2]); enum isRGBA(T...) = T.length == 4 && isRGB!(T[0..3]) && isAlphaColorComponent!(T[3]); enum isARGB(T...) = T.length == 4 && isAlphaColorComponent!(T[3]) && isRGB!(T[0..3]); enum isBGR(T...) = T.length == 3 && isBlueColorComponent!(T[0]) && isGreenColorComponent!(T[1]) && isRedColorComponent!(T[2]); enum isBGRA(T...) = T.length == 4 && isBGR!(T[0..3]) && isAlphaColorComponent!(T[3]); enum isABGR(T...) = T.length == 4 && isAlphaColorComponent!(T[3]) && isBGR!(T[0..3]); alias RGBColorComponents(T) = TypeTuple!(RedColorComponent!T, GreenColorComponent!T, BlueColorComponent!T); alias RGBAColorComponents(T) = TypeTuple!(RGBColorComponents!T, AlphaColorComponent!T); alias ARGBColorComponents(T) = TypeTuple!(AlphaColorComponent!T, RGBColorComponents!T); alias BGRColorComponents(T) = TypeTuple!(BlueColorComponent!T, GreenColorComponent!T, RedColorComponent!T); alias BGRAColorComponents(T) = TypeTuple!(BGRColorComponents!T, AlphaColorComponent!T); alias ABGRColorComponents(T) = TypeTuple!(AlphaColorComponent!T, BGRColorComponents!T); enum isValidColorComponentDefinition(T...) = allSatisfy!(isRGBAColorComponent, T) && NoDuplicates!(T).length == T.length; static assert(isValidColorComponentDefinition!(RGBAColorComponents!float)); private string _genMembers(size_t IDX, N...)() { string ret; foreach(K; N) { ret ~= "alias " ~ K ~ " = _components[" ~ to!string(IDX-1) ~ "];\n"; } return ret; } private mixin template _GenAccessors(size_t IDX, T...) if(T.length > 0) { static if(T.length == 1) { mixin(_genMembers!(IDX, __traits(allMembers, T[0]))()); } else { mixin _GenAccessors!(IDX+1, T[0]); mixin _GenAccessors!(IDX+1, T[1..$]); } } struct Color(COMPONENTS...) if(COMPONENTS.length > 0 && isValidColorComponentDefinition!COMPONENTS) { COMPONENTS _components; this(T...)(T t) { this._components[] = t[]; } mixin _GenAccessors!(0, COMPONENTS); } alias RGBAf = Color!(RGBAColorComponents!float); alias RGBf = Color!(RGBAColorComponents!float);