1 /*
2 GWEN
3 Copyright (c) 2010 Facepunch Studios
4 See license in Gwen.h
5 */
6
7 #include "Gwen/Utility.h"
8 #include "Gwen/Controls/ColorControls.h"
9
10 using namespace Gwen;
11 using namespace Gwen::Controls;
12
13 //Find a place to put these...
HSVToColor(float h,float s,float v)14 Color HSVToColor(float h, float s, float v)
15 {
16 if (h < 0.0f) h += 360.0f;
17 if (h > 360.0f) h -= 360.0f;
18
19 s *= 255.0f;
20 v *= 255.0f;
21
22 float r, g, b;
23
24 if (!h && !s)
25 {
26 r = g = b = v;
27 }
28 double min, max, delta, hue;
29
30 max = v;
31 delta = (max * s) / 255.0;
32 min = max - delta;
33
34 hue = h;
35 if (h > 300 || h <= 60)
36 {
37 r = (int)max;
38 if (h > 300)
39 {
40 g = (int)min;
41 hue = (hue - 360.0) / 60.0;
42 b = (int)((hue * delta - min) * -1);
43 }
44 else
45 {
46 b = (int)min;
47 hue = hue / 60.0;
48 g = (int)(hue * delta + min);
49 }
50 }
51 else if (h > 60 && h < 180)
52 {
53 g = (int)max;
54 if (h < 120)
55 {
56 b = (int)min;
57 hue = (hue / 60.0 - 2.0) * delta;
58 r = (int)(min - hue);
59 }
60 else
61 {
62 r = (int)min;
63 hue = (hue / 60 - 2.0) * delta;
64 b = (int)(min + hue);
65 }
66 }
67 else
68 {
69 b = (int)max;
70 if (h < 240)
71 {
72 r = (int)min;
73 hue = (hue / 60.0 - 4.0) * delta;
74 g = (int)(min - hue);
75 }
76 else
77 {
78 g = (int)min;
79 hue = (hue / 60 - 4.0) * delta;
80 r = (int)(min + hue);
81 }
82 }
83
84 return Color(r, g, b, 255);
85 }
86
RGBtoHSV(int r,int g,int b)87 HSV RGBtoHSV(int r, int g, int b)
88 {
89 double min, max, delta, temp;
90 min = GwenUtil_Min(r, GwenUtil_Min(g, b));
91 max = GwenUtil_Max(r, GwenUtil_Max(g, b));
92 delta = max - min;
93
94 HSV hsv;
95 hsv.v = (int)max;
96 if (!delta)
97 {
98 hsv.h = hsv.s = 0;
99 }
100 else
101 {
102 temp = delta / max;
103 hsv.s = (int)(temp * 255);
104
105 if (r == (int)max)
106 {
107 temp = (double)(g - b) / delta;
108 }
109 else if (g == (int)max)
110 {
111 temp = 2.0 + ((double)(b - r) / delta);
112 }
113 else
114 {
115 temp = 4.0 + ((double)(r - g) / delta);
116 }
117 temp *= 60;
118 if (temp < 0)
119 {
120 temp += 360;
121 }
122 if (temp == 360)
123 {
124 temp = 0;
125 }
126 hsv.h = (int)temp;
127 }
128
129 hsv.s /= 255.0f;
130 hsv.v /= 255.0f;
131
132 return hsv;
133 }
134
GWEN_CONTROL_CONSTRUCTOR(ColorLerpBox)135 GWEN_CONTROL_CONSTRUCTOR(ColorLerpBox)
136 {
137 SetColor(Gwen::Color(255, 128, 0, 255));
138 SetSize(128, 128);
139 SetMouseInputEnabled(true);
140 m_bDepressed = false;
141 }
142
143 //Find a place to put this? color member?
LerpColor(Gwen::Color & toColor,Gwen::Color & fromColor,float amount)144 Gwen::Color LerpColor(Gwen::Color& toColor, Gwen::Color& fromColor, float amount)
145 {
146 Gwen::Color colorDelta = toColor - fromColor;
147
148 colorDelta.r *= amount;
149 colorDelta.g *= amount;
150 colorDelta.b *= amount;
151
152 Gwen::Color newColor = fromColor + colorDelta;
153 return newColor;
154 }
155
GetSelectedColor()156 Gwen::Color ColorLerpBox::GetSelectedColor()
157 {
158 return GetColorAtPos(cursorPos.x, cursorPos.y);
159 }
160
SetColor(Gwen::Color color,bool onlyHue)161 void ColorLerpBox::SetColor(Gwen::Color color, bool onlyHue)
162 {
163 HSV hsv = RGBtoHSV(color.r, color.g, color.b);
164 m_Hue = hsv.h;
165 if (!onlyHue)
166 {
167 cursorPos.x = hsv.s * Width();
168 cursorPos.y = (1 - hsv.v) * Height();
169 }
170
171 onSelectionChanged.Call(this);
172 }
173
OnMouseMoved(int x,int y,int,int)174 void ColorLerpBox::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
175 {
176 if (m_bDepressed)
177 {
178 cursorPos = CanvasPosToLocal(Gwen::Point(x, y));
179 //Do we have clamp?
180 if (cursorPos.x < 0)
181 cursorPos.x = 0;
182 if (cursorPos.x > Width())
183 cursorPos.x = Width();
184
185 if (cursorPos.y < 0)
186 cursorPos.y = 0;
187 if (cursorPos.y > Height())
188 cursorPos.y = Height();
189
190 onSelectionChanged.Call(this);
191 }
192 }
193
OnMouseClickLeft(int x,int y,bool bDown)194 void ColorLerpBox::OnMouseClickLeft(int x, int y, bool bDown)
195 {
196 m_bDepressed = bDown;
197 if (bDown)
198 Gwen::MouseFocus = this;
199 else
200 Gwen::MouseFocus = NULL;
201
202 OnMouseMoved(x, y, 0, 0);
203 }
204
GetColorAtPos(int x,int y)205 Gwen::Color ColorLerpBox::GetColorAtPos(int x, int y)
206 {
207 float xPercent = ((float)x / (float)Width());
208 float yPercent = 1 - ((float)y / (float)Height());
209
210 Gwen::Color result = HSVToColor(m_Hue, xPercent, yPercent);
211
212 result.a = 255;
213
214 return result;
215 }
Render(Gwen::Skin::Base * skin)216 void ColorLerpBox::Render(Gwen::Skin::Base* skin)
217 {
218 //Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
219 BaseClass::Render(skin);
220 for (int x = 0; x < Width(); x++)
221 {
222 for (int y = 0; y < Height(); y++)
223 {
224 skin->GetRender()->SetDrawColor(GetColorAtPos(x, y));
225 skin->GetRender()->DrawPixel(x, y);
226 }
227 }
228
229 skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
230 skin->GetRender()->DrawLinedRect(GetRenderBounds());
231
232 Gwen::Color selected = GetSelectedColor();
233 if ((selected.r + selected.g + selected.b) / 3 < 170)
234 skin->GetRender()->SetDrawColor(Gwen::Color(255, 255, 255, 255));
235 else
236 skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
237
238 Gwen::Rect testRect = Gwen::Rect(cursorPos.x - 3, cursorPos.y - 3, 6, 6);
239
240 skin->GetRender()->DrawShavedCornerRect(testRect);
241 }
242
GWEN_CONTROL_CONSTRUCTOR(ColorSlider)243 GWEN_CONTROL_CONSTRUCTOR(ColorSlider)
244 {
245 SetSize(32, 128);
246 SetMouseInputEnabled(true);
247 m_bDepressed = false;
248 }
249
Render(Gwen::Skin::Base * skin)250 void ColorSlider::Render(Gwen::Skin::Base* skin)
251 {
252 //Is there any way to move this into skin? Not for now, no idea how we'll "actually" render these
253 int y = 0;
254 for (y = 0; y < Height(); y++)
255 {
256 float yPercent = (float)y / (float)Height();
257 skin->GetRender()->SetDrawColor(HSVToColor(yPercent * 360, 1, 1));
258 skin->GetRender()->DrawFilledRect(Gwen::Rect(5, y, Width() - 10, 1));
259 }
260
261 int drawHeight = m_iSelectedDist - 3;
262
263 //Draw our selectors
264 skin->GetRender()->SetDrawColor(Gwen::Color(0, 0, 0, 255));
265 skin->GetRender()->DrawFilledRect(Gwen::Rect(0, drawHeight + 2, Width(), 1));
266 skin->GetRender()->DrawFilledRect(Gwen::Rect(0, drawHeight, 5, 5));
267 skin->GetRender()->DrawFilledRect(Gwen::Rect(Width() - 5, drawHeight, 5, 5));
268 skin->GetRender()->SetDrawColor(Gwen::Color(255, 255, 255, 255));
269 skin->GetRender()->DrawFilledRect(Gwen::Rect(1, drawHeight + 1, 3, 3));
270 skin->GetRender()->DrawFilledRect(Gwen::Rect(Width() - 4, drawHeight + 1, 3, 3));
271 }
272
OnMouseClickLeft(int x,int y,bool bDown)273 void ColorSlider::OnMouseClickLeft(int x, int y, bool bDown)
274 {
275 m_bDepressed = bDown;
276 if (bDown)
277 Gwen::MouseFocus = this;
278 else
279 Gwen::MouseFocus = NULL;
280
281 OnMouseMoved(x, y, 0, 0);
282 }
283
GetColorAtHeight(int y)284 Gwen::Color ColorSlider::GetColorAtHeight(int y)
285 {
286 float yPercent = (float)y / (float)Height();
287 return HSVToColor(yPercent * 360, 1, 1);
288 }
OnMouseMoved(int x,int y,int,int)289 void ColorSlider::OnMouseMoved(int x, int y, int /*deltaX*/, int /*deltaY*/)
290 {
291 if (m_bDepressed)
292 {
293 Gwen::Point cursorPos = CanvasPosToLocal(Gwen::Point(x, y));
294
295 if (cursorPos.y < 0)
296 cursorPos.y = 0;
297 if (cursorPos.y > Height())
298 cursorPos.y = Height();
299
300 m_iSelectedDist = cursorPos.y;
301 onSelectionChanged.Call(this);
302 }
303 }
304
SetColor(Gwen::Color color)305 void ColorSlider::SetColor(Gwen::Color color)
306 {
307 HSV hsv = RGBtoHSV(color.r, color.g, color.b);
308
309 m_iSelectedDist = hsv.h / 360 * Height();
310
311 onSelectionChanged.Call(this);
312 }
313
GetSelectedColor()314 Gwen::Color ColorSlider::GetSelectedColor()
315 {
316 return GetColorAtHeight(m_iSelectedDist);
317 }
318