1 /*!
2 	@file
3 	@author		Albert Semenov
4 	@date		08/2008
5 */
6 #include "Precompiled.h"
7 #include "ColourPanel.h"
8 
9 namespace demo
10 {
11 
ColourPanel()12 	ColourPanel::ColourPanel()
13 	{
14 		initialiseByAttributes(this);
15 
16 		mCurrentColour = MyGUI::Colour::Green;
17 		mBaseColour = MyGUI::Colour::Green;
18 
19 		mColourRect->eventMouseButtonPressed += MyGUI::newDelegate(this, &ColourPanel::notifyMouseButtonPressed);
20 		mColourRect->eventMouseDrag += MyGUI::newDelegate(this, &ColourPanel::notifyMouseDrag);
21 		mImageColourPicker->eventMouseDrag += MyGUI::newDelegate(this, &ColourPanel::notifyMouseDrag);
22 		mScrollRange->eventScrollChangePosition += MyGUI::newDelegate(this, &ColourPanel::notifyScrollChangePosition);
23 
24 		mEditRed->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
25 		mEditGreen->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
26 		mEditBlue->eventEditTextChange += MyGUI::newDelegate(this, &ColourPanel::notifyEditTextChange);
27 
28 		mOk->eventMouseButtonClick += MyGUI::newDelegate(this, &ColourPanel::notifyMouseButtonClick);
29 
30 		mColourRange.push_back(MyGUI::Colour(1, 0, 0));
31 		mColourRange.push_back(MyGUI::Colour(1, 0, 1));
32 		mColourRange.push_back(MyGUI::Colour(0, 0, 1));
33 		mColourRange.push_back(MyGUI::Colour(0, 1, 1));
34 		mColourRange.push_back(MyGUI::Colour(0, 1, 0));
35 		mColourRange.push_back(MyGUI::Colour(1, 1, 0));
36 		mColourRange.push_back(mColourRange[0]);
37 
38 		createTexture();
39 
40 		updateFirst();
41 	}
42 
~ColourPanel()43 	ColourPanel::~ColourPanel()
44 	{
45 		destroyTexture();
46 	}
47 
notifyMouseButtonClick(MyGUI::Widget * _sender)48 	void ColourPanel::notifyMouseButtonClick(MyGUI::Widget* _sender)
49 	{
50 		eventColourAccept(this);
51 	}
52 
updateFirst()53 	void ColourPanel::updateFirst()
54 	{
55 		notifyScrollChangePosition(nullptr, mScrollRange->getScrollPosition());
56 
57 		notifyMouseDrag(nullptr,
58 			mImageColourPicker->getAbsoluteLeft() + (mColourRect->getWidth() / 2),
59 			mImageColourPicker->getAbsoluteTop() + (mColourRect->getHeight() / 2),
60 			MyGUI::MouseButton::Left);
61 	}
62 
createTexture()63 	void ColourPanel::createTexture()
64 	{
65 		int size = 32;
66 		mTexture = MyGUI::RenderManager::getInstance().createTexture("ColourGradient");
67 		mTexture->createManual(size, size,
68 			MyGUI::TextureUsage::Static | MyGUI::TextureUsage::Write,
69 			MyGUI::PixelFormat::R8G8B8A8);
70 
71 		mColourRect->setImageTexture("ColourGradient");
72 	}
73 
destroyTexture()74 	void ColourPanel::destroyTexture()
75 	{
76 		MyGUI::RenderManager::getInstance().destroyTexture( mTexture );
77 		mTexture = nullptr;
78 	}
79 
updateTexture(const MyGUI::Colour & _colour)80 	void ColourPanel::updateTexture(const MyGUI::Colour& _colour)
81 	{
82 		size_t size = 32;
83 
84 		MyGUI::uint8* pDest = static_cast<MyGUI::uint8*>(mTexture->lock(MyGUI::TextureUsage::Write));
85 
86 		for (size_t j = 0; j < size; j++)
87 			for (size_t i = 0; i < size; i++)
88 			{
89 				float x = (float)i / size;
90 				float y = (float)j / size;
91 				*pDest++ = MyGUI::uint8((1.0f - y) * (_colour.blue  * x + (1.0f - x)) * 255); // B
92 				*pDest++ = MyGUI::uint8((1.0f - y) * (_colour.green * x + (1.0f - x)) * 255); // G
93 				*pDest++ = MyGUI::uint8((1.0f - y) * (_colour.red   * x + (1.0f - x)) * 255); // R
94 				*pDest++ = 255; // A
95 			}
96 
97 		// Unlock the pixel buffer
98 		mTexture->unlock();
99 	}
100 
notifyMouseDrag(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)101 	void ColourPanel::notifyMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
102 	{
103 		if (_id != MyGUI::MouseButton::Left)
104 			return;
105 
106 		MyGUI::Widget* parent = mImageColourPicker->getParent();
107 		MyGUI::IntPoint point(_left - parent->getAbsoluteLeft(), _top - parent->getAbsoluteTop());
108 
109 		if (point.left < 0) point.left = 0;
110 		if (point.top < 0) point.top = 0;
111 		if (point.left > mColourRect->getWidth()) point.left = mColourRect->getWidth();
112 		if (point.top > mColourRect->getHeight()) point.top = mColourRect->getHeight();
113 
114 		mImageColourPicker->setPosition(point.left - (mImageColourPicker->getWidth() / 2), point.top - (mImageColourPicker->getHeight() / 2));
115 
116 		updateFromPoint(point);
117 	}
118 
notifyMouseButtonPressed(MyGUI::Widget * _sender,int _left,int _top,MyGUI::MouseButton _id)119 	void ColourPanel::notifyMouseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
120 	{
121 		if (_id == MyGUI::MouseButton::Left)
122 			notifyMouseDrag(nullptr, _left, _top, _id);
123 	}
124 
updateFromPoint(const MyGUI::IntPoint & _point)125 	void ColourPanel::updateFromPoint(const MyGUI::IntPoint& _point)
126 	{
127 		// get colour by cursor position Altren 09.2008
128 		float x = 1.0f * _point.left / mColourRect->getWidth();
129 		float y = 1.0f * _point.top / mColourRect->getHeight();
130 		if (x > 1) x = 1;
131 		else if (x < 0) x = 0;
132 		if (y > 1) y = 1;
133 		else if (y < 0) y = 0;
134 
135 		mCurrentColour.red = (1 - y) * (mBaseColour.red * x + MyGUI::Colour::White.red * (1 - x));
136 		mCurrentColour.green = (1 - y) * (mBaseColour.green * x + MyGUI::Colour::White.green * (1 - x));
137 		mCurrentColour.blue = (1 - y) * (mBaseColour.blue * x + MyGUI::Colour::White.blue * (1 - x));
138 
139 		mColourView->setColour(mCurrentColour);
140 
141 		mEditRed->setCaption(MyGUI::utility::toString((int)(mCurrentColour.red * 255)));
142 		mEditGreen->setCaption(MyGUI::utility::toString((int)(mCurrentColour.green * 255)));
143 		mEditBlue->setCaption(MyGUI::utility::toString((int)(mCurrentColour.blue * 255)));
144 	}
145 
notifyScrollChangePosition(MyGUI::ScrollBar * _sender,size_t _position)146 	void ColourPanel::notifyScrollChangePosition(MyGUI::ScrollBar* _sender, size_t _position)
147 	{
148 		float sector_size = (float)mScrollRange->getScrollRange() / 6.0f;
149 		float sector_current = (float)_position / sector_size;
150 
151 		// current sector
152 		size_t current = (size_t)sector_current;
153 		assert(current < 6);
154 		// смещение до следующего сектора от 0 до 1
155 		float offfset = (sector_current - (float)current);
156 
157 		const MyGUI::Colour& from = mColourRange[current];
158 		const MyGUI::Colour& to = mColourRange[current + 1];
159 
160 		mBaseColour.red = from.red + offfset * (to.red - from.red);
161 		mBaseColour.green = from.green + offfset * (to.green - from.green);
162 		mBaseColour.blue = from.blue + offfset * (to.blue - from.blue);
163 
164 		updateTexture(mBaseColour);
165 
166 		MyGUI::IntPoint point(
167 			mImageColourPicker->getLeft() + (mImageColourPicker->getWidth() / 2),
168 			mImageColourPicker->getTop() + (mImageColourPicker->getHeight() / 2));
169 
170 		updateFromPoint(point);
171 	}
172 
notifyEditTextChange(MyGUI::EditBox * _sender)173 	void ColourPanel::notifyEditTextChange(MyGUI::EditBox* _sender)
174 	{
175 		MyGUI::EditBox* edit = static_cast<MyGUI::EditBox*>(_sender);
176 		size_t cursor = edit->getTextCursor();
177 		size_t num = MyGUI::utility::parseSizeT(edit->getOnlyText());
178 		if (num > 255) num = 255;
179 		edit->setCaption(MyGUI::utility::toString(num));
180 		if (cursor < edit->getTextLength()) edit->setTextCursor(cursor);
181 
182 		MyGUI::Colour colour(
183 			MyGUI::utility::parseFloat(mEditRed->getOnlyText()) / 255.0f,
184 			MyGUI::utility::parseFloat(mEditGreen->getOnlyText()) / 255.0f,
185 			MyGUI::utility::parseFloat(mEditBlue->getOnlyText()) / 255.0f);
186 
187 		updateFromColour(colour);
188 	}
189 
setColour(const MyGUI::Colour & _colour)190 	void ColourPanel::setColour(const MyGUI::Colour& _colour)
191 	{
192 		MyGUI::Colour colour = getSaturate(_colour);
193 		mEditRed->setCaption(MyGUI::utility::toString((int)(colour.red * 255)));
194 		mEditGreen->setCaption(MyGUI::utility::toString((int)(colour.green * 255)));
195 		mEditBlue->setCaption(MyGUI::utility::toString((int)(colour.blue * 255)));
196 
197 		updateFromColour(colour);
198 	}
199 
updateFromColour(const MyGUI::Colour & _colour)200 	void ColourPanel::updateFromColour(const MyGUI::Colour& _colour)
201 	{
202 		mCurrentColour = _colour;
203 
204 		std::vector<float> vec;
205 		vec.push_back(_colour.red);
206 		vec.push_back(_colour.green);
207 		vec.push_back(_colour.blue);
208 		std::sort(vec.begin(), vec.end());
209 
210 		MyGUI::IntPoint point((int)((1 - vec[0] / vec[2]) * mColourRect->getWidth()), (int)((1 - vec[2]) * mColourRect->getHeight()));
211 		mImageColourPicker->setPosition(point.left - (mImageColourPicker->getWidth() / 2), point.top - (mImageColourPicker->getHeight() / 2));
212 
213 		int iMax = (_colour.red == vec[2]) ? 0 : (_colour.green == vec[2]) ? 1 : 2;
214 		int iMin = (_colour.red == vec[0]) ? 0 : (_colour.green == vec[0]) ? 1 : 2;
215 		int iAvg = 3 - iMax - iMin;
216 
217 		if (iMin == iMax) // if gray colour - set base red
218 		{
219 			iMax = 0;
220 			iMin = 1;
221 			iAvg = 2;
222 			byIndex(mBaseColour, iMin) = 0.;
223 			byIndex(mBaseColour, iAvg) = 0.;
224 			byIndex(mBaseColour, iMax) = 1.;
225 		}
226 		else
227 		{
228 			byIndex(mBaseColour, iMin) = 0.;
229 			byIndex(mBaseColour, iAvg) = (vec[1] - vec[0]) / (vec[2] - vec[0]);
230 			byIndex(mBaseColour, iMax) = 1.;
231 		}
232 
233 
234 		int i;
235 		for (i = 0; i < 6; ++i)
236 		{
237 			if ((std::abs(byIndex(mColourRange[i], iMin) - byIndex(mBaseColour, iMin)) < 0.001f) &&
238 				(std::abs(byIndex(mColourRange[i], iMax) - byIndex(mBaseColour, iMax)) < 0.001f) &&
239 				(std::abs(byIndex(mColourRange[i+1], iMin) - byIndex(mBaseColour, iMin)) < 0.001f) &&
240 				(std::abs(byIndex(mColourRange[i+1], iMax) - byIndex(mBaseColour, iMax)) < 0.001f))
241 				break;
242 		}
243 
244 		float sector_size = (float)mScrollRange->getScrollRange() / 6.0f;
245 		size_t current = i;
246 
247 		float offset = byIndex(mBaseColour, iAvg);
248 		if (byIndex(mColourRange[i+1], iAvg) < byIndex(mColourRange[i], iAvg)) offset = 1 - byIndex(mBaseColour, iAvg);
249 
250 		size_t pos = size_t((current + offset) * sector_size);
251 
252 		mScrollRange->setScrollPosition(pos);
253 
254 		// бонус для обрезки цвета под шкалу
255 		mBaseColour.red = mColourRange[i].red + offset * (mColourRange[i+1].red - mColourRange[i].red);
256 		mBaseColour.green = mColourRange[i].green + offset * (mColourRange[i+1].green - mColourRange[i].green);
257 		mBaseColour.blue = mColourRange[i].blue + offset * (mColourRange[i+1].blue - mColourRange[i].blue);
258 
259 		updateTexture(mBaseColour);
260 
261 		mColourView->setColour(mCurrentColour);
262 	}
263 
getSaturate(const MyGUI::Colour & _colour) const264 	MyGUI::Colour ColourPanel::getSaturate(const MyGUI::Colour& _colour) const
265 	{
266 		MyGUI::Colour colour = _colour;
267 		if (colour.red < 0)
268 			colour.red = 0;
269 		else if (colour.red > 1)
270 			colour.red = 1;
271 
272 		if (colour.green < 0)
273 			colour.green = 0;
274 		else if (colour.green > 1)
275 			colour.green = 1;
276 
277 		if (colour.blue < 0)
278 			colour.blue = 0;
279 		else if (colour.blue > 1)
280 			colour.blue = 1;
281 
282 		return colour;
283 	}
284 
byIndex(MyGUI::Colour & _colour,size_t _index)285 	float& ColourPanel::byIndex(MyGUI::Colour& _colour, size_t _index)
286 	{
287 		if (_index == 0) return _colour.red;
288 		else if (_index == 1) return _colour.green;
289 		else if (_index == 2) return _colour.blue;
290 		else return _colour.alpha;
291 	}
292 
getColour() const293 	const MyGUI::Colour& ColourPanel::getColour() const
294 	{
295 		return mCurrentColour;
296 	}
297 
298 } // namespace demo
299