1 /*!
2 	@file
3 	@author		Albert Semenov
4 	@date		08/2008
5 */
6 
7 #include "Precompiled.h"
8 #include "ColourPanel.h"
9 #include "CommandManager.h"
10 
11 namespace tools
12 {
13 
ColourPanel()14 	ColourPanel::ColourPanel() :
15 		mColourRect(nullptr),
16 		mColourView(nullptr),
17 		mImageColourPicker(nullptr),
18 		mEditRed(nullptr),
19 		mEditGreen(nullptr),
20 		mEditBlue(nullptr),
21 		mInputAlpha(nullptr),
22 		mTextAlpha(nullptr),
23 		mScrollRange(nullptr),
24 		mAlphaSliderBack(nullptr),
25 		mAlphaSliderPlace(nullptr),
26 		mAlphaSlider(nullptr),
27 		mTexture(nullptr),
28 		mAlphaSupport(true)
29 	{
30 	}
31 
~ColourPanel()32 	ColourPanel::~ColourPanel()
33 	{
34 		destroyTexture();
35 	}
36 
OnInitialise(Control * _parent,MyGUI::Widget * _place,const std::string & _layoutName)37 	void ColourPanel::OnInitialise(Control* _parent, MyGUI::Widget* _place, const std::string& _layoutName)
38 	{
39 		Control::OnInitialise(_parent, _place, GetLayoutName(this));
40 
41 		InitialiseByAttributes(this);
42 
43 		setDialogRoot(mMainWidget);
44 
45 		mTextureName = MyGUI::utility::toString((size_t)this, "_ColourGradient");
46 
47 		mCurrentColour = MyGUI::Colour::Green;
48 		mBaseColour = MyGUI::Colour::Green;
49 
50 		mColourRect->eventMouseButtonPressed += MyGUI::newDelegate(this, &ColourPanel::notifyMouseButtonPressed);
51 		mColourRect->eventMouseDrag += MyGUI::newDelegate(this, &ColourPanel::notifyMouseDrag);
52 		mImageColourPicker->eventMouseDrag += MyGUI::newDelegate(this, &ColourPanel::notifyMouseDrag);
53 		mScrollRange->eventScrollChangePosition += MyGUI::newDelegate(this, &ColourPanel::notifyScrollChangePosition);
54 		mAlphaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &ColourPanel::notifyScrollChangePositionAlpha);
55 
56 		mEditRed->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
57 		mEditGreen->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
58 		mEditBlue->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
59 		mInputAlpha->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChangeAlpha);
60 
61 		CommandManager::getInstance().getEvent("Command_ColorAccept")->connect(this, &ColourPanel::commandColorAccept);
62 		CommandManager::getInstance().getEvent("Command_ColorCancel")->connect(this, &ColourPanel::commandColorCancel);
63 
64 		mColourRange.push_back(MyGUI::Colour(1, 0, 0));
65 		mColourRange.push_back(MyGUI::Colour(1, 0, 1));
66 		mColourRange.push_back(MyGUI::Colour(0, 0, 1));
67 		mColourRange.push_back(MyGUI::Colour(0, 1, 1));
68 		mColourRange.push_back(MyGUI::Colour(0, 1, 0));
69 		mColourRange.push_back(MyGUI::Colour(1, 1, 0));
70 		mColourRange.push_back(mColourRange[0]);
71 
72 		mMainWidget->setVisible(false);
73 
74 		createTexture();
75 
76 		updateFirst();
77 	}
78 
updateFirst()79 	void ColourPanel::updateFirst()
80 	{
81 		notifyScrollChangePosition(nullptr, mScrollRange->getScrollPosition());
82 
83 		notifyMouseDrag(nullptr,
84 			mImageColourPicker->getAbsoluteLeft() + (mColourRect->getWidth() / 2),
85 			mImageColourPicker->getAbsoluteTop() + (mColourRect->getHeight() / 2),
86 			MyGUI::MouseButton::Left);
87 	}
88 
createTexture()89 	void ColourPanel::createTexture()
90 	{
91 		int size = 32;
92 		mTexture = MyGUI::RenderManager::getInstance().createTexture(mTextureName);
93 		mTexture->createManual(size, size,
94 			MyGUI::TextureUsage::Static | MyGUI::TextureUsage::Write,
95 			MyGUI::PixelFormat::R8G8B8A8);
96 
97 		mColourRect->setImageTexture(mTextureName);
98 	}
99 
destroyTexture()100 	void ColourPanel::destroyTexture()
101 	{
102 		MyGUI::RenderManager::getInstance().destroyTexture( mTexture );
103 		mTexture = nullptr;
104 	}
105 
updateTexture(const MyGUI::Colour & _colour)106 	void ColourPanel::updateTexture(const MyGUI::Colour& _colour)
107 	{
108 		size_t size = 32;
109 
110 		MyGUI::uint8* pDest = static_cast<MyGUI::uint8*>(mTexture->lock(MyGUI::TextureUsage::Write));
111 
112 		for (size_t j = 0; j < size; j++)
113 		{
114 			for (size_t i = 0; i < size; i++)
115 			{
116 				float x = (float)i / size;
117 				float y = (float)j / size;
118 				*pDest++ = MyGUI::uint8((1.f - y) * (_colour.blue  * x + (1.f - x)) * 255); // B
119 				*pDest++ = MyGUI::uint8((1.f - y) * (_colour.green * x + (1.f - x)) * 255); // G
120 				*pDest++ = MyGUI::uint8((1.f - y) * (_colour.red   * x + (1.f - x)) * 255); // R
121 				*pDest++ = 255; // A
122 			}
123 		}
124 
125 		// Unlock the pixel buffer
126 		mTexture->unlock();
127 	}
128 
notifyMouseDrag(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)129 	void ColourPanel::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
130 	{
131 		if (_id != MyGUI::MouseButton::Left)
132 			return;
133 
134 		MyGUI::Widget* parent = mImageColourPicker->getParent();
135 		MyGUI::IntPoint point(_left - parent->getAbsoluteLeft(), _top - parent->getAbsoluteTop());
136 
137 		if (point.left < 0)
138 			point.left = 0;
139 		if (point.top < 0)
140 			point.top = 0;
141 		if (point.left > mColourRect->getWidth())
142 			point.left = mColourRect->getWidth();
143 		if (point.top > mColourRect->getHeight())
144 			point.top = mColourRect->getHeight();
145 
146 		mImageColourPicker->setPosition(point.left - (mImageColourPicker->getWidth() / 2), point.top - (mImageColourPicker->getHeight() / 2));
147 
148 		updateFromPoint(point);
149 	}
150 
notifyMouseButtonPressed(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)151 	void ColourPanel::notifyMouseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
152 	{
153 		if (_id == MyGUI::MouseButton::Left)
154 			notifyMouseDrag(nullptr, _left, _top, _id);
155 	}
156 
updateFromPoint(const MyGUI::IntPoint & _point)157 	void ColourPanel::updateFromPoint(const MyGUI::IntPoint& _point)
158 	{
159 		// get colour by cursor position Altren 09.2008
160 		float x = 1.0f * _point.left / mColourRect->getWidth();
161 		float y = 1.0f * _point.top / mColourRect->getHeight();
162 
163 		if (x > 1)
164 			x = 1;
165 		else if (x < 0)
166 			x = 0;
167 
168 		if (y > 1)
169 			y = 1;
170 		else if (y < 0)
171 			y = 0;
172 
173 		mCurrentColour.red = (1 - y) * (mBaseColour.red * x + MyGUI::Colour::White.red * (1 - x));
174 		mCurrentColour.green = (1 - y) * (mBaseColour.green * x + MyGUI::Colour::White.green * (1 - x));
175 		mCurrentColour.blue = (1 - y) * (mBaseColour.blue * x + MyGUI::Colour::White.blue * (1 - x));
176 
177 		mColourView->setColour(mCurrentColour);
178 		mAlphaSliderBack->setColour(mCurrentColour);
179 
180 		eventPreviewColour(mCurrentColour);
181 
182 		mEditRed->setCaption(MyGUI::utility::toString((int)(mCurrentColour.red * 255)));
183 		mEditGreen->setCaption(MyGUI::utility::toString((int)(mCurrentColour.green * 255)));
184 		mEditBlue->setCaption(MyGUI::utility::toString((int)(mCurrentColour.blue * 255)));
185 	}
186 
notifyScrollChangePosition(MyGUI::ScrollBar * _sender,size_t _position)187 	void ColourPanel::notifyScrollChangePosition(MyGUI::ScrollBar* _sender, size_t _position)
188 	{
189 		float sector_size = (float)mScrollRange->getScrollRange() / 6.0f;
190 		float sector_current = (float)_position / sector_size;
191 
192 		// current sector
193 		size_t current = (size_t)sector_current;
194 		assert(current < 6);
195 		// offset to the next sector from 0 to 1
196 		float offfset = (sector_current - (float)current);
197 
198 		const MyGUI::Colour& from = mColourRange[current];
199 		const MyGUI::Colour& to = mColourRange[current + 1];
200 
201 		mBaseColour.red = from.red + offfset * (to.red - from.red);
202 		mBaseColour.green = from.green + offfset * (to.green - from.green);
203 		mBaseColour.blue = from.blue + offfset * (to.blue - from.blue);
204 
205 		updateTexture(mBaseColour);
206 
207 		MyGUI::IntPoint point(
208 			mImageColourPicker->getLeft() + (mImageColourPicker->getWidth() / 2),
209 			mImageColourPicker->getTop() + (mImageColourPicker->getHeight() / 2));
210 
211 		updateFromPoint(point);
212 	}
213 
notifyEditTextChange(MyGUI::EditBox * _sender)214 	void ColourPanel::notifyEditTextChange(MyGUI::EditBox* _sender)
215 	{
216 		MyGUI::EditBox* edit = static_cast<MyGUI::EditBox*>(_sender);
217 		size_t cursor = edit->getTextCursor();
218 		size_t num = MyGUI::utility::parseSizeT(edit->getOnlyText());
219 		if (num > 255)
220 			num = 255;
221 		edit->setCaption(MyGUI::utility::toString(num));
222 		if (cursor < edit->getTextLength())
223 			edit->setTextCursor(cursor);
224 
225 		MyGUI::Colour colour(
226 			MyGUI::utility::parseFloat(mEditRed->getOnlyText()) / 255.0f,
227 			MyGUI::utility::parseFloat(mEditGreen->getOnlyText()) / 255.0f,
228 			MyGUI::utility::parseFloat(mEditBlue->getOnlyText()) / 255.0f);
229 
230 		updateFromColour(colour);
231 	}
232 
setColour(const MyGUI::Colour & _colour)233 	void ColourPanel::setColour(const MyGUI::Colour& _colour)
234 	{
235 		MyGUI::Colour colour = getSaturate(_colour);
236 		mEditRed->setCaption(MyGUI::utility::toString((int)(colour.red * 255)));
237 		mEditGreen->setCaption(MyGUI::utility::toString((int)(colour.green * 255)));
238 		mEditBlue->setCaption(MyGUI::utility::toString((int)(colour.blue * 255)));
239 		mInputAlpha->setCaption(MyGUI::utility::toString(mAlphaSupport ? colour.alpha : 1));
240 
241 		updateFromColour(colour);
242 	}
243 
updateFromColour(const MyGUI::Colour & _colour)244 	void ColourPanel::updateFromColour(const MyGUI::Colour& _colour)
245 	{
246 		mCurrentColour = _colour;
247 		if (!mAlphaSupport)
248 			mCurrentColour.alpha = 1;
249 
250 		std::vector<float> vec;
251 		vec.push_back(mCurrentColour.red);
252 		vec.push_back(mCurrentColour.green);
253 		vec.push_back(mCurrentColour.blue);
254 		std::sort(vec.begin(), vec.end());
255 
256 		MyGUI::IntPoint point((int)((1 - vec[0] / vec[2]) * mColourRect->getWidth()), (int)((1 - vec[2]) * mColourRect->getHeight()));
257 		mImageColourPicker->setPosition(point.left - (mImageColourPicker->getWidth() / 2), point.top - (mImageColourPicker->getHeight() / 2));
258 
259 		int iMax = (mCurrentColour.red == vec[2]) ? 0 : (mCurrentColour.green == vec[2]) ? 1 : 2;
260 		int iMin = (mCurrentColour.red == vec[0]) ? 0 : (mCurrentColour.green == vec[0]) ? 1 : 2;
261 		int iAvg = 3 - iMax - iMin;
262 
263 		if (iMin == iMax) // if gray colour - set base red
264 		{
265 			iMax = 0;
266 			iMin = 1;
267 			iAvg = 2;
268 			byIndex(mBaseColour, iMin) = 0.;
269 			byIndex(mBaseColour, iAvg) = 0.;
270 			byIndex(mBaseColour, iMax) = 1.;
271 		}
272 		else
273 		{
274 			byIndex(mBaseColour, iMin) = 0.;
275 			byIndex(mBaseColour, iAvg) = (vec[1] - vec[0]) / (vec[2] - vec[0]);
276 			byIndex(mBaseColour, iMax) = 1.;
277 		}
278 
279 		int i = 0;
280 		for (i = 0; i < 6; ++i)
281 		{
282 			if ((std::fabs(byIndex(mColourRange[i], iMin) - byIndex(mBaseColour, iMin)) < 0.001f) &&
283 				(std::fabs(byIndex(mColourRange[i], iMax) - byIndex(mBaseColour, iMax)) < 0.001f) &&
284 				(std::fabs(byIndex(mColourRange[i+1], iMin) - byIndex(mBaseColour, iMin)) < 0.001f) &&
285 				(std::fabs(byIndex(mColourRange[i+1], iMax) - byIndex(mBaseColour, iMax)) < 0.001f))
286 				break;
287 		}
288 
289 		float sector_size = (float)mScrollRange->getScrollRange() / 6.0f;
290 		size_t current = i;
291 
292 		float offset = byIndex(mBaseColour, iAvg);
293 		if (byIndex(mColourRange[i+1], iAvg) < byIndex(mColourRange[i], iAvg))
294 			offset = 1 - byIndex(mBaseColour, iAvg);
295 
296 		size_t pos = size_t((current + offset) * sector_size);
297 
298 		mScrollRange->setScrollPosition(pos);
299 
300 		// bonus for colour's cutoff under scale
301 		mBaseColour.red = mColourRange[i].red + offset * (mColourRange[i+1].red - mColourRange[i].red);
302 		mBaseColour.green = mColourRange[i].green + offset * (mColourRange[i+1].green - mColourRange[i].green);
303 		mBaseColour.blue = mColourRange[i].blue + offset * (mColourRange[i+1].blue - mColourRange[i].blue);
304 
305 		updateTexture(mBaseColour);
306 
307 		mAlphaSlider->setScrollPosition((size_t)((double)(mAlphaSlider->getScrollRange() - 1) * (double)mCurrentColour.alpha));
308 
309 		mColourView->setColour(mCurrentColour);
310 		mColourView->setAlpha(mCurrentColour.alpha);
311 		mAlphaSliderBack->setColour(mCurrentColour);
312 
313 		eventPreviewColour(mCurrentColour);
314 	}
315 
getSaturate(const MyGUI::Colour & _colour) const316 	MyGUI::Colour ColourPanel::getSaturate(const MyGUI::Colour& _colour) const
317 	{
318 		MyGUI::Colour colour = _colour;
319 		if (colour.red < 0)
320 			colour.red = 0;
321 		else if (colour.red > 1)
322 			colour.red = 1;
323 
324 		if (colour.green < 0)
325 			colour.green = 0;
326 		else if (colour.green > 1)
327 			colour.green = 1;
328 
329 		if (colour.blue < 0)
330 			colour.blue = 0;
331 		else if (colour.blue > 1)
332 			colour.blue = 1;
333 
334 		return colour;
335 	}
336 
byIndex(MyGUI::Colour & _colour,size_t _index)337 	float& ColourPanel::byIndex(MyGUI::Colour& _colour, size_t _index)
338 	{
339 		if (_index == 0)
340 			return _colour.red;
341 		else if (_index == 1)
342 			return _colour.green;
343 		else if (_index == 2)
344 			return _colour.blue;
345 		else
346 			return _colour.alpha;
347 	}
348 
onDoModal()349 	void ColourPanel::onDoModal()
350 	{
351 	}
352 
onEndModal()353 	void ColourPanel::onEndModal()
354 	{
355 	}
356 
getColour() const357 	const MyGUI::Colour& ColourPanel::getColour() const
358 	{
359 		return mCurrentColour;
360 	}
361 
notifyEditTextChangeAlpha(MyGUI::EditBox * _sender)362 	void ColourPanel::notifyEditTextChangeAlpha(MyGUI::EditBox* _sender)
363 	{
364 		MyGUI::UString value = _sender->getOnlyText();
365 
366 		mCurrentColour.alpha = MyGUI::utility::parseValue<float>(value);
367 
368 		bool validate = true;
369 		if (mCurrentColour.alpha > 1)
370 		{
371 			mCurrentColour.alpha = 1;
372 			validate = false;
373 		}
374 		else if (mCurrentColour.alpha < 0)
375 		{
376 			mCurrentColour.alpha = 0;
377 			validate = false;
378 		}
379 
380 		if (!validate)
381 			value = MyGUI::utility::toString(mCurrentColour.alpha);
382 
383 		size_t index = _sender->getTextCursor();
384 		_sender->setCaption(value);
385 		_sender->setTextCursor(index);
386 
387 		mAlphaSlider->setScrollPosition((size_t)((double)(mAlphaSlider->getScrollRange() - 1) * (double)mCurrentColour.alpha));
388 		mColourView->setAlpha(mCurrentColour.alpha);
389 
390 		eventPreviewColour(mCurrentColour);
391 	}
392 
notifyScrollChangePositionAlpha(MyGUI::ScrollBar * _sender,size_t _position)393 	void ColourPanel::notifyScrollChangePositionAlpha(MyGUI::ScrollBar* _sender, size_t _position)
394 	{
395 		mCurrentColour.alpha = (float)((double)mAlphaSlider->getScrollPosition() / (double)(mAlphaSlider->getScrollRange() - 1));
396 
397 		if (mCurrentColour.alpha > 1)
398 			mCurrentColour.alpha = 1;
399 		else if (mCurrentColour.alpha < 0)
400 			mCurrentColour.alpha = 0;
401 
402 		mInputAlpha->setCaption(MyGUI::utility::toString(mCurrentColour.alpha));
403 		mColourView->setAlpha(mCurrentColour.alpha);
404 
405 		eventPreviewColour(mCurrentColour);
406 	}
407 
setAlphaSupport(bool _value)408 	void ColourPanel::setAlphaSupport(bool _value)
409 	{
410 		mAlphaSupport = _value;
411 		updateAlphaSupport();
412 
413 		setColour(getColour());
414 	}
415 
getAlphaSupport() const416 	bool ColourPanel::getAlphaSupport() const
417 	{
418 		return mAlphaSupport;
419 	}
420 
updateAlphaSupport()421 	void ColourPanel::updateAlphaSupport()
422 	{
423 		mInputAlpha->setVisible(mAlphaSupport);
424 		mTextAlpha->setVisible(mAlphaSupport);
425 		mAlphaSliderPlace->setVisible(mAlphaSupport);
426 	}
427 
checkCommand()428 	bool ColourPanel::checkCommand()
429 	{
430 		return isDialogModal();
431 	}
432 
commandColorAccept(const MyGUI::UString & _commandName,bool & _result)433 	void ColourPanel::commandColorAccept(const MyGUI::UString& _commandName, bool& _result)
434 	{
435 		if (!checkCommand())
436 			return;
437 
438 		eventEndDialog(this, true);
439 
440 		_result = true;
441 	}
442 
commandColorCancel(const MyGUI::UString & _commandName,bool & _result)443 	void ColourPanel::commandColorCancel(const MyGUI::UString& _commandName, bool& _result)
444 	{
445 		if (!checkCommand())
446 			return;
447 
448 		eventEndDialog(this, false);
449 
450 		_result = true;
451 	}
452 
453 }
454