llfloatercolorpicker.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:33k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloatercolorpicker.cpp
  3.  * @brief Generic system color picker
  4.  *
  5.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2004-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloatercolorpicker.h"
  34. // Viewer project includes
  35. #include "lltoolmgr.h"
  36. #include "lltoolpipette.h"
  37. #include "llviewercontrol.h"
  38. #include "llworld.h"
  39. // Linden library includes
  40. #include "llfontgl.h"
  41. #include "llsys.h"
  42. #include "llgl.h"
  43. #include "llrender.h"
  44. #include "v3dmath.h"
  45. #include "lldir.h"
  46. #include "llui.h"
  47. #include "lllineeditor.h"
  48. #include "v4coloru.h"
  49. #include "llbutton.h"
  50. #include "lluictrlfactory.h"
  51. #include "llgl.h"
  52. #include "llpointer.h"
  53. #include "llimage.h"
  54. #include "llmousehandler.h"
  55. #include "llglheaders.h"
  56. #include "llcheckboxctrl.h"
  57. #include "lltextbox.h"
  58. #include "lluiconstants.h"
  59. #include "llfocusmgr.h"
  60. #include "lldraghandle.h"
  61. #include "llwindow.h"
  62. // System includes
  63. #include <sstream>
  64. #include <iomanip>
  65. const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
  66. const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
  67. const F32 CONTEXT_FADE_TIME = 0.08f;
  68. //////////////////////////////////////////////////////////////////////////////
  69. //
  70. // Class LLFloaterColorPicker
  71. //
  72. //////////////////////////////////////////////////////////////////////////////
  73. LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
  74. : LLFloater(LLSD()),
  75.   mComponents ( 3 ),
  76.   mMouseDownInLumRegion ( FALSE ),
  77.   mMouseDownInHueRegion ( FALSE ),
  78.   mMouseDownInSwatch ( FALSE ),
  79.   // *TODO: Specify this in XML
  80.   mRGBViewerImageLeft ( 140 ),
  81.   mRGBViewerImageTop ( 356 ),
  82.   mRGBViewerImageWidth ( 256 ),
  83.   mRGBViewerImageHeight ( 256 ),
  84.   mLumRegionLeft ( mRGBViewerImageLeft + mRGBViewerImageWidth + 16 ),
  85.   mLumRegionTop ( mRGBViewerImageTop ),
  86.   mLumRegionWidth ( 16 ),
  87.   mLumRegionHeight ( mRGBViewerImageHeight ),
  88.   mLumMarkerSize ( 6 ),
  89.   // *TODO: Specify this in XML
  90.   mSwatchRegionLeft ( 12 ),
  91.   mSwatchRegionTop ( 190 ),
  92.   mSwatchRegionWidth ( 116 ),
  93.   mSwatchRegionHeight ( 60 ),
  94.   mSwatchView ( NULL ),
  95.   // *TODO: Specify this in XML
  96.   numPaletteColumns ( 16 ),
  97.   numPaletteRows ( 2 ),
  98.   highlightEntry ( -1 ),
  99.   mPaletteRegionLeft ( 11 ),
  100.   mPaletteRegionTop ( 100 - 8 ),
  101.   mPaletteRegionWidth ( mLumRegionLeft + mLumRegionWidth - 10 ),
  102.   mPaletteRegionHeight ( 40 ),
  103.   mSwatch ( swatch ),
  104.   mActive ( TRUE ),
  105.   mCanApplyImmediately ( show_apply_immediate ),
  106.   mContextConeOpacity ( 0.f )
  107. {
  108. // build the majority of the gui using the factory builder
  109. LLUICtrlFactory::getInstance()->buildFloater ( this, "floater_color_picker.xml", NULL );
  110. // create user interface for this picker
  111. createUI ();
  112. if (!mCanApplyImmediately)
  113. {
  114. mApplyImmediateCheck->setEnabled(FALSE);
  115. mApplyImmediateCheck->set(FALSE);
  116. }
  117. }
  118. LLFloaterColorPicker::~LLFloaterColorPicker()
  119. {
  120. // destroy the UI we created
  121. destroyUI ();
  122. }
  123. //////////////////////////////////////////////////////////////////////////////
  124. //
  125. void LLFloaterColorPicker::createUI ()
  126. {
  127. // create RGB type area (not really RGB but it's got R,G & B in it.,..
  128. LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
  129. U8* bits = raw->getData();
  130. S32 linesize = mRGBViewerImageWidth * mComponents;
  131. for ( S32 y = 0; y < mRGBViewerImageHeight; ++y )
  132. {
  133. for ( S32 x = 0; x < linesize; x += mComponents )
  134. {
  135. F32 rVal, gVal, bVal;
  136. hslToRgb ( (F32)x / (F32) ( linesize - 1 ),
  137.    (F32)y / (F32) ( mRGBViewerImageHeight - 1 ),
  138.    0.5f,
  139.    rVal,
  140.    gVal,
  141.    bVal );
  142. * ( bits + x + y * linesize + 0 ) = ( U8 )( rVal * 255.0f );
  143. * ( bits + x + y * linesize + 1 ) = ( U8 )( gVal * 255.0f );
  144. * ( bits + x + y * linesize + 2 ) = ( U8 )( bVal * 255.0f );
  145. }
  146. }
  147. mRGBImage = LLViewerTextureManager::getLocalTexture( (LLImageRaw*)raw, FALSE );
  148. gGL.getTexUnit(0)->bind(mRGBImage);
  149. mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP);
  150. // create palette
  151. for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each )
  152. {
  153. std::ostringstream codec;
  154. codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << each + 1;
  155. // argh!
  156. const std::string s ( codec.str () );
  157. mPalette.push_back ( new LLColor4 ( LLUIColorTable::instance().getColor ( s )  ) );
  158. }
  159. }
  160. //////////////////////////////////////////////////////////////////////////////
  161. //
  162. void LLFloaterColorPicker::showUI ()
  163. {
  164. setVisible ( TRUE );
  165. setFocus ( TRUE );
  166. openFloater(getKey());
  167. // HACK: if system color picker is required - close the SL one we made and use default system dialog
  168. if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) )
  169. {
  170. LLColorSwatchCtrl* swatch = getSwatch ();
  171. setVisible ( FALSE );
  172. // code that will get switched in for default system color picker
  173. if ( swatch )
  174. {
  175. LLColor4 curCol = swatch->get ();
  176. send_agent_pause();
  177. getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );
  178. send_agent_resume();
  179. setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] );
  180. setCurRgb( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] );
  181. LLColorSwatchCtrl::onColorChanged ( swatch, LLColorSwatchCtrl::COLOR_CHANGE );
  182. }
  183. closeFloater();
  184. }
  185. }
  186. //////////////////////////////////////////////////////////////////////////////
  187. // called after the dialog is rendered
  188. BOOL LLFloaterColorPicker::postBuild()
  189. {
  190. mCancelBtn = getChild<LLButton>( "cancel_btn" );
  191.     mCancelBtn->setClickedCallback ( onClickCancel, this );
  192. mSelectBtn = getChild<LLButton>( "select_btn");
  193.     mSelectBtn->setClickedCallback ( onClickSelect, this );
  194. mSelectBtn->setFocus ( TRUE );
  195. mPipetteBtn = getChild<LLButton>("color_pipette" );
  196. mPipetteBtn->setImages(std::string("eye_button_inactive.tga"), std::string("eye_button_active.tga"));
  197. mPipetteBtn->setCommitCallback( boost::bind(&LLFloaterColorPicker::onClickPipette, this ));
  198. mApplyImmediateCheck = getChild<LLCheckBoxCtrl>("apply_immediate");
  199. mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately"));
  200. mApplyImmediateCheck->setCommitCallback(onImmediateCheck, this);
  201. childSetCommitCallback("rspin", onTextCommit, (void*)this );
  202. childSetCommitCallback("gspin", onTextCommit, (void*)this );
  203. childSetCommitCallback("bspin", onTextCommit, (void*)this );
  204. childSetCommitCallback("hspin", onTextCommit, (void*)this );
  205. childSetCommitCallback("sspin", onTextCommit, (void*)this );
  206. childSetCommitCallback("lspin", onTextCommit, (void*)this );
  207. LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1));
  208.     return TRUE;
  209. }
  210. //////////////////////////////////////////////////////////////////////////////
  211. //
  212. void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
  213. {
  214. // under some circumstances, we get rogue values that can be calmed by clamping...
  215. rValIn = llclamp ( rValIn, 0.0f, 1.0f );
  216. gValIn = llclamp ( gValIn, 0.0f, 1.0f );
  217. bValIn = llclamp ( bValIn, 0.0f, 1.0f );
  218. // store initial value in case cancel or revert is selected
  219. setOrigRgb ( rValIn, gValIn, bValIn );
  220. // starting point for current value to
  221. setCurRgb ( rValIn, gValIn, bValIn );
  222. // unpdate text entry fields
  223. updateTextEntry ();
  224. }
  225. //////////////////////////////////////////////////////////////////////////////
  226. //
  227. void LLFloaterColorPicker::destroyUI ()
  228. {
  229. // shut down pipette tool if active
  230. stopUsingPipette();
  231. // delete palette we created
  232. std::vector < LLColor4* >::iterator iter = mPalette.begin ();
  233. while ( iter != mPalette.end () )
  234. {
  235. delete ( *iter );
  236. ++iter;
  237. }
  238. if ( mSwatchView )
  239. {
  240. this->removeChild ( mSwatchView );
  241. delete mSwatchView;
  242. mSwatchView = NULL;
  243. }
  244. }
  245. //////////////////////////////////////////////////////////////////////////////
  246. //
  247. F32 LLFloaterColorPicker::hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
  248. {
  249. if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
  250. if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
  251. if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
  252. if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
  253. if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
  254. return ( val1In );
  255. }
  256. //////////////////////////////////////////////////////////////////////////////
  257. //
  258. void LLFloaterColorPicker::hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut )
  259. {
  260. if ( sValIn < 0.00001f )
  261. {
  262. rValOut = lValIn;
  263. gValOut = lValIn;
  264. bValOut = lValIn;
  265. }
  266. else
  267. {
  268. F32 interVal1;
  269. F32 interVal2;
  270. if ( lValIn < 0.5f )
  271. interVal2 = lValIn * ( 1.0f + sValIn );
  272. else
  273. interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
  274. interVal1 = 2.0f * lValIn - interVal2;
  275. rValOut = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
  276. gValOut = hueToRgb ( interVal1, interVal2, hValIn );
  277. bValOut = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
  278. }
  279. }
  280. //////////////////////////////////////////////////////////////////////////////
  281. // mutator for original RGB value
  282. void LLFloaterColorPicker::setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
  283. {
  284. origR = origRIn;
  285. origG = origGIn;
  286. origB = origBIn;
  287. }
  288. //////////////////////////////////////////////////////////////////////////////
  289. // accessor for original RGB value
  290. void LLFloaterColorPicker::getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
  291. {
  292. origROut = origR;
  293. origGOut = origG;
  294. origBOut = origB;
  295. }
  296. //////////////////////////////////////////////////////////////////////////////
  297. // mutator for current RGB value
  298. void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
  299. {
  300. // save current RGB
  301. curR = curRIn;
  302. curG = curGIn;
  303. curB = curBIn;
  304. // update corresponding HSL values and
  305. LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
  306. // color changed so update text fields
  307.     updateTextEntry();
  308. }
  309. //////////////////////////////////////////////////////////////////////////////
  310. // accessor for current RGB value
  311. void LLFloaterColorPicker::getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
  312. {
  313. curROut = curR;
  314. curGOut = curG;
  315. curBOut = curB;
  316. }
  317. //////////////////////////////////////////////////////////////////////////////
  318. // mutator for current HSL value
  319. void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
  320. {
  321. // save current HSL
  322. curH = curHIn;
  323. curS = curSIn;
  324. curL = curLIn;
  325. // update corresponding RGB values and
  326. hslToRgb ( curH, curS, curL, curR, curG, curB );
  327. }
  328. //////////////////////////////////////////////////////////////////////////////
  329. // accessor for current HSL value
  330. void LLFloaterColorPicker::getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
  331. {
  332. curHOut = curH;
  333. curSOut = curS;
  334. curLOut = curL;
  335. }
  336. //////////////////////////////////////////////////////////////////////////////
  337. // called when 'cancel' clicked
  338. void LLFloaterColorPicker::onClickCancel ( void* data )
  339. {
  340. if (data)
  341. {
  342. LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
  343. if ( self )
  344. {
  345. self->cancelSelection ();
  346. self->closeFloater();
  347. }
  348. }
  349. }
  350. //////////////////////////////////////////////////////////////////////////////
  351. // called when 'select' clicked
  352. void LLFloaterColorPicker::onClickSelect ( void* data )
  353. {
  354. if (data)
  355. {
  356. LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
  357. if ( self )
  358. {
  359. // apply to selection
  360. LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_SELECT );
  361. self->closeFloater();
  362. }
  363. }
  364. }
  365. void LLFloaterColorPicker::onClickPipette( )
  366. {
  367. BOOL pipette_active = mPipetteBtn->getToggleState();
  368. pipette_active = !pipette_active;
  369. if (pipette_active)
  370. {
  371. LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
  372. }
  373. else
  374. {
  375. LLToolMgr::getInstance()->clearTransientTool();
  376. }
  377. }
  378. //////////////////////////////////////////////////////////////////////////////
  379. // called when 'text is committed' - i,e. focus moves from a text field
  380. void LLFloaterColorPicker::onTextCommit ( LLUICtrl* ctrl, void* data )
  381. {
  382. if ( data )
  383. {
  384. LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
  385. if ( self )
  386. {
  387. self->onTextEntryChanged ( ctrl );
  388. }
  389. }
  390. }
  391. void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
  392. {
  393. LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
  394. if (self)
  395. {
  396. gSavedSettings.setBOOL("ApplyColorImmediately", self->mApplyImmediateCheck->get());
  397. if (self->mApplyImmediateCheck->get())
  398. {
  399. LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
  400. }
  401. }
  402. }
  403. void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
  404. {
  405. setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
  406. if (mApplyImmediateCheck->get())
  407. {
  408. LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
  409. }
  410. }
  411. void LLFloaterColorPicker::onMouseCaptureLost()
  412. {
  413. setMouseDownInHueRegion(FALSE);
  414. setMouseDownInLumRegion(FALSE);
  415. }
  416. //////////////////////////////////////////////////////////////////////////////
  417. //
  418. void LLFloaterColorPicker::draw()
  419. {
  420. LLRect swatch_rect;
  421. mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this);
  422. // draw context cone connecting color picker with color swatch in parent floater
  423. LLRect local_rect = getLocalRect();
  424. if (gFocusMgr.childHasKeyboardFocus(this) && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f)
  425. {
  426. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  427. LLGLEnable(GL_CULL_FACE);
  428. gGL.begin(LLRender::QUADS);
  429. {
  430. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  431. gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
  432. gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
  433. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  434. gGL.vertex2i(local_rect.mRight, local_rect.mTop);
  435. gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
  436. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  437. gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
  438. gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
  439. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  440. gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
  441. gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
  442. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  443. gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
  444. gGL.vertex2i(local_rect.mRight, local_rect.mTop);
  445. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  446. gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
  447. gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
  448. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
  449. gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
  450. gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
  451. gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
  452. gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
  453. gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
  454. }
  455. gGL.end();
  456. }
  457. if (gFocusMgr.childHasMouseCapture(getDragHandle()))
  458. {
  459. mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
  460. }
  461. else
  462. {
  463. mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
  464. }
  465. mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
  466. mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
  467. mSelectBtn->setEnabled(mActive);
  468. // base floater stuff
  469. LLFloater::draw ();
  470. // draw image for RGB area (not really RGB but you'll see what I mean...
  471. gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white );
  472. // update 'cursor' into RGB Section
  473. S32 xPos = ( S32 ) ( ( F32 )mRGBViewerImageWidth * getCurH () ) - 8;
  474. S32 yPos = ( S32 ) ( ( F32 )mRGBViewerImageHeight * getCurS () ) - 8;
  475. gl_line_2d ( mRGBViewerImageLeft + xPos,
  476.  mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
  477.  mRGBViewerImageLeft + xPos + 16,
  478.  mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
  479.  LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
  480. gl_line_2d ( mRGBViewerImageLeft + xPos + 8,
  481.  mRGBViewerImageTop - mRGBViewerImageHeight + yPos,
  482.  mRGBViewerImageLeft + xPos + 8,
  483.  mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 16,
  484.  LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
  485. // create rgb area outline
  486. gl_rect_2d ( mRGBViewerImageLeft,
  487.  mRGBViewerImageTop - mRGBViewerImageHeight,
  488.  mRGBViewerImageLeft + mRGBViewerImageWidth + 1,
  489.  mRGBViewerImageTop,
  490.  LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
  491.  FALSE );
  492. // draw luminance slider
  493. for ( S32 y = 0; y < mLumRegionHeight; ++y )
  494. {
  495. F32 rValSlider, gValSlider, bValSlider;
  496. hslToRgb ( getCurH (), getCurS (), ( F32 )y / ( F32 )mLumRegionHeight, rValSlider, gValSlider, bValSlider );
  497. gl_rect_2d( mLumRegionLeft, 
  498. mLumRegionTop - mLumRegionHeight + y, 
  499. mLumRegionLeft + mLumRegionWidth, 
  500. mLumRegionTop - mLumRegionHeight + y - 1, 
  501. LLColor4 ( rValSlider, gValSlider, bValSlider, 1.0f ) );
  502. }
  503. // draw luninance marker
  504. S32 startX = mLumRegionLeft + mLumRegionWidth;
  505. S32 startY = mLumRegionTop - mLumRegionHeight + ( S32 ) ( mLumRegionHeight * getCurL () );
  506. gl_triangle_2d ( startX, startY,
  507. startX + mLumMarkerSize, startY - mLumMarkerSize,
  508. startX + mLumMarkerSize, startY + mLumMarkerSize,
  509. LLColor4 ( 0.75f, 0.75f, 0.75f, 1.0f ), TRUE );
  510. // draw luminance slider outline
  511. gl_rect_2d ( mLumRegionLeft,
  512.  mLumRegionTop - mLumRegionHeight,
  513.  mLumRegionLeft + mLumRegionWidth + 1,
  514.  mLumRegionTop,
  515.  LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
  516.  FALSE );
  517. // draw selected color swatch
  518. gl_rect_2d ( mSwatchRegionLeft,
  519.  mSwatchRegionTop - mSwatchRegionHeight,
  520.  mSwatchRegionLeft + mSwatchRegionWidth,
  521.  mSwatchRegionTop,
  522.  LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f ),
  523.  TRUE );
  524. // draw selected color swatch outline
  525. gl_rect_2d ( mSwatchRegionLeft,
  526.  mSwatchRegionTop - mSwatchRegionHeight,
  527.  mSwatchRegionLeft + mSwatchRegionWidth + 1,
  528.  mSwatchRegionTop,
  529.  LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
  530.  FALSE );
  531. // color palette code is a little more involved so break it out into its' own method
  532. drawPalette ();
  533. }
  534. //////////////////////////////////////////////////////////////////////////////
  535. // find a complimentary color to the one passed in that can be used to highlight
  536. const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& backgroundColor )
  537. {
  538. // going to base calculation on luminance
  539. F32 hVal, sVal, lVal;
  540. backgroundColor.calcHSL(&hVal, &sVal, &lVal);
  541. hVal *= 360.f;
  542. sVal *= 100.f;
  543. lVal *= 100.f;
  544. // fairly simple heuristic for now...!
  545. if ( lVal < 0.5f )
  546. {
  547. return LLColor4::white;
  548. }
  549. return LLColor4::black;
  550. }
  551. //////////////////////////////////////////////////////////////////////////////
  552. // draw color palette
  553. void LLFloaterColorPicker::drawPalette ()
  554. {
  555. S32 curEntry = 0;
  556. for ( S32 y = 0; y < numPaletteRows; ++y )
  557. {
  558. for ( S32 x = 0; x < numPaletteColumns; ++x )
  559. {
  560. // calculate position
  561. S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * x ) / numPaletteColumns;
  562. S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * y ) / numPaletteRows;
  563. S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( x + 1 ) ) / numPaletteColumns );
  564. S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( y + 1 ) ) / numPaletteRows );
  565. // draw palette entry color
  566. if ( mPalette [ curEntry ] )
  567. {
  568. gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ], TRUE );
  569. gl_rect_2d ( x1 + 1, y1 - 1, x2 - 1, y2 + 1, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE );
  570. }
  571. }
  572. }
  573. // if there is something to highlight (mouse down in swatch & hovering over palette)
  574. if ( highlightEntry >= 0 )
  575. {
  576. // extract row/column from palette index
  577. S32 entryColumn = highlightEntry % numPaletteColumns;
  578. S32 entryRow = highlightEntry / numPaletteColumns;
  579. // calculate position of this entry
  580. S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * entryColumn ) / numPaletteColumns;
  581. S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * entryRow ) / numPaletteRows;
  582. S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( entryColumn + 1 ) ) / numPaletteColumns );
  583. S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( entryRow + 1 ) ) / numPaletteRows );
  584. // center position of entry
  585. S32 xCenter = x1 + ( x2 - x1 ) / 2;
  586. S32 yCenter = y1 - ( y1 - y2 ) / 2;
  587. // find a color that works well as a highlight color
  588. LLColor4 hlColor ( getComplimentaryColor ( *mPalette [ highlightEntry ] ) );
  589. // mark a cross for entry that is being hovered
  590. gl_line_2d ( xCenter - 4, yCenter - 4, xCenter + 4, yCenter + 4, hlColor );
  591. gl_line_2d ( xCenter + 4, yCenter - 4, xCenter - 4, yCenter + 4, hlColor );
  592. }
  593. }
  594. //////////////////////////////////////////////////////////////////////////////
  595. // update text entry values for RGB/HSL (can't be done in ::draw () since this overwrites input
  596. void LLFloaterColorPicker::updateTextEntry ()
  597. {
  598. // set values in spinners
  599. childSetValue("rspin", ( getCurR () * 255.0f ) );
  600. childSetValue("gspin", ( getCurG () * 255.0f ) );
  601. childSetValue("bspin", ( getCurB () * 255.0f ) );
  602. childSetValue("hspin", ( getCurH () * 360.0f ) );
  603. childSetValue("sspin", ( getCurS () * 100.0f ) );
  604. childSetValue("lspin", ( getCurL () * 100.0f ) );
  605. }
  606. //////////////////////////////////////////////////////////////////////////////
  607. //
  608. void LLFloaterColorPicker::onTextEntryChanged ( LLUICtrl* ctrl )
  609. {
  610. // value in RGB boxes changed
  611. std::string name = ctrl->getName();
  612. if ( ( name == "rspin" ) || ( name == "gspin" ) || ( name == "bspin" ) )
  613. {
  614. // get current RGB
  615. F32 rVal, gVal, bVal;
  616. getCurRgb ( rVal, gVal, bVal );
  617. // update component value with new value from text
  618. if ( name == "rspin" )
  619. {
  620. rVal = (F32)ctrl->getValue().asReal() / 255.0f;
  621. }
  622. else
  623. if ( name == "gspin" )
  624. {
  625. gVal = (F32)ctrl->getValue().asReal() / 255.0f;
  626. }
  627. else
  628. if ( name == "bspin" )
  629. {
  630. bVal = (F32)ctrl->getValue().asReal() / 255.0f;
  631. }
  632. // update current RGB (and implicitly HSL)
  633. setCurRgb ( rVal, gVal, bVal );
  634. updateTextEntry ();
  635. }
  636. else
  637. // value in HSL boxes changed
  638. if ( ( name == "hspin" ) || ( name == "sspin" ) || ( name == "lspin" ) )
  639. {
  640. // get current HSL
  641. F32 hVal, sVal, lVal;
  642. getCurHsl ( hVal, sVal, lVal );
  643. // update component value with new value from text
  644. if ( name == "hspin" )
  645. hVal = (F32)ctrl->getValue().asReal() / 360.0f;
  646. else
  647. if ( name == "sspin" )
  648. sVal = (F32)ctrl->getValue().asReal() / 100.0f;
  649. else
  650. if ( name == "lspin" )
  651. lVal = (F32)ctrl->getValue().asReal() / 100.0f;
  652. // update current HSL (and implicitly RGB)
  653. setCurHsl ( hVal, sVal, lVal );
  654. updateTextEntry ();
  655. }
  656. if (mApplyImmediateCheck->get())
  657. {
  658. LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
  659. }
  660. }
  661. //////////////////////////////////////////////////////////////////////////////
  662. //
  663. BOOL LLFloaterColorPicker::updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
  664. {
  665. if ( xPosIn >= mRGBViewerImageLeft &&
  666.  xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth &&
  667.  yPosIn <= mRGBViewerImageTop &&
  668.  yPosIn >= mRGBViewerImageTop - mRGBViewerImageHeight )
  669. {
  670. // update HSL (and therefore RGB) based on new H & S and current L
  671. setCurHsl ( ( ( F32 )xPosIn - ( F32 )mRGBViewerImageLeft ) / ( F32 )mRGBViewerImageWidth,
  672. ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight,
  673. getCurL () );
  674. // indicate a value changed
  675. return TRUE;
  676. }
  677. else
  678. if ( xPosIn >= mLumRegionLeft &&
  679.  xPosIn <= mLumRegionLeft + mLumRegionWidth &&
  680.  yPosIn <= mLumRegionTop &&
  681.  yPosIn >= mLumRegionTop - mLumRegionHeight )
  682. {
  683. // update HSL (and therefore RGB) based on current HS and new L
  684.  setCurHsl ( getCurH (),
  685.  getCurS (),
  686. ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight );
  687. // indicate a value changed
  688. return TRUE;
  689. }
  690. return FALSE;
  691. }
  692. //////////////////////////////////////////////////////////////////////////////
  693. //
  694. BOOL LLFloaterColorPicker::handleMouseDown ( S32 x, S32 y, MASK mask )
  695. {
  696. // make it the frontmost
  697. gFloaterView->bringToFront(this);
  698. // rect containing RGB area
  699. LLRect rgbAreaRect ( mRGBViewerImageLeft,
  700.  mRGBViewerImageTop,
  701.  mRGBViewerImageLeft + mRGBViewerImageWidth,
  702.  mRGBViewerImageTop - mRGBViewerImageHeight );
  703. if ( rgbAreaRect.pointInRect ( x, y ) )
  704. {
  705. gFocusMgr.setMouseCapture(this);
  706. // mouse button down
  707. setMouseDownInHueRegion ( TRUE );
  708. // update all values based on initial click
  709. updateRgbHslFromPoint ( x, y );
  710. // required by base class
  711. return TRUE;
  712. }
  713. // rect containing RGB area
  714. LLRect lumAreaRect ( mLumRegionLeft,
  715.  mLumRegionTop,
  716.  mLumRegionLeft + mLumRegionWidth + mLumMarkerSize,
  717.  mLumRegionTop - mLumRegionHeight );
  718. if ( lumAreaRect.pointInRect ( x, y ) )
  719. {
  720. gFocusMgr.setMouseCapture(this);
  721. // mouse button down
  722. setMouseDownInLumRegion ( TRUE );
  723. // required by base class
  724. return TRUE;
  725. }
  726. // rect containing swatch area
  727. LLRect swatchRect ( mSwatchRegionLeft,
  728. mSwatchRegionTop,
  729. mSwatchRegionLeft + mSwatchRegionWidth,
  730. mSwatchRegionTop - mSwatchRegionHeight );
  731. setMouseDownInSwatch( FALSE );
  732. if ( swatchRect.pointInRect ( x, y ) )
  733. {
  734. setMouseDownInSwatch( TRUE );
  735. // required - dont drag windows here.
  736. return TRUE;
  737. }
  738. // rect containing palette area
  739. LLRect paletteRect ( mPaletteRegionLeft,
  740.  mPaletteRegionTop,
  741.  mPaletteRegionLeft + mPaletteRegionWidth,
  742.  mPaletteRegionTop - mPaletteRegionHeight );
  743. if ( paletteRect.pointInRect ( x, y ) )
  744. {
  745. // release keyboard focus so we can change text values
  746. if (gFocusMgr.childHasKeyboardFocus(this))
  747. {
  748. mSelectBtn->setFocus(TRUE);
  749. }
  750. // calculate which palette index we selected
  751. S32 c = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
  752. S32 r = ( ( y - ( mPaletteRegionTop - mPaletteRegionHeight ) ) * numPaletteRows ) / mPaletteRegionHeight;
  753. U32 index = ( numPaletteRows - r - 1 ) * numPaletteColumns + c;
  754. if ( index <= mPalette.size () )
  755. {
  756. LLColor4 selected = *mPalette [ index ];
  757. setCurRgb ( selected [ 0 ], selected [ 1 ], selected [ 2 ] );
  758. if (mApplyImmediateCheck->get())
  759. {
  760. LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
  761. }
  762. updateTextEntry ();
  763. }
  764. return TRUE;
  765. }
  766. // dispatch to base class for the rest of things
  767. return LLFloater::handleMouseDown ( x, y, mask );
  768. }
  769. //////////////////////////////////////////////////////////////////////////////
  770. //
  771. BOOL LLFloaterColorPicker::handleHover ( S32 x, S32 y, MASK mask )
  772. {
  773. // if we're the front most window
  774. if ( isFrontmost () )
  775. {
  776. // mouse was pressed within region
  777. if ( getMouseDownInHueRegion() || getMouseDownInLumRegion())
  778. {
  779. S32 clamped_x, clamped_y;
  780. if (getMouseDownInHueRegion())
  781. {
  782. clamped_x = llclamp(x, mRGBViewerImageLeft, mRGBViewerImageLeft + mRGBViewerImageWidth);
  783. clamped_y = llclamp(y, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBViewerImageTop);
  784. }
  785. else
  786. {
  787. clamped_x = llclamp(x, mLumRegionLeft, mLumRegionLeft + mLumRegionWidth);
  788. clamped_y = llclamp(y, mLumRegionTop - mLumRegionHeight, mLumRegionTop);
  789. }
  790. // update the stored RGB/HSL values using the mouse position - returns TRUE if RGB was updated
  791. if ( updateRgbHslFromPoint ( clamped_x, clamped_y ) )
  792. {
  793. // update text entry fields
  794. updateTextEntry ();
  795. // RN: apparently changing color when dragging generates too much traffic and results in sporadic updates
  796. //// commit changed color to swatch subject
  797. //// REVIEW: this gets sent each time a color changes - is this okay ?
  798. //if (mApplyImmediateCheck->get())
  799. //{
  800. // LLColorSwatchCtrl::onColorChanged ( getSwatch () );
  801. //}
  802. }
  803. }
  804. highlightEntry = -1;
  805. if ( mMouseDownInSwatch )
  806. {
  807. getWindow()->setCursor ( UI_CURSOR_ARROWDRAG );
  808. // if cursor if over a palette entry
  809. LLRect paletteRect ( mPaletteRegionLeft,
  810. mPaletteRegionTop,
  811. mPaletteRegionLeft + mPaletteRegionWidth,
  812. mPaletteRegionTop - mPaletteRegionHeight );
  813. if ( paletteRect.pointInRect ( x, y ) )
  814. {
  815. // find row/column in palette
  816. S32 xOffset = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
  817. S32 yOffset = ( ( mPaletteRegionTop - y - 1 ) * numPaletteRows ) / mPaletteRegionHeight;
  818. // calculate the entry 0..n-1 to highlight and set variable to next draw() picks it up
  819. highlightEntry = xOffset + yOffset * numPaletteColumns;
  820. }
  821. return TRUE;
  822. }
  823. }
  824. // dispatch to base class for the rest of things
  825. return LLFloater::handleHover ( x, y, mask );
  826. }
  827. //////////////////////////////////////////////////////////////////////////////
  828. // reverts state once mouse button is released
  829. BOOL LLFloaterColorPicker::handleMouseUp ( S32 x, S32 y, MASK mask )
  830. {
  831. getWindow()->setCursor ( UI_CURSOR_ARROW );
  832. if (getMouseDownInHueRegion() || getMouseDownInLumRegion())
  833. {
  834. if (mApplyImmediateCheck->get())
  835. {
  836. LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
  837. }
  838. }
  839. // rect containing palette area
  840. LLRect paletteRect ( mPaletteRegionLeft,
  841. mPaletteRegionTop,
  842. mPaletteRegionLeft + mPaletteRegionWidth,
  843. mPaletteRegionTop - mPaletteRegionHeight );
  844. if ( paletteRect.pointInRect ( x, y ) )
  845. {
  846. if ( mMouseDownInSwatch )
  847. {
  848. S32 curEntry = 0;
  849. for ( S32 row = 0; row < numPaletteRows; ++row )
  850. {
  851. for ( S32 column = 0; column < numPaletteColumns; ++column )
  852. {
  853. S32 left = mPaletteRegionLeft + ( mPaletteRegionWidth * column ) / numPaletteColumns;
  854. S32 top = mPaletteRegionTop - ( mPaletteRegionHeight * row ) / numPaletteRows;
  855. S32 right = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( column + 1 ) ) / numPaletteColumns );
  856. S32 bottom = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( row + 1 ) ) / numPaletteRows );
  857. // rect is flipped vertically when testing here
  858. LLRect dropRect ( left, top, right, bottom );
  859. if ( dropRect.pointInRect ( x, y ) )
  860. {
  861. if ( mPalette [ curEntry ] )
  862. {
  863. delete mPalette [ curEntry ];
  864. mPalette [ curEntry ] = new LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f );
  865. // save off color
  866. std::ostringstream codec;
  867. codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << curEntry + 1;
  868. const std::string s ( codec.str () );
  869. LLUIColorTable::instance().setColor(s, *mPalette [ curEntry ] );
  870. }
  871. }
  872. ++curEntry;
  873. }
  874. }
  875. }
  876. }
  877. // mouse button not down anymore
  878. setMouseDownInHueRegion ( FALSE );
  879. setMouseDownInLumRegion ( FALSE );
  880. // mouse button not down in color swatch anymore
  881. mMouseDownInSwatch = false;
  882. if (hasMouseCapture())
  883. {
  884. gFocusMgr.setMouseCapture(NULL);
  885. }
  886. // dispatch to base class for the rest of things
  887. return LLFloater::handleMouseUp ( x, y, mask );
  888. }
  889. //////////////////////////////////////////////////////////////////////////////
  890. // cancel current color selection, revert to original and close picker
  891. void LLFloaterColorPicker::cancelSelection ()
  892. {
  893. // restore the previous color selection
  894. setCurRgb ( getOrigR (), getOrigG (), getOrigB () );
  895. // update in world item with original color via current swatch
  896. LLColorSwatchCtrl::onColorChanged( getSwatch(), LLColorSwatchCtrl::COLOR_CANCEL );
  897. // hide picker dialog
  898. this->setVisible ( FALSE );
  899. }
  900. void LLFloaterColorPicker::setMouseDownInHueRegion ( BOOL mouse_down_in_region )
  901. {
  902. mMouseDownInHueRegion = mouse_down_in_region;
  903. if (mouse_down_in_region)
  904. {
  905. if (gFocusMgr.childHasKeyboardFocus(this))
  906. {
  907. // get focus out of spinners so that they can update freely
  908. mSelectBtn->setFocus(TRUE);
  909. }
  910. }
  911. }
  912. void LLFloaterColorPicker::setMouseDownInLumRegion ( BOOL mouse_down_in_region )
  913. {
  914. mMouseDownInLumRegion = mouse_down_in_region;
  915. if (mouse_down_in_region)
  916. {
  917. if (gFocusMgr.childHasKeyboardFocus(this))
  918. {
  919. // get focus out of spinners so that they can update freely
  920. mSelectBtn->setFocus(TRUE);
  921. }
  922. }
  923. }
  924. void LLFloaterColorPicker::setMouseDownInSwatch (BOOL mouse_down_in_swatch)
  925. {
  926. mMouseDownInSwatch = mouse_down_in_swatch;
  927. if (mouse_down_in_swatch)
  928. {
  929. if (gFocusMgr.childHasKeyboardFocus(this))
  930. {
  931. // get focus out of spinners so that they can update freely
  932. mSelectBtn->setFocus(TRUE);
  933. }
  934. }
  935. }
  936. void LLFloaterColorPicker::setActive(BOOL active) 
  937. // shut down pipette tool if active
  938. if (!active && mPipetteBtn->getToggleState())
  939. {
  940. stopUsingPipette();
  941. }
  942. mActive = active; 
  943. }
  944. void LLFloaterColorPicker::stopUsingPipette()
  945. {
  946. if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance())
  947. {
  948. LLToolMgr::getInstance()->clearTransientTool();
  949. }
  950. }