diff options
Diffstat (limited to 'indra/newview/llfloatercolorpicker.cpp')
-rw-r--r-- | indra/newview/llfloatercolorpicker.cpp | 2180 |
1 files changed, 1090 insertions, 1090 deletions
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index e6d6028419..603f54fb49 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -1,1090 +1,1090 @@ -/**
- * @file llfloatercolorpicker.cpp
- * @brief Generic system color picker
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloatercolorpicker.h"
-
-// Viewer project includes
-#include "lltoolmgr.h"
-#include "lltoolpipette.h"
-#include "llviewercontrol.h"
-#include "llworld.h"
-
-// Linden library includes
-#include "llfontgl.h"
-#include "llsys.h"
-#include "llgl.h"
-#include "llrender.h"
-#include "v3dmath.h"
-#include "lldir.h"
-#include "llui.h"
-#include "lllineeditor.h"
-#include "v4coloru.h"
-#include "llbutton.h"
-#include "lluictrlfactory.h"
-#include "llgl.h"
-#include "llpointer.h"
-#include "llimage.h"
-#include "llmousehandler.h"
-#include "llglheaders.h"
-#include "llcheckboxctrl.h"
-#include "lltextbox.h"
-#include "lluiconstants.h"
-#include "llfocusmgr.h"
-#include "lldraghandle.h"
-#include "llwindow.h"
-
-// System includes
-#include <sstream>
-#include <iomanip>
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Class LLFloaterColorPicker
-//
-//////////////////////////////////////////////////////////////////////////////
-
-LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, bool show_apply_immediate )
- : LLFloater(LLSD()),
- mComponents ( 3 ),
- mMouseDownInLumRegion ( false ),
- mMouseDownInHueRegion ( false ),
- mMouseDownInSwatch ( false ),
- // *TODO: Specify this in XML
- mRGBViewerImageLeft ( 140 ),
- mRGBViewerImageTop ( 356 ),
- mRGBViewerImageWidth ( 256 ),
- mRGBViewerImageHeight ( 256 ),
- mLumRegionLeft ( mRGBViewerImageLeft + mRGBViewerImageWidth + 16 ),
- mLumRegionTop ( mRGBViewerImageTop ),
- mLumRegionWidth ( 16 ),
- mLumRegionHeight ( mRGBViewerImageHeight ),
- mLumMarkerSize ( 6 ),
- // *TODO: Specify this in XML
- mSwatchRegionLeft ( 12 ),
- mSwatchRegionTop ( 190 ),
- mSwatchRegionWidth ( 116 ),
- mSwatchRegionHeight ( 60 ),
- mSwatchView ( NULL ),
- // *TODO: Specify this in XML
- numPaletteColumns ( 16 ),
- numPaletteRows ( 2 ),
- highlightEntry ( -1 ),
- mPaletteRegionLeft ( 11 ),
- mPaletteRegionTop ( 100 - 8 ),
- mPaletteRegionWidth ( mLumRegionLeft + mLumRegionWidth - 10 ),
- mPaletteRegionHeight ( 40 ),
- mSwatch ( swatch ),
- mActive ( true ),
- mCanApplyImmediately ( show_apply_immediate ),
- mContextConeOpacity ( 0.f ),
- mContextConeInAlpha (CONTEXT_CONE_IN_ALPHA),
- mContextConeOutAlpha (CONTEXT_CONE_OUT_ALPHA),
- mContextConeFadeTime (CONTEXT_CONE_FADE_TIME)
-{
- buildFromFile ( "floater_color_picker.xml");
-
- // create user interface for this picker
- createUI ();
-
- if (!mCanApplyImmediately)
- {
- mApplyImmediateCheck->setEnabled(false);
- mApplyImmediateCheck->set(false);
- }
-}
-
-LLFloaterColorPicker::~LLFloaterColorPicker()
-{
- // destroy the UI we created
- destroyUI ();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::createUI ()
-{
- // create RGB type area (not really RGB but it's got R,G & B in it.,..
-
- LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
- LLImageDataLock lock(raw);
-
- U8* bits = raw->getData();
- S32 linesize = mRGBViewerImageWidth * mComponents;
- for ( S32 y = 0; y < mRGBViewerImageHeight; ++y )
- {
- for ( S32 x = 0; x < linesize; x += mComponents )
- {
- F32 rVal, gVal, bVal;
-
- hslToRgb ( (F32)x / (F32) ( linesize - 1 ),
- (F32)y / (F32) ( mRGBViewerImageHeight - 1 ),
- 0.5f,
- rVal,
- gVal,
- bVal );
-
- * ( bits + x + y * linesize + 0 ) = ( U8 )( rVal * 255.0f );
- * ( bits + x + y * linesize + 1 ) = ( U8 )( gVal * 255.0f );
- * ( bits + x + y * linesize + 2 ) = ( U8 )( bVal * 255.0f );
- }
- }
- mRGBImage = LLViewerTextureManager::getLocalTexture( (LLImageRaw*)raw, false );
- gGL.getTexUnit(0)->bind(mRGBImage);
- mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP);
-
- // create palette
- for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each )
- {
- mPalette.push_back(new LLColor4(LLUIColorTable::instance().getColor(llformat("ColorPaletteEntry%02d", each + 1))));
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::showUI ()
-{
- openFloater(getKey());
- setVisible ( true );
- setFocus ( true );
-
- // HACK: if system color picker is required - close the SL one we made and use default system dialog
- if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) )
- {
- LLColorSwatchCtrl* swatch = getSwatch ();
-
- setVisible ( false );
-
- // code that will get switched in for default system color picker
- if ( swatch )
- {
- // Todo: this needs to be threaded for viewer not to timeout
- LLColor4 curCol = swatch->get ();
- send_agent_pause();
- bool commit = getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );
- send_agent_resume();
-
- if (commit)
- {
- setOrigRgb(curCol[0], curCol[1], curCol[2]);
- setCurRgb(curCol[0], curCol[1], curCol[2]);
-
- LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_SELECT);
- }
- else
- {
- LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_CANCEL);
- }
- }
-
- closeFloater();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called after the dialog is rendered
-bool LLFloaterColorPicker::postBuild()
-{
- mCancelBtn = getChild<LLButton>( "cancel_btn" );
- mCancelBtn->setClickedCallback ( onClickCancel, this );
-
- mSelectBtn = getChild<LLButton>( "select_btn");
- mSelectBtn->setClickedCallback ( onClickSelect, this );
- mSelectBtn->setFocus ( true );
-
- mPipetteBtn = getChild<LLButton>("color_pipette" );
-
- mPipetteBtn->setImages(std::string("eye_button_inactive.tga"), std::string("eye_button_active.tga"));
-
- mPipetteBtn->setCommitCallback( boost::bind(&LLFloaterColorPicker::onClickPipette, this ));
-
- mApplyImmediateCheck = getChild<LLCheckBoxCtrl>("apply_immediate");
- mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately"));
- mApplyImmediateCheck->setCommitCallback(onImmediateCheck, this);
-
- childSetCommitCallback("rspin", onTextCommit, (void*)this );
- childSetCommitCallback("gspin", onTextCommit, (void*)this );
- childSetCommitCallback("bspin", onTextCommit, (void*)this );
- childSetCommitCallback("hspin", onTextCommit, (void*)this );
- childSetCommitCallback("sspin", onTextCommit, (void*)this );
- childSetCommitCallback("lspin", onTextCommit, (void*)this );
-
- LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1));
-
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
-{
- // under some circumstances, we get rogue values that can be calmed by clamping...
- rValIn = llclamp ( rValIn, 0.0f, 1.0f );
- gValIn = llclamp ( gValIn, 0.0f, 1.0f );
- bValIn = llclamp ( bValIn, 0.0f, 1.0f );
-
- // store initial value in case cancel or revert is selected
- setOrigRgb ( rValIn, gValIn, bValIn );
-
- // starting point for current value to
- setCurRgb ( rValIn, gValIn, bValIn );
-
- // unpdate text entry fields
- updateTextEntry ();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::destroyUI ()
-{
- // shut down pipette tool if active
- stopUsingPipette();
-
- // delete palette we created
- std::vector < LLColor4* >::iterator iter = mPalette.begin ();
- while ( iter != mPalette.end () )
- {
- delete ( *iter );
- ++iter;
- }
-
- if ( mSwatchView )
- {
- this->removeChild ( mSwatchView );
- mSwatchView->die();;
- mSwatchView = NULL;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-F32 LLFloaterColorPicker::hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
-{
- if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
- if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
- if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
- if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
- if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
- return ( val1In );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut )
-{
- if ( sValIn < 0.00001f )
- {
- rValOut = lValIn;
- gValOut = lValIn;
- bValOut = lValIn;
- }
- else
- {
- F32 interVal1;
- F32 interVal2;
-
- if ( lValIn < 0.5f )
- interVal2 = lValIn * ( 1.0f + sValIn );
- else
- interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
-
- interVal1 = 2.0f * lValIn - interVal2;
-
- rValOut = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
- gValOut = hueToRgb ( interVal1, interVal2, hValIn );
- bValOut = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// mutator for original RGB value
-void LLFloaterColorPicker::setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
-{
- origR = origRIn;
- origG = origGIn;
- origB = origBIn;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// accessor for original RGB value
-void LLFloaterColorPicker::getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
-{
- origROut = origR;
- origGOut = origG;
- origBOut = origB;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// mutator for current RGB value
-void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
-{
- // save current RGB
- curR = curRIn;
- curG = curGIn;
- curB = curBIn;
-
- // update corresponding HSL values and
- LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
-
- // color changed so update text fields
- updateTextEntry();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// accessor for current RGB value
-void LLFloaterColorPicker::getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
-{
- curROut = curR;
- curGOut = curG;
- curBOut = curB;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// mutator for current HSL value
-void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
-{
- // save current HSL
- curH = curHIn;
- curS = curSIn;
- curL = curLIn;
-
- // update corresponding RGB values and
- hslToRgb ( curH, curS, curL, curR, curG, curB );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// accessor for current HSL value
-void LLFloaterColorPicker::getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
-{
- curHOut = curH;
- curSOut = curS;
- curLOut = curL;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when 'cancel' clicked
-void LLFloaterColorPicker::onClickCancel ( void* data )
-{
- if (data)
- {
- LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
-
- if ( self )
- {
- self->cancelSelection();
- self->closeFloater();
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when 'select' clicked
-void LLFloaterColorPicker::onClickSelect ( void* data )
-{
- if (data)
- {
- LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
-
- if ( self )
- {
- // apply to selection
- LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_SELECT );
- self->closeFloater();
- }
- }
-}
-
-void LLFloaterColorPicker::onClickPipette( )
-{
- bool pipette_active = mPipetteBtn->getToggleState();
- pipette_active = !pipette_active;
- if (pipette_active)
- {
- LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
- }
- else
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when 'text is committed' - i,e. focus moves from a text field
-void LLFloaterColorPicker::onTextCommit ( LLUICtrl* ctrl, void* data )
-{
- if ( data )
- {
- LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
- if ( self )
- {
- self->onTextEntryChanged ( ctrl );
- }
- }
-}
-
-void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
-{
- LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
- if (self)
- {
- gSavedSettings.setBOOL("ApplyColorImmediately", self->mApplyImmediateCheck->get());
- if (self->mApplyImmediateCheck->get() && self->isColorChanged())
- {
- LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
- }
-}
-
-void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
-{
- // Pipete
- selectCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
-}
-
-void LLFloaterColorPicker::onMouseCaptureLost()
-{
- setMouseDownInHueRegion(false);
- setMouseDownInLumRegion(false);
-}
-
-F32 LLFloaterColorPicker::getSwatchTransparency()
-{
- // If the floater is focused, don't apply its alpha to the color swatch (STORM-676).
- return getTransparencyType() == TT_ACTIVE ? 1.f : LLFloater::getCurrentTransparency();
-}
-
-bool LLFloaterColorPicker::isColorChanged()
-{
- return ((getOrigR() != getCurR()) || (getOrigG() != getCurG()) || (getOrigB() != getCurB()));
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::draw()
-{
- static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
- drawConeToOwner(mContextConeOpacity, max_opacity, mSwatch, mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
-
- mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
- mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
- mSelectBtn->setEnabled(mActive);
-
- // base floater stuff
- LLFloater::draw ();
-
- const F32 alpha = getSwatchTransparency();
-
- // draw image for RGB area (not really RGB but you'll see what I mean...
- gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white % alpha);
-
- // update 'cursor' into RGB Section
- S32 xPos = ( S32 ) ( ( F32 )mRGBViewerImageWidth * getCurH () ) - 8;
- S32 yPos = ( S32 ) ( ( F32 )mRGBViewerImageHeight * getCurS () ) - 8;
- gl_line_2d ( mRGBViewerImageLeft + xPos,
- mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
- mRGBViewerImageLeft + xPos + 16,
- mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8,
- LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
-
- gl_line_2d ( mRGBViewerImageLeft + xPos + 8,
- mRGBViewerImageTop - mRGBViewerImageHeight + yPos,
- mRGBViewerImageLeft + xPos + 8,
- mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 16,
- LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) );
-
- // create rgb area outline
- gl_rect_2d ( mRGBViewerImageLeft,
- mRGBViewerImageTop - mRGBViewerImageHeight,
- mRGBViewerImageLeft + mRGBViewerImageWidth + 1,
- mRGBViewerImageTop,
- LLColor4 ( 0.0f, 0.0f, 0.0f, alpha ),
- false );
-
- // draw luminance slider
- for ( S32 y = 0; y < mLumRegionHeight; ++y )
- {
- F32 rValSlider, gValSlider, bValSlider;
- hslToRgb ( getCurH (), getCurS (), ( F32 )y / ( F32 )mLumRegionHeight, rValSlider, gValSlider, bValSlider );
-
- gl_rect_2d( mLumRegionLeft,
- mLumRegionTop - mLumRegionHeight + y,
- mLumRegionLeft + mLumRegionWidth,
- mLumRegionTop - mLumRegionHeight + y - 1,
- LLColor4 ( rValSlider, gValSlider, bValSlider, alpha ) );
- }
-
-
- // draw luninance marker
- S32 startX = mLumRegionLeft + mLumRegionWidth;
- S32 startY = mLumRegionTop - mLumRegionHeight + ( S32 ) ( mLumRegionHeight * getCurL () );
- gl_triangle_2d ( startX, startY,
- startX + mLumMarkerSize, startY - mLumMarkerSize,
- startX + mLumMarkerSize, startY + mLumMarkerSize,
- LLColor4 ( 0.75f, 0.75f, 0.75f, 1.0f ), true );
-
- // draw luminance slider outline
- gl_rect_2d ( mLumRegionLeft,
- mLumRegionTop - mLumRegionHeight,
- mLumRegionLeft + mLumRegionWidth + 1,
- mLumRegionTop,
- LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
- false );
-
- // draw selected color swatch
- gl_rect_2d ( mSwatchRegionLeft,
- mSwatchRegionTop - mSwatchRegionHeight,
- mSwatchRegionLeft + mSwatchRegionWidth,
- mSwatchRegionTop,
- LLColor4 ( getCurR (), getCurG (), getCurB (), alpha ),
- true );
-
- // draw selected color swatch outline
- gl_rect_2d ( mSwatchRegionLeft,
- mSwatchRegionTop - mSwatchRegionHeight,
- mSwatchRegionLeft + mSwatchRegionWidth + 1,
- mSwatchRegionTop,
- LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
- false );
-
- // color palette code is a little more involved so break it out into its' own method
- drawPalette ();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// find a complimentary color to the one passed in that can be used to highlight
-const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& backgroundColor )
-{
- // going to base calculation on luminance
- F32 hVal, sVal, lVal;
- backgroundColor.calcHSL(&hVal, &sVal, &lVal);
- hVal *= 360.f;
- sVal *= 100.f;
- lVal *= 100.f;
-
- // fairly simple heuristic for now...!
- if ( lVal < 0.5f )
- {
- return LLColor4::white;
- }
-
- return LLColor4::black;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// set current RGB and rise change event if needed.
-void LLFloaterColorPicker::selectCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
-{
- setCurRgb(curRIn, curGIn, curBIn);
- if (mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// set current HSL and rise change event if needed.
-void LLFloaterColorPicker::selectCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
-{
- setCurHsl(curHIn, curSIn, curLIn);
- if (mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// draw color palette
-void LLFloaterColorPicker::drawPalette ()
-{
- S32 curEntry = 0;
- const F32 alpha = getSwatchTransparency();
-
- for ( S32 y = 0; y < numPaletteRows; ++y )
- {
- for ( S32 x = 0; x < numPaletteColumns; ++x )
- {
- // calculate position
- S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * x ) / numPaletteColumns;
- S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * y ) / numPaletteRows;
- S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( x + 1 ) ) / numPaletteColumns );
- S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( y + 1 ) ) / numPaletteRows );
-
- // draw palette entry color
- if ( mPalette [ curEntry ] )
- {
- gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ] % alpha, true );
- gl_rect_2d ( x1 + 1, y1 - 1, x2 - 1, y2 + 1, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), false );
- }
- }
- }
-
- // if there is something to highlight (mouse down in swatch & hovering over palette)
- if ( highlightEntry >= 0 )
- {
- // extract row/column from palette index
- S32 entryColumn = highlightEntry % numPaletteColumns;
- S32 entryRow = highlightEntry / numPaletteColumns;
-
- // calculate position of this entry
- S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * entryColumn ) / numPaletteColumns;
- S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * entryRow ) / numPaletteRows;
- S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( entryColumn + 1 ) ) / numPaletteColumns );
- S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( entryRow + 1 ) ) / numPaletteRows );
-
- // center position of entry
- S32 xCenter = x1 + ( x2 - x1 ) / 2;
- S32 yCenter = y1 - ( y1 - y2 ) / 2;
-
- // find a color that works well as a highlight color
- LLColor4 hlColor ( getComplimentaryColor ( *mPalette [ highlightEntry ] ) );
-
- // mark a cross for entry that is being hovered
- gl_line_2d ( xCenter - 4, yCenter - 4, xCenter + 4, yCenter + 4, hlColor );
- gl_line_2d ( xCenter + 4, yCenter - 4, xCenter - 4, yCenter + 4, hlColor );
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// update text entry values for RGB/HSL (can't be done in ::draw () since this overwrites input
-void LLFloaterColorPicker::updateTextEntry ()
-{
- // set values in spinners
- getChild<LLUICtrl>("rspin")->setValue(( getCurR () * 255.0f ) );
- getChild<LLUICtrl>("gspin")->setValue(( getCurG () * 255.0f ) );
- getChild<LLUICtrl>("bspin")->setValue(( getCurB () * 255.0f ) );
- getChild<LLUICtrl>("hspin")->setValue(( getCurH () * 360.0f ) );
- getChild<LLUICtrl>("sspin")->setValue(( getCurS () * 100.0f ) );
- getChild<LLUICtrl>("lspin")->setValue(( getCurL () * 100.0f ) );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLFloaterColorPicker::onTextEntryChanged ( LLUICtrl* ctrl )
-{
- // value in RGB boxes changed
- std::string name = ctrl->getName();
- if ( ( name == "rspin" ) || ( name == "gspin" ) || ( name == "bspin" ) )
- {
- // get current RGB
- F32 rVal, gVal, bVal;
- getCurRgb ( rVal, gVal, bVal );
-
- // update component value with new value from text
- if ( name == "rspin" )
- {
- rVal = (F32)ctrl->getValue().asReal() / 255.0f;
- }
- else
- if ( name == "gspin" )
- {
- gVal = (F32)ctrl->getValue().asReal() / 255.0f;
- }
- else
- if ( name == "bspin" )
- {
- bVal = (F32)ctrl->getValue().asReal() / 255.0f;
- }
-
- // update current RGB (and implicitly HSL)
- selectCurRgb ( rVal, gVal, bVal );
-
- updateTextEntry ();
- }
- else
- // value in HSL boxes changed
- if ( ( name == "hspin" ) || ( name == "sspin" ) || ( name == "lspin" ) )
- {
- // get current HSL
- F32 hVal, sVal, lVal;
- getCurHsl ( hVal, sVal, lVal );
-
- // update component value with new value from text
- if ( name == "hspin" )
- hVal = (F32)ctrl->getValue().asReal() / 360.0f;
- else
- if ( name == "sspin" )
- sVal = (F32)ctrl->getValue().asReal() / 100.0f;
- else
- if ( name == "lspin" )
- lVal = (F32)ctrl->getValue().asReal() / 100.0f;
-
- // update current HSL (and implicitly RGB)
- selectCurHsl ( hVal, sVal, lVal );
-
- updateTextEntry ();
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-bool LLFloaterColorPicker::updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
-{
- if ( xPosIn >= mRGBViewerImageLeft &&
- xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth &&
- yPosIn <= mRGBViewerImageTop &&
- yPosIn >= mRGBViewerImageTop - mRGBViewerImageHeight )
- {
- // update HSL (and therefore RGB) based on new H & S and current L
- selectCurHsl ( ( ( F32 )xPosIn - ( F32 )mRGBViewerImageLeft ) / ( F32 )mRGBViewerImageWidth,
- ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight,
- getCurL () );
-
- // indicate a value changed
- return true;
- }
- else
- if ( xPosIn >= mLumRegionLeft &&
- xPosIn <= mLumRegionLeft + mLumRegionWidth &&
- yPosIn <= mLumRegionTop &&
- yPosIn >= mLumRegionTop - mLumRegionHeight )
- {
-
- // update HSL (and therefore RGB) based on current HS and new L
- selectCurHsl ( getCurH (),
- getCurS (),
- ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight );
-
- // indicate a value changed
- return true;
- }
-
- return false;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-bool LLFloaterColorPicker::handleMouseDown ( S32 x, S32 y, MASK mask )
-{
- // make it the frontmost
- gFloaterView->bringToFront(this);
-
- // rect containing RGB area
- LLRect rgbAreaRect ( mRGBViewerImageLeft,
- mRGBViewerImageTop,
- mRGBViewerImageLeft + mRGBViewerImageWidth,
- mRGBViewerImageTop - mRGBViewerImageHeight );
-
- if ( rgbAreaRect.pointInRect ( x, y ) )
- {
- gFocusMgr.setMouseCapture(this);
- // mouse button down
- setMouseDownInHueRegion ( true );
-
- // update all values based on initial click
- updateRgbHslFromPoint ( x, y );
-
- // required by base class
- return true;
- }
-
- // rect containing RGB area
- LLRect lumAreaRect ( mLumRegionLeft,
- mLumRegionTop,
- mLumRegionLeft + mLumRegionWidth + mLumMarkerSize,
- mLumRegionTop - mLumRegionHeight );
-
- if ( lumAreaRect.pointInRect ( x, y ) )
- {
- gFocusMgr.setMouseCapture(this);
- // mouse button down
- setMouseDownInLumRegion ( true );
-
- // required by base class
- return true;
- }
-
- // rect containing swatch area
- LLRect swatchRect ( mSwatchRegionLeft,
- mSwatchRegionTop,
- mSwatchRegionLeft + mSwatchRegionWidth,
- mSwatchRegionTop - mSwatchRegionHeight );
-
- setMouseDownInSwatch( false );
- if ( swatchRect.pointInRect ( x, y ) )
- {
- setMouseDownInSwatch( true );
-
- // required - dont drag windows here.
- return true;
- }
-
- // rect containing palette area
- LLRect paletteRect ( mPaletteRegionLeft,
- mPaletteRegionTop,
- mPaletteRegionLeft + mPaletteRegionWidth,
- mPaletteRegionTop - mPaletteRegionHeight );
-
- if ( paletteRect.pointInRect ( x, y ) )
- {
- // release keyboard focus so we can change text values
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- mSelectBtn->setFocus(true);
- }
-
- // calculate which palette index we selected
- S32 c = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
- S32 r = ( ( y - ( mPaletteRegionTop - mPaletteRegionHeight ) ) * numPaletteRows ) / mPaletteRegionHeight;
-
- U32 index = ( numPaletteRows - r - 1 ) * numPaletteColumns + c;
-
- if ( index <= mPalette.size () )
- {
- LLColor4 selected = *mPalette [ index ];
-
- selectCurRgb ( selected [ 0 ], selected [ 1 ], selected [ 2 ] );
-
- if (mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
-
- updateTextEntry ();
- }
-
- return true;
- }
-
- // dispatch to base class for the rest of things
-
- return LLFloater::handleMouseDown ( x, y, mask );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-bool LLFloaterColorPicker::handleHover ( S32 x, S32 y, MASK mask )
-{
- // if we're the front most window
- if ( isFrontmost () )
- {
- // mouse was pressed within region
- if ( getMouseDownInHueRegion() || getMouseDownInLumRegion())
- {
- S32 clamped_x, clamped_y;
- if (getMouseDownInHueRegion())
- {
- clamped_x = llclamp(x, mRGBViewerImageLeft, mRGBViewerImageLeft + mRGBViewerImageWidth);
- clamped_y = llclamp(y, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBViewerImageTop);
- }
- else
- {
- clamped_x = llclamp(x, mLumRegionLeft, mLumRegionLeft + mLumRegionWidth);
- clamped_y = llclamp(y, mLumRegionTop - mLumRegionHeight, mLumRegionTop);
- }
-
- // update the stored RGB/HSL values using the mouse position - returns true if RGB was updated
- if ( updateRgbHslFromPoint ( clamped_x, clamped_y ) )
- {
- // update text entry fields
- updateTextEntry ();
-
- // RN: apparently changing color when dragging generates too much traffic and results in sporadic updates
- //// commit changed color to swatch subject
- //// REVIEW: this gets sent each time a color changes - is this okay ?
- //if (mApplyImmediateCheck->get())
- //{
- // LLColorSwatchCtrl::onColorChanged ( getSwatch () );
- //}
- }
- }
-
- highlightEntry = -1;
-
- if ( mMouseDownInSwatch )
- {
- getWindow()->setCursor ( UI_CURSOR_ARROWDRAG );
-
- // if cursor if over a palette entry
- LLRect paletteRect ( mPaletteRegionLeft,
- mPaletteRegionTop,
- mPaletteRegionLeft + mPaletteRegionWidth,
- mPaletteRegionTop - mPaletteRegionHeight );
-
- if ( paletteRect.pointInRect ( x, y ) )
- {
- // find row/column in palette
- S32 xOffset = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth;
- S32 yOffset = ( ( mPaletteRegionTop - y - 1 ) * numPaletteRows ) / mPaletteRegionHeight;
-
- // calculate the entry 0..n-1 to highlight and set variable to next draw() picks it up
- highlightEntry = xOffset + yOffset * numPaletteColumns;
- }
-
- return true;
- }
- }
-
- // dispatch to base class for the rest of things
- return LLFloater::handleHover ( x, y, mask );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// reverts state once mouse button is released
-bool LLFloaterColorPicker::handleMouseUp ( S32 x, S32 y, MASK mask )
-{
- getWindow()->setCursor ( UI_CURSOR_ARROW );
-
- if (getMouseDownInHueRegion() || getMouseDownInLumRegion())
- {
- if (mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
- }
-
- // rect containing palette area
- LLRect paletteRect ( mPaletteRegionLeft,
- mPaletteRegionTop,
- mPaletteRegionLeft + mPaletteRegionWidth,
- mPaletteRegionTop - mPaletteRegionHeight );
-
- if ( paletteRect.pointInRect ( x, y ) )
- {
- if ( mMouseDownInSwatch )
- {
- S32 curEntry = 0;
- for ( S32 row = 0; row < numPaletteRows; ++row )
- {
- for ( S32 column = 0; column < numPaletteColumns; ++column )
- {
- S32 left = mPaletteRegionLeft + ( mPaletteRegionWidth * column ) / numPaletteColumns;
- S32 top = mPaletteRegionTop - ( mPaletteRegionHeight * row ) / numPaletteRows;
- S32 right = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( column + 1 ) ) / numPaletteColumns );
- S32 bottom = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( row + 1 ) ) / numPaletteRows );
-
- // rect is flipped vertically when testing here
- LLRect dropRect ( left, top, right, bottom );
-
- if ( dropRect.pointInRect ( x, y ) )
- {
- if ( mPalette [ curEntry ] )
- {
- delete mPalette [ curEntry ];
-
- mPalette [ curEntry ] = new LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f );
-
- // save off color
- std::ostringstream codec;
- codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << curEntry + 1;
- const std::string s ( codec.str () );
- LLUIColorTable::instance().setColor(s, *mPalette [ curEntry ] );
- }
- }
-
- ++curEntry;
- }
- }
- }
- }
-
- // mouse button not down anymore
- setMouseDownInHueRegion ( false );
- setMouseDownInLumRegion ( false );
-
- // mouse button not down in color swatch anymore
- mMouseDownInSwatch = false;
-
- if (hasMouseCapture())
- {
- gFocusMgr.setMouseCapture(NULL);
- }
-
- // dispatch to base class for the rest of things
- return LLFloater::handleMouseUp ( x, y, mask );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// cancel current color selection, revert to original and close picker
-void LLFloaterColorPicker::cancelSelection ()
-{
- // restore the previous color selection
- setCurRgb ( getOrigR (), getOrigG (), getOrigB () );
-
- // update in world item with original color via current swatch
- LLColorSwatchCtrl::onColorChanged( getSwatch(), LLColorSwatchCtrl::COLOR_CANCEL );
-
- // hide picker dialog
- this->setVisible ( false );
-}
-
-void LLFloaterColorPicker::setMouseDownInHueRegion ( bool mouse_down_in_region )
-{
- mMouseDownInHueRegion = mouse_down_in_region;
- if (mouse_down_in_region)
- {
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- // get focus out of spinners so that they can update freely
- mSelectBtn->setFocus(true);
- }
- }
-}
-
-void LLFloaterColorPicker::setMouseDownInLumRegion ( bool mouse_down_in_region )
-{
- mMouseDownInLumRegion = mouse_down_in_region;
- if (mouse_down_in_region)
- {
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- // get focus out of spinners so that they can update freely
- mSelectBtn->setFocus(true);
- }
- }
-}
-
-void LLFloaterColorPicker::setMouseDownInSwatch (bool mouse_down_in_swatch)
-{
- mMouseDownInSwatch = mouse_down_in_swatch;
- if (mouse_down_in_swatch)
- {
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- // get focus out of spinners so that they can update freely
- mSelectBtn->setFocus(true);
- }
- }
-}
-
-void LLFloaterColorPicker::setActive(bool active)
-{
- // shut down pipette tool if active
- if (!active && mPipetteBtn->getToggleState())
- {
- stopUsingPipette();
- }
- mActive = active;
-}
-
-void LLFloaterColorPicker::stopUsingPipette()
-{
- if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance())
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
-}
+/** + * @file llfloatercolorpicker.cpp + * @brief Generic system color picker + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatercolorpicker.h" + +// Viewer project includes +#include "lltoolmgr.h" +#include "lltoolpipette.h" +#include "llviewercontrol.h" +#include "llworld.h" + +// Linden library includes +#include "llfontgl.h" +#include "llsys.h" +#include "llgl.h" +#include "llrender.h" +#include "v3dmath.h" +#include "lldir.h" +#include "llui.h" +#include "lllineeditor.h" +#include "v4coloru.h" +#include "llbutton.h" +#include "lluictrlfactory.h" +#include "llgl.h" +#include "llpointer.h" +#include "llimage.h" +#include "llmousehandler.h" +#include "llglheaders.h" +#include "llcheckboxctrl.h" +#include "lltextbox.h" +#include "lluiconstants.h" +#include "llfocusmgr.h" +#include "lldraghandle.h" +#include "llwindow.h" + +// System includes +#include <sstream> +#include <iomanip> + +////////////////////////////////////////////////////////////////////////////// +// +// Class LLFloaterColorPicker +// +////////////////////////////////////////////////////////////////////////////// + +LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, bool show_apply_immediate ) + : LLFloater(LLSD()), + mComponents ( 3 ), + mMouseDownInLumRegion ( false ), + mMouseDownInHueRegion ( false ), + mMouseDownInSwatch ( false ), + // *TODO: Specify this in XML + mRGBViewerImageLeft ( 140 ), + mRGBViewerImageTop ( 356 ), + mRGBViewerImageWidth ( 256 ), + mRGBViewerImageHeight ( 256 ), + mLumRegionLeft ( mRGBViewerImageLeft + mRGBViewerImageWidth + 16 ), + mLumRegionTop ( mRGBViewerImageTop ), + mLumRegionWidth ( 16 ), + mLumRegionHeight ( mRGBViewerImageHeight ), + mLumMarkerSize ( 6 ), + // *TODO: Specify this in XML + mSwatchRegionLeft ( 12 ), + mSwatchRegionTop ( 190 ), + mSwatchRegionWidth ( 116 ), + mSwatchRegionHeight ( 60 ), + mSwatchView ( NULL ), + // *TODO: Specify this in XML + numPaletteColumns ( 16 ), + numPaletteRows ( 2 ), + highlightEntry ( -1 ), + mPaletteRegionLeft ( 11 ), + mPaletteRegionTop ( 100 - 8 ), + mPaletteRegionWidth ( mLumRegionLeft + mLumRegionWidth - 10 ), + mPaletteRegionHeight ( 40 ), + mSwatch ( swatch ), + mActive ( true ), + mCanApplyImmediately ( show_apply_immediate ), + mContextConeOpacity ( 0.f ), + mContextConeInAlpha (CONTEXT_CONE_IN_ALPHA), + mContextConeOutAlpha (CONTEXT_CONE_OUT_ALPHA), + mContextConeFadeTime (CONTEXT_CONE_FADE_TIME) +{ + buildFromFile ( "floater_color_picker.xml"); + + // create user interface for this picker + createUI (); + + if (!mCanApplyImmediately) + { + mApplyImmediateCheck->setEnabled(false); + mApplyImmediateCheck->set(false); + } +} + +LLFloaterColorPicker::~LLFloaterColorPicker() +{ + // destroy the UI we created + destroyUI (); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::createUI () +{ + // create RGB type area (not really RGB but it's got R,G & B in it.,.. + + LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents ); + LLImageDataLock lock(raw); + + U8* bits = raw->getData(); + S32 linesize = mRGBViewerImageWidth * mComponents; + for ( S32 y = 0; y < mRGBViewerImageHeight; ++y ) + { + for ( S32 x = 0; x < linesize; x += mComponents ) + { + F32 rVal, gVal, bVal; + + hslToRgb ( (F32)x / (F32) ( linesize - 1 ), + (F32)y / (F32) ( mRGBViewerImageHeight - 1 ), + 0.5f, + rVal, + gVal, + bVal ); + + * ( bits + x + y * linesize + 0 ) = ( U8 )( rVal * 255.0f ); + * ( bits + x + y * linesize + 1 ) = ( U8 )( gVal * 255.0f ); + * ( bits + x + y * linesize + 2 ) = ( U8 )( bVal * 255.0f ); + } + } + mRGBImage = LLViewerTextureManager::getLocalTexture( (LLImageRaw*)raw, false ); + gGL.getTexUnit(0)->bind(mRGBImage); + mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP); + + // create palette + for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each ) + { + mPalette.push_back(new LLColor4(LLUIColorTable::instance().getColor(llformat("ColorPaletteEntry%02d", each + 1)))); + } +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::showUI () +{ + openFloater(getKey()); + setVisible ( true ); + setFocus ( true ); + + // HACK: if system color picker is required - close the SL one we made and use default system dialog + if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) ) + { + LLColorSwatchCtrl* swatch = getSwatch (); + + setVisible ( false ); + + // code that will get switched in for default system color picker + if ( swatch ) + { + // Todo: this needs to be threaded for viewer not to timeout + LLColor4 curCol = swatch->get (); + send_agent_pause(); + bool commit = getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); + send_agent_resume(); + + if (commit) + { + setOrigRgb(curCol[0], curCol[1], curCol[2]); + setCurRgb(curCol[0], curCol[1], curCol[2]); + + LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_SELECT); + } + else + { + LLColorSwatchCtrl::onColorChanged(swatch, LLColorSwatchCtrl::COLOR_CANCEL); + } + } + + closeFloater(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// called after the dialog is rendered +bool LLFloaterColorPicker::postBuild() +{ + mCancelBtn = getChild<LLButton>( "cancel_btn" ); + mCancelBtn->setClickedCallback ( onClickCancel, this ); + + mSelectBtn = getChild<LLButton>( "select_btn"); + mSelectBtn->setClickedCallback ( onClickSelect, this ); + mSelectBtn->setFocus ( true ); + + mPipetteBtn = getChild<LLButton>("color_pipette" ); + + mPipetteBtn->setImages(std::string("eye_button_inactive.tga"), std::string("eye_button_active.tga")); + + mPipetteBtn->setCommitCallback( boost::bind(&LLFloaterColorPicker::onClickPipette, this )); + + mApplyImmediateCheck = getChild<LLCheckBoxCtrl>("apply_immediate"); + mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately")); + mApplyImmediateCheck->setCommitCallback(onImmediateCheck, this); + + childSetCommitCallback("rspin", onTextCommit, (void*)this ); + childSetCommitCallback("gspin", onTextCommit, (void*)this ); + childSetCommitCallback("bspin", onTextCommit, (void*)this ); + childSetCommitCallback("hspin", onTextCommit, (void*)this ); + childSetCommitCallback("sspin", onTextCommit, (void*)this ); + childSetCommitCallback("lspin", onTextCommit, (void*)this ); + + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1)); + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn ) +{ + // under some circumstances, we get rogue values that can be calmed by clamping... + rValIn = llclamp ( rValIn, 0.0f, 1.0f ); + gValIn = llclamp ( gValIn, 0.0f, 1.0f ); + bValIn = llclamp ( bValIn, 0.0f, 1.0f ); + + // store initial value in case cancel or revert is selected + setOrigRgb ( rValIn, gValIn, bValIn ); + + // starting point for current value to + setCurRgb ( rValIn, gValIn, bValIn ); + + // unpdate text entry fields + updateTextEntry (); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::destroyUI () +{ + // shut down pipette tool if active + stopUsingPipette(); + + // delete palette we created + std::vector < LLColor4* >::iterator iter = mPalette.begin (); + while ( iter != mPalette.end () ) + { + delete ( *iter ); + ++iter; + } + + if ( mSwatchView ) + { + this->removeChild ( mSwatchView ); + mSwatchView->die();; + mSwatchView = NULL; + } +} + + +////////////////////////////////////////////////////////////////////////////// +// +F32 LLFloaterColorPicker::hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) +{ + if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; + if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; + if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); + if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); + if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); + return ( val1In ); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut ) +{ + if ( sValIn < 0.00001f ) + { + rValOut = lValIn; + gValOut = lValIn; + bValOut = lValIn; + } + else + { + F32 interVal1; + F32 interVal2; + + if ( lValIn < 0.5f ) + interVal2 = lValIn * ( 1.0f + sValIn ); + else + interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); + + interVal1 = 2.0f * lValIn - interVal2; + + rValOut = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); + gValOut = hueToRgb ( interVal1, interVal2, hValIn ); + bValOut = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// mutator for original RGB value +void LLFloaterColorPicker::setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn ) +{ + origR = origRIn; + origG = origGIn; + origB = origBIn; +} + +////////////////////////////////////////////////////////////////////////////// +// accessor for original RGB value +void LLFloaterColorPicker::getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut ) +{ + origROut = origR; + origGOut = origG; + origBOut = origB; +} + +////////////////////////////////////////////////////////////////////////////// +// mutator for current RGB value +void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) +{ + // save current RGB + curR = curRIn; + curG = curGIn; + curB = curBIn; + + // update corresponding HSL values and + LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL); + + // color changed so update text fields + updateTextEntry(); +} + +////////////////////////////////////////////////////////////////////////////// +// accessor for current RGB value +void LLFloaterColorPicker::getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut ) +{ + curROut = curR; + curGOut = curG; + curBOut = curB; +} + +////////////////////////////////////////////////////////////////////////////// +// mutator for current HSL value +void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) +{ + // save current HSL + curH = curHIn; + curS = curSIn; + curL = curLIn; + + // update corresponding RGB values and + hslToRgb ( curH, curS, curL, curR, curG, curB ); +} + +////////////////////////////////////////////////////////////////////////////// +// accessor for current HSL value +void LLFloaterColorPicker::getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut ) +{ + curHOut = curH; + curSOut = curS; + curLOut = curL; +} + +////////////////////////////////////////////////////////////////////////////// +// called when 'cancel' clicked +void LLFloaterColorPicker::onClickCancel ( void* data ) +{ + if (data) + { + LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data; + + if ( self ) + { + self->cancelSelection(); + self->closeFloater(); + } + } +} + +////////////////////////////////////////////////////////////////////////////// +// called when 'select' clicked +void LLFloaterColorPicker::onClickSelect ( void* data ) +{ + if (data) + { + LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data; + + if ( self ) + { + // apply to selection + LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_SELECT ); + self->closeFloater(); + } + } +} + +void LLFloaterColorPicker::onClickPipette( ) +{ + bool pipette_active = mPipetteBtn->getToggleState(); + pipette_active = !pipette_active; + if (pipette_active) + { + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// called when 'text is committed' - i,e. focus moves from a text field +void LLFloaterColorPicker::onTextCommit ( LLUICtrl* ctrl, void* data ) +{ + if ( data ) + { + LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data; + if ( self ) + { + self->onTextEntryChanged ( ctrl ); + } + } +} + +void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data) +{ + LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data; + if (self) + { + gSavedSettings.setBOOL("ApplyColorImmediately", self->mApplyImmediateCheck->get()); + if (self->mApplyImmediateCheck->get() && self->isColorChanged()) + { + LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } + } +} + +void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te ) +{ + // Pipete + selectCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]); +} + +void LLFloaterColorPicker::onMouseCaptureLost() +{ + setMouseDownInHueRegion(false); + setMouseDownInLumRegion(false); +} + +F32 LLFloaterColorPicker::getSwatchTransparency() +{ + // If the floater is focused, don't apply its alpha to the color swatch (STORM-676). + return getTransparencyType() == TT_ACTIVE ? 1.f : LLFloater::getCurrentTransparency(); +} + +bool LLFloaterColorPicker::isColorChanged() +{ + return ((getOrigR() != getCurR()) || (getOrigG() != getCurG()) || (getOrigB() != getCurB())); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::draw() +{ + static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, mSwatch, mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha); + + mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); + mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately); + mSelectBtn->setEnabled(mActive); + + // base floater stuff + LLFloater::draw (); + + const F32 alpha = getSwatchTransparency(); + + // draw image for RGB area (not really RGB but you'll see what I mean... + gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white % alpha); + + // update 'cursor' into RGB Section + S32 xPos = ( S32 ) ( ( F32 )mRGBViewerImageWidth * getCurH () ) - 8; + S32 yPos = ( S32 ) ( ( F32 )mRGBViewerImageHeight * getCurS () ) - 8; + gl_line_2d ( mRGBViewerImageLeft + xPos, + mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8, + mRGBViewerImageLeft + xPos + 16, + mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 8, + LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) ); + + gl_line_2d ( mRGBViewerImageLeft + xPos + 8, + mRGBViewerImageTop - mRGBViewerImageHeight + yPos, + mRGBViewerImageLeft + xPos + 8, + mRGBViewerImageTop - mRGBViewerImageHeight + yPos + 16, + LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ) ); + + // create rgb area outline + gl_rect_2d ( mRGBViewerImageLeft, + mRGBViewerImageTop - mRGBViewerImageHeight, + mRGBViewerImageLeft + mRGBViewerImageWidth + 1, + mRGBViewerImageTop, + LLColor4 ( 0.0f, 0.0f, 0.0f, alpha ), + false ); + + // draw luminance slider + for ( S32 y = 0; y < mLumRegionHeight; ++y ) + { + F32 rValSlider, gValSlider, bValSlider; + hslToRgb ( getCurH (), getCurS (), ( F32 )y / ( F32 )mLumRegionHeight, rValSlider, gValSlider, bValSlider ); + + gl_rect_2d( mLumRegionLeft, + mLumRegionTop - mLumRegionHeight + y, + mLumRegionLeft + mLumRegionWidth, + mLumRegionTop - mLumRegionHeight + y - 1, + LLColor4 ( rValSlider, gValSlider, bValSlider, alpha ) ); + } + + + // draw luninance marker + S32 startX = mLumRegionLeft + mLumRegionWidth; + S32 startY = mLumRegionTop - mLumRegionHeight + ( S32 ) ( mLumRegionHeight * getCurL () ); + gl_triangle_2d ( startX, startY, + startX + mLumMarkerSize, startY - mLumMarkerSize, + startX + mLumMarkerSize, startY + mLumMarkerSize, + LLColor4 ( 0.75f, 0.75f, 0.75f, 1.0f ), true ); + + // draw luminance slider outline + gl_rect_2d ( mLumRegionLeft, + mLumRegionTop - mLumRegionHeight, + mLumRegionLeft + mLumRegionWidth + 1, + mLumRegionTop, + LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), + false ); + + // draw selected color swatch + gl_rect_2d ( mSwatchRegionLeft, + mSwatchRegionTop - mSwatchRegionHeight, + mSwatchRegionLeft + mSwatchRegionWidth, + mSwatchRegionTop, + LLColor4 ( getCurR (), getCurG (), getCurB (), alpha ), + true ); + + // draw selected color swatch outline + gl_rect_2d ( mSwatchRegionLeft, + mSwatchRegionTop - mSwatchRegionHeight, + mSwatchRegionLeft + mSwatchRegionWidth + 1, + mSwatchRegionTop, + LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), + false ); + + // color palette code is a little more involved so break it out into its' own method + drawPalette (); +} + +////////////////////////////////////////////////////////////////////////////// +// find a complimentary color to the one passed in that can be used to highlight +const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& backgroundColor ) +{ + // going to base calculation on luminance + F32 hVal, sVal, lVal; + backgroundColor.calcHSL(&hVal, &sVal, &lVal); + hVal *= 360.f; + sVal *= 100.f; + lVal *= 100.f; + + // fairly simple heuristic for now...! + if ( lVal < 0.5f ) + { + return LLColor4::white; + } + + return LLColor4::black; +} + +////////////////////////////////////////////////////////////////////////////// +// set current RGB and rise change event if needed. +void LLFloaterColorPicker::selectCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) +{ + setCurRgb(curRIn, curGIn, curBIn); + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// set current HSL and rise change event if needed. +void LLFloaterColorPicker::selectCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) +{ + setCurHsl(curHIn, curSIn, curLIn); + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// draw color palette +void LLFloaterColorPicker::drawPalette () +{ + S32 curEntry = 0; + const F32 alpha = getSwatchTransparency(); + + for ( S32 y = 0; y < numPaletteRows; ++y ) + { + for ( S32 x = 0; x < numPaletteColumns; ++x ) + { + // calculate position + S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * x ) / numPaletteColumns; + S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * y ) / numPaletteRows; + S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( x + 1 ) ) / numPaletteColumns ); + S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( y + 1 ) ) / numPaletteRows ); + + // draw palette entry color + if ( mPalette [ curEntry ] ) + { + gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ] % alpha, true ); + gl_rect_2d ( x1 + 1, y1 - 1, x2 - 1, y2 + 1, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), false ); + } + } + } + + // if there is something to highlight (mouse down in swatch & hovering over palette) + if ( highlightEntry >= 0 ) + { + // extract row/column from palette index + S32 entryColumn = highlightEntry % numPaletteColumns; + S32 entryRow = highlightEntry / numPaletteColumns; + + // calculate position of this entry + S32 x1 = mPaletteRegionLeft + ( mPaletteRegionWidth * entryColumn ) / numPaletteColumns; + S32 y1 = mPaletteRegionTop - ( mPaletteRegionHeight * entryRow ) / numPaletteRows; + S32 x2 = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( entryColumn + 1 ) ) / numPaletteColumns ); + S32 y2 = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( entryRow + 1 ) ) / numPaletteRows ); + + // center position of entry + S32 xCenter = x1 + ( x2 - x1 ) / 2; + S32 yCenter = y1 - ( y1 - y2 ) / 2; + + // find a color that works well as a highlight color + LLColor4 hlColor ( getComplimentaryColor ( *mPalette [ highlightEntry ] ) ); + + // mark a cross for entry that is being hovered + gl_line_2d ( xCenter - 4, yCenter - 4, xCenter + 4, yCenter + 4, hlColor ); + gl_line_2d ( xCenter + 4, yCenter - 4, xCenter - 4, yCenter + 4, hlColor ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// update text entry values for RGB/HSL (can't be done in ::draw () since this overwrites input +void LLFloaterColorPicker::updateTextEntry () +{ + // set values in spinners + getChild<LLUICtrl>("rspin")->setValue(( getCurR () * 255.0f ) ); + getChild<LLUICtrl>("gspin")->setValue(( getCurG () * 255.0f ) ); + getChild<LLUICtrl>("bspin")->setValue(( getCurB () * 255.0f ) ); + getChild<LLUICtrl>("hspin")->setValue(( getCurH () * 360.0f ) ); + getChild<LLUICtrl>("sspin")->setValue(( getCurS () * 100.0f ) ); + getChild<LLUICtrl>("lspin")->setValue(( getCurL () * 100.0f ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterColorPicker::onTextEntryChanged ( LLUICtrl* ctrl ) +{ + // value in RGB boxes changed + std::string name = ctrl->getName(); + if ( ( name == "rspin" ) || ( name == "gspin" ) || ( name == "bspin" ) ) + { + // get current RGB + F32 rVal, gVal, bVal; + getCurRgb ( rVal, gVal, bVal ); + + // update component value with new value from text + if ( name == "rspin" ) + { + rVal = (F32)ctrl->getValue().asReal() / 255.0f; + } + else + if ( name == "gspin" ) + { + gVal = (F32)ctrl->getValue().asReal() / 255.0f; + } + else + if ( name == "bspin" ) + { + bVal = (F32)ctrl->getValue().asReal() / 255.0f; + } + + // update current RGB (and implicitly HSL) + selectCurRgb ( rVal, gVal, bVal ); + + updateTextEntry (); + } + else + // value in HSL boxes changed + if ( ( name == "hspin" ) || ( name == "sspin" ) || ( name == "lspin" ) ) + { + // get current HSL + F32 hVal, sVal, lVal; + getCurHsl ( hVal, sVal, lVal ); + + // update component value with new value from text + if ( name == "hspin" ) + hVal = (F32)ctrl->getValue().asReal() / 360.0f; + else + if ( name == "sspin" ) + sVal = (F32)ctrl->getValue().asReal() / 100.0f; + else + if ( name == "lspin" ) + lVal = (F32)ctrl->getValue().asReal() / 100.0f; + + // update current HSL (and implicitly RGB) + selectCurHsl ( hVal, sVal, lVal ); + + updateTextEntry (); + } +} + +////////////////////////////////////////////////////////////////////////////// +// +bool LLFloaterColorPicker::updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn ) +{ + if ( xPosIn >= mRGBViewerImageLeft && + xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth && + yPosIn <= mRGBViewerImageTop && + yPosIn >= mRGBViewerImageTop - mRGBViewerImageHeight ) + { + // update HSL (and therefore RGB) based on new H & S and current L + selectCurHsl ( ( ( F32 )xPosIn - ( F32 )mRGBViewerImageLeft ) / ( F32 )mRGBViewerImageWidth, + ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight, + getCurL () ); + + // indicate a value changed + return true; + } + else + if ( xPosIn >= mLumRegionLeft && + xPosIn <= mLumRegionLeft + mLumRegionWidth && + yPosIn <= mLumRegionTop && + yPosIn >= mLumRegionTop - mLumRegionHeight ) + { + + // update HSL (and therefore RGB) based on current HS and new L + selectCurHsl ( getCurH (), + getCurS (), + ( ( F32 )yPosIn - ( ( F32 )mRGBViewerImageTop - ( F32 )mRGBViewerImageHeight ) ) / ( F32 )mRGBViewerImageHeight ); + + // indicate a value changed + return true; + } + + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// +bool LLFloaterColorPicker::handleMouseDown ( S32 x, S32 y, MASK mask ) +{ + // make it the frontmost + gFloaterView->bringToFront(this); + + // rect containing RGB area + LLRect rgbAreaRect ( mRGBViewerImageLeft, + mRGBViewerImageTop, + mRGBViewerImageLeft + mRGBViewerImageWidth, + mRGBViewerImageTop - mRGBViewerImageHeight ); + + if ( rgbAreaRect.pointInRect ( x, y ) ) + { + gFocusMgr.setMouseCapture(this); + // mouse button down + setMouseDownInHueRegion ( true ); + + // update all values based on initial click + updateRgbHslFromPoint ( x, y ); + + // required by base class + return true; + } + + // rect containing RGB area + LLRect lumAreaRect ( mLumRegionLeft, + mLumRegionTop, + mLumRegionLeft + mLumRegionWidth + mLumMarkerSize, + mLumRegionTop - mLumRegionHeight ); + + if ( lumAreaRect.pointInRect ( x, y ) ) + { + gFocusMgr.setMouseCapture(this); + // mouse button down + setMouseDownInLumRegion ( true ); + + // required by base class + return true; + } + + // rect containing swatch area + LLRect swatchRect ( mSwatchRegionLeft, + mSwatchRegionTop, + mSwatchRegionLeft + mSwatchRegionWidth, + mSwatchRegionTop - mSwatchRegionHeight ); + + setMouseDownInSwatch( false ); + if ( swatchRect.pointInRect ( x, y ) ) + { + setMouseDownInSwatch( true ); + + // required - dont drag windows here. + return true; + } + + // rect containing palette area + LLRect paletteRect ( mPaletteRegionLeft, + mPaletteRegionTop, + mPaletteRegionLeft + mPaletteRegionWidth, + mPaletteRegionTop - mPaletteRegionHeight ); + + if ( paletteRect.pointInRect ( x, y ) ) + { + // release keyboard focus so we can change text values + if (gFocusMgr.childHasKeyboardFocus(this)) + { + mSelectBtn->setFocus(true); + } + + // calculate which palette index we selected + S32 c = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth; + S32 r = ( ( y - ( mPaletteRegionTop - mPaletteRegionHeight ) ) * numPaletteRows ) / mPaletteRegionHeight; + + U32 index = ( numPaletteRows - r - 1 ) * numPaletteColumns + c; + + if ( index <= mPalette.size () ) + { + LLColor4 selected = *mPalette [ index ]; + + selectCurRgb ( selected [ 0 ], selected [ 1 ], selected [ 2 ] ); + + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } + + updateTextEntry (); + } + + return true; + } + + // dispatch to base class for the rest of things + + return LLFloater::handleMouseDown ( x, y, mask ); +} + +////////////////////////////////////////////////////////////////////////////// +// +bool LLFloaterColorPicker::handleHover ( S32 x, S32 y, MASK mask ) +{ + // if we're the front most window + if ( isFrontmost () ) + { + // mouse was pressed within region + if ( getMouseDownInHueRegion() || getMouseDownInLumRegion()) + { + S32 clamped_x, clamped_y; + if (getMouseDownInHueRegion()) + { + clamped_x = llclamp(x, mRGBViewerImageLeft, mRGBViewerImageLeft + mRGBViewerImageWidth); + clamped_y = llclamp(y, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBViewerImageTop); + } + else + { + clamped_x = llclamp(x, mLumRegionLeft, mLumRegionLeft + mLumRegionWidth); + clamped_y = llclamp(y, mLumRegionTop - mLumRegionHeight, mLumRegionTop); + } + + // update the stored RGB/HSL values using the mouse position - returns true if RGB was updated + if ( updateRgbHslFromPoint ( clamped_x, clamped_y ) ) + { + // update text entry fields + updateTextEntry (); + + // RN: apparently changing color when dragging generates too much traffic and results in sporadic updates + //// commit changed color to swatch subject + //// REVIEW: this gets sent each time a color changes - is this okay ? + //if (mApplyImmediateCheck->get()) + //{ + // LLColorSwatchCtrl::onColorChanged ( getSwatch () ); + //} + } + } + + highlightEntry = -1; + + if ( mMouseDownInSwatch ) + { + getWindow()->setCursor ( UI_CURSOR_ARROWDRAG ); + + // if cursor if over a palette entry + LLRect paletteRect ( mPaletteRegionLeft, + mPaletteRegionTop, + mPaletteRegionLeft + mPaletteRegionWidth, + mPaletteRegionTop - mPaletteRegionHeight ); + + if ( paletteRect.pointInRect ( x, y ) ) + { + // find row/column in palette + S32 xOffset = ( ( x - mPaletteRegionLeft ) * numPaletteColumns ) / mPaletteRegionWidth; + S32 yOffset = ( ( mPaletteRegionTop - y - 1 ) * numPaletteRows ) / mPaletteRegionHeight; + + // calculate the entry 0..n-1 to highlight and set variable to next draw() picks it up + highlightEntry = xOffset + yOffset * numPaletteColumns; + } + + return true; + } + } + + // dispatch to base class for the rest of things + return LLFloater::handleHover ( x, y, mask ); +} + +////////////////////////////////////////////////////////////////////////////// +// reverts state once mouse button is released +bool LLFloaterColorPicker::handleMouseUp ( S32 x, S32 y, MASK mask ) +{ + getWindow()->setCursor ( UI_CURSOR_ARROW ); + + if (getMouseDownInHueRegion() || getMouseDownInLumRegion()) + { + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } + } + + // rect containing palette area + LLRect paletteRect ( mPaletteRegionLeft, + mPaletteRegionTop, + mPaletteRegionLeft + mPaletteRegionWidth, + mPaletteRegionTop - mPaletteRegionHeight ); + + if ( paletteRect.pointInRect ( x, y ) ) + { + if ( mMouseDownInSwatch ) + { + S32 curEntry = 0; + for ( S32 row = 0; row < numPaletteRows; ++row ) + { + for ( S32 column = 0; column < numPaletteColumns; ++column ) + { + S32 left = mPaletteRegionLeft + ( mPaletteRegionWidth * column ) / numPaletteColumns; + S32 top = mPaletteRegionTop - ( mPaletteRegionHeight * row ) / numPaletteRows; + S32 right = ( mPaletteRegionLeft + ( mPaletteRegionWidth * ( column + 1 ) ) / numPaletteColumns ); + S32 bottom = ( mPaletteRegionTop - ( mPaletteRegionHeight * ( row + 1 ) ) / numPaletteRows ); + + // rect is flipped vertically when testing here + LLRect dropRect ( left, top, right, bottom ); + + if ( dropRect.pointInRect ( x, y ) ) + { + if ( mPalette [ curEntry ] ) + { + delete mPalette [ curEntry ]; + + mPalette [ curEntry ] = new LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f ); + + // save off color + std::ostringstream codec; + codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << curEntry + 1; + const std::string s ( codec.str () ); + LLUIColorTable::instance().setColor(s, *mPalette [ curEntry ] ); + } + } + + ++curEntry; + } + } + } + } + + // mouse button not down anymore + setMouseDownInHueRegion ( false ); + setMouseDownInLumRegion ( false ); + + // mouse button not down in color swatch anymore + mMouseDownInSwatch = false; + + if (hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + } + + // dispatch to base class for the rest of things + return LLFloater::handleMouseUp ( x, y, mask ); +} + +////////////////////////////////////////////////////////////////////////////// +// cancel current color selection, revert to original and close picker +void LLFloaterColorPicker::cancelSelection () +{ + // restore the previous color selection + setCurRgb ( getOrigR (), getOrigG (), getOrigB () ); + + // update in world item with original color via current swatch + LLColorSwatchCtrl::onColorChanged( getSwatch(), LLColorSwatchCtrl::COLOR_CANCEL ); + + // hide picker dialog + this->setVisible ( false ); +} + +void LLFloaterColorPicker::setMouseDownInHueRegion ( bool mouse_down_in_region ) +{ + mMouseDownInHueRegion = mouse_down_in_region; + if (mouse_down_in_region) + { + if (gFocusMgr.childHasKeyboardFocus(this)) + { + // get focus out of spinners so that they can update freely + mSelectBtn->setFocus(true); + } + } +} + +void LLFloaterColorPicker::setMouseDownInLumRegion ( bool mouse_down_in_region ) +{ + mMouseDownInLumRegion = mouse_down_in_region; + if (mouse_down_in_region) + { + if (gFocusMgr.childHasKeyboardFocus(this)) + { + // get focus out of spinners so that they can update freely + mSelectBtn->setFocus(true); + } + } +} + +void LLFloaterColorPicker::setMouseDownInSwatch (bool mouse_down_in_swatch) +{ + mMouseDownInSwatch = mouse_down_in_swatch; + if (mouse_down_in_swatch) + { + if (gFocusMgr.childHasKeyboardFocus(this)) + { + // get focus out of spinners so that they can update freely + mSelectBtn->setFocus(true); + } + } +} + +void LLFloaterColorPicker::setActive(bool active) +{ + // shut down pipette tool if active + if (!active && mPipetteBtn->getToggleState()) + { + stopUsingPipette(); + } + mActive = active; +} + +void LLFloaterColorPicker::stopUsingPipette() +{ + if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()) + { + LLToolMgr::getInstance()->clearTransientTool(); + } +} |