1 module nudsfml.graphics.color;
2 
3 import std.traits;
4 import std.algorithm;
5 
6 import bindbc.sfml.graphics;
7 
8 struct Color {
9     ubyte r = 0;
10     ubyte g = 0;
11     ubyte b = 0;
12     ubyte a = 255;
13 
14     static immutable Black = Color(0, 0, 0, 255);
15     static immutable White = Color(255, 255, 255, 255);
16     static immutable Red = Color(255, 0, 0, 255);
17     static immutable Green = Color(0, 255, 0,255);
18     static immutable Blue = Color(0, 0, 255,255);
19     static immutable Yellow = Color(255, 255, 0, 255);
20     static immutable Magenta = Color(255, 0, 255, 255);
21     static immutable Cyan = Color(0, 255, 255, 255);
22     static immutable Transparent = Color(0, 0, 0, 0);
23 
24     string toString() const {
25         import std.conv;
26         return "(R: " ~ text(r) ~ " G: " ~ text(g) ~ " B: " ~ text(b) ~ " A: " ~ text(a) ~")";
27     }
28 
29     Color opBinary(string op)(Color otherColor) const
30         if((op == "+") || (op == "-") || (op == "*"))
31     {
32         static if(op == "+")
33         {
34             return Color(cast(ubyte)min(r+otherColor.r, 255),
35                          cast(ubyte)min(g+otherColor.g, 255),
36                          cast(ubyte)min(b+otherColor.b, 255),
37                          cast(ubyte)min(a+otherColor.a, 255));
38         }
39         static if(op == "-")
40         {
41             return Color(cast(ubyte)max(r-otherColor.r, 0),
42                          cast(ubyte)max(g-otherColor.g, 0),
43                          cast(ubyte)max(b-otherColor.b, 0),
44                          cast(ubyte)max(a-otherColor.a, 0));
45         }
46         static if(op == "*")
47         {
48             return Color(cast(ubyte)(r*otherColor.r / 255),
49                          cast(ubyte)(g*otherColor.g / 255),
50                          cast(ubyte)(b*otherColor.b / 255),
51                          cast(ubyte)(a*otherColor.a / 255));
52         }
53     }
54 
55     Color opBinary(string op, E)(E num) const
56         if(isNumeric!(E) && ((op == "*") || (op == "/")))
57     {
58         static if(op == "*")
59         {
60             //actually dividing or multiplying by a negative
61             if(num < 1)
62             {
63                 return Color(cast(ubyte)max(r*num, 0),
64                              cast(ubyte)max(g*num, 0),
65                              cast(ubyte)max(b*num, 0),
66                              cast(ubyte)max(a*num, 0));
67             }
68             else
69             {
70                 return Color(cast(ubyte)min(r*num, 255),
71                              cast(ubyte)min(g*num, 255),
72                              cast(ubyte)min(b*num, 255),
73                              cast(ubyte)min(a*num, 255));
74             }
75         }
76         static if(op == "/")
77         {
78             //actually multiplying or dividing by a negative
79             if(num < 1)
80             {
81                 return Color(cast(ubyte)min(r/num, 255),
82                              cast(ubyte)min(g/num, 255),
83                              cast(ubyte)min(b/num, 255),
84                              cast(ubyte)min(a/num, 255));
85             }
86             else
87             {
88                 return Color(cast(ubyte)max(r/num, 0),
89                              cast(ubyte)max(g/num, 0),
90                              cast(ubyte)max(b/num, 0),
91                              cast(ubyte)max(a/num, 0));
92             }
93         }
94     }
95 
96     ref Color opOpAssign(string op)(Color otherColor)
97         if((op == "+") || (op == "-") || (op == "*"))
98     {
99         static if(op == "+")
100         {
101             r = cast(ubyte)min(r+otherColor.r, 255);
102             g = cast(ubyte)min(g+otherColor.g, 255);
103             b = cast(ubyte)min(b+otherColor.b, 255);
104             a = cast(ubyte)min(a+otherColor.a, 255);
105         }
106         static if(op == "-")
107         {
108             r = cast(ubyte)max(r-otherColor.r, 0);
109             g = cast(ubyte)max(g-otherColor.g, 0);
110             b = cast(ubyte)max(b-otherColor.b, 0);
111             a = cast(ubyte)max(a-otherColor.a, 0);
112         }
113         static if(op == "*")
114         {
115             r = cast(ubyte)(r*otherColor.r / 255);
116             g = cast(ubyte)(g*otherColor.g / 255);
117             b = cast(ubyte)(b*otherColor.b / 255);
118             a = cast(ubyte)(a*otherColor.a / 255);
119         }
120 
121         return this;
122     }
123 
124 ref Color opOpAssign(string op, E)(E num)
125         if(isNumeric!(E) && ((op == "*") || (op == "/")))
126     {
127         static if(op == "*")
128         {
129             //actually dividing or multiplying by a negative
130             if(num < 1)
131             {
132                 r = cast(ubyte)max(r*num, 0);
133                 g = cast(ubyte)max(g*num, 0);
134                 b = cast(ubyte)max(b*num, 0);
135                 a = cast(ubyte)max(a*num, 0);
136             }
137             else
138             {
139                 r = cast(ubyte)min(r*num, 255);
140                 g = cast(ubyte)min(g*num, 255);
141                 b = cast(ubyte)min(b*num, 255);
142                 a = cast(ubyte)min(a*num, 255);
143             }
144 
145             return this;
146         }
147         static if(op == "/")
148         {
149             //actually multiplying or dividing by a negative
150             if( num < 1)
151             {
152                 r = cast(ubyte)min(r/num, 255);
153                 g = cast(ubyte)min(g/num, 255);
154                 b = cast(ubyte)min(b/num, 255);
155                 a = cast(ubyte)min(a/num, 255);
156             }
157             else
158             {
159                 r = cast(ubyte)max(r/num, 0);
160                 g = cast(ubyte)max(g/num, 0);
161                 b = cast(ubyte)max(b/num, 0);
162                 a = cast(ubyte)max(a/num, 0);
163             }
164 
165             return this;
166         }
167     }
168     /**
169      * Overload of the `==` and `!=` operators.
170      *
171      * This operator compares two colors and check if they are equal.
172      *
173      * Params:
174      * otherColor = the Color to be compared with
175      *
176      * Returns: true if colors are equal, false if they are different.
177      */
178     bool opEquals(Color otherColor) const
179     {
180         return ((r == otherColor.r) && (g == otherColor.g) && (b == otherColor.b) && (a == otherColor.a));
181     }
182 
183 
184 }
185 
186 sfColor fromColor(Color color) {
187     sfColor c = sfColor(color.r,
188                         color.g, 
189                         color.b, 
190                         color.a);
191     return c;
192 }