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