Color Picker

This commit is contained in:
Lopuska 2015-01-21 23:14:53 +01:00 committed by Azaezel
parent 39f0e269d6
commit 03109c9d6d
9 changed files with 2424 additions and 642 deletions

View file

@ -71,6 +71,18 @@ GuiColorPickerCtrl::GuiColorPickerCtrl()
mSelectorGap = 1;
mActionOnMove = false;
mShowReticle = true;
mSelectColor = false;
mSetColor = mSetColor.BLACK;
mBitmap = NULL;
}
GuiColorPickerCtrl::~GuiColorPickerCtrl()
{
if (mBitmap)
{
delete mBitmap;
mBitmap = NULL;
}
}
//--------------------------------------------------------------------------
@ -331,60 +343,180 @@ void GuiColorPickerCtrl::renderColorBox(RectI &bounds)
void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
{
if (mStateBlock.isNull())
{
GFXStateBlockDesc desc;
desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
desc.setZReadWrite(false);
desc.zWriteEnable = false;
desc.setCullMode(GFXCullNone);
mStateBlock = GFX->createStateBlock( desc );
}
if (mStateBlock.isNull())
{
GFXStateBlockDesc desc;
desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
desc.setZReadWrite(false);
desc.zWriteEnable = false;
desc.setCullMode(GFXCullNone);
mStateBlock = GFX->createStateBlock(desc);
}
RectI boundsRect(offset, getExtent());
renderColorBox(boundsRect);
RectI boundsRect(offset, getExtent());
renderColorBox(boundsRect);
if (mPositionChanged)
{
mPositionChanged = false;
Point2I extent = getRoot()->getExtent();
// If we are anything but a pallete, change the pick color
if (mDisplayMode != pPallet)
{
Point2I resolution = getRoot()->getExtent();
if (mPositionChanged || mBitmap == NULL)
{
bool nullBitmap = false;
U32 buf_x = offset.x + mSelectorPos.x + 1;
U32 buf_y = resolution.y - ( extent.y - ( offset.y + mSelectorPos.y + 1 ) );
if (mPositionChanged == false && mBitmap == NULL)
nullBitmap = true;
GFXTexHandle bb( resolution.x,
resolution.y,
GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) );
Point2I tmpPt( buf_x, buf_y );
mPositionChanged = false;
Point2I extent = getRoot()->getExtent();
// If we are anything but a pallete, change the pick color
if (mDisplayMode != pPallet)
{
Point2I resolution = getRoot()->getExtent();
GFXTarget *targ = GFX->getActiveRenderTarget();
targ->resolveTo( bb );
GBitmap bmp( bb.getWidth(), bb.getHeight() );
U32 buf_x = offset.x + mSelectorPos.x + 1;
U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y + 1));
bb.copyToBmp( &bmp );
//bmp.writePNGDebug( "foo.png" );
GFXTexHandle bb(resolution.x,
resolution.y,
GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__));
ColorI tmp;
bmp.getColor( buf_x, buf_y, tmp );
Point2I tmpPt(buf_x, buf_y);
mPickColor = (ColorF)tmp;
GFXTarget *targ = GFX->getActiveRenderTarget();
targ->resolveTo(bb);
// Now do onAction() if we are allowed
if (mActionOnMove)
onAction();
}
}
//render the children
renderChildControls( offset, updateRect);
if (mBitmap)
{
delete mBitmap;
mBitmap = NULL;
}
mBitmap = new GBitmap(bb.getWidth(), bb.getHeight());
bb.copyToBmp(mBitmap);
//bmp.writePNGDebug( "foo.png" );
if (!nullBitmap)
{
if (mSelectColor)
{
Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap);
mSetColor = mSetColor.BLACK;
mSelectColor = false;
setSelectorPos(pos);
}
else
{
ColorI tmp;
mBitmap->getColor(buf_x, buf_y, tmp);
mPickColor = (ColorF)tmp;
// Now do onAction() if we are allowed
if (mActionOnMove)
onAction();
}
}
}
}
//render the children
renderChildControls(offset, updateRect);
}
void GuiColorPickerCtrl::setSelectorPos(const ColorF & color)
{
if (mBitmap && !mPositionChanged)
{
Point2I resolution = getRoot() ? getRoot()->getExtent() : Point2I(1024, 768);
RectI rect(getGlobalBounds());
Point2I pos = findColor(color, rect.point, resolution, *mBitmap);
mSetColor = mSetColor.BLACK;
mSelectColor = false;
setSelectorPos(pos);
}
else
{
mSetColor = color;
mSelectColor = true;
mPositionChanged = true;
}
}
Point2I GuiColorPickerCtrl::findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp)
{
RectI rect;
Point2I ext = getExtent();
if (mDisplayMode != pDropperBackground)
{
ext.x -= 3;
ext.y -= 2;
rect = RectI(Point2I(1, 1), ext);
}
else
{
rect = RectI(Point2I(0, 0), ext);
}
Point2I closestPos(-1, -1);
/* Debugging
char filename[256];
dSprintf( filename, 256, "%s.%s", "colorPickerTest", "png" );
// Open up the file on disk.
FileStream fs;
if ( !fs.open( filename, Torque::FS::File::Write ) )
Con::errorf( "GuiObjectView::saveAsImage() - Failed to open output file '%s'!", filename );
else
{
// Write it and close.
bmp.writeBitmap( "png", fs );
fs.close();
}
*/
ColorI tmp;
U32 buf_x;
U32 buf_y;
ColorF curColor;
F32 val(10000.0f);
F32 closestVal(10000.0f);
bool closestSet = false;
for (S32 x = rect.point.x; x <= rect.extent.x; x++)
{
for (S32 y = rect.point.y; y <= rect.extent.y; y++)
{
buf_x = offset.x + x + 1;
buf_y = (resolution.y - (offset.y + y + 1));
if (GFX->getAdapterType() != OpenGL)
buf_y = resolution.y - buf_y;
//Get the color at that position
bmp.getColor(buf_x, buf_y, tmp);
curColor = (ColorF)tmp;
//Evaluate how close the color is to our desired color
val = mFabs(color.red - curColor.red) + mFabs(color.green - curColor.green) + mFabs(color.blue - curColor.blue);
if (!closestSet)
{
closestVal = val;
closestPos.set(x, y);
closestSet = true;
}
else if (val < closestVal)
{
closestVal = val;
closestPos.set(x, y);
}
}
}
return closestPos;
}
//--------------------------------------------------------------------------
@ -539,3 +671,10 @@ DefineConsoleMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update
{
object->updateColor();
}
DefineEngineMethod(GuiColorPickerCtrl, setSelectorColor, void, (ColorF color), ,
"Sets the current position of the selector based on a color.n"
"@param color Color to look for.n")
{
object->setSelectorPos(color);
}

View file

@ -98,7 +98,11 @@ class GuiColorPickerCtrl : public GuiControl
bool mMouseDown; ///< Mouse button down?
bool mActionOnMove; ///< Perform onAction() when position has changed?
bool mSelectColor;
ColorF mSetColor;
GBitmap* mBitmap;
Point2I findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp);
S32 mSelectorGap; ///< The half-way "gap" between the selector pos and where the selector is allowed to draw.
@ -113,6 +117,7 @@ class GuiColorPickerCtrl : public GuiControl
DECLARE_CATEGORY( "Gui Editor" );
GuiColorPickerCtrl();
~GuiColorPickerCtrl();
static void initPersistFields();
void onRender(Point2I offset, const RectI &updateRect);
@ -131,6 +136,7 @@ class GuiColorPickerCtrl : public GuiControl
/// @name Selector Functions
/// @{
void setSelectorPos(const Point2I &pos); ///< Set new pos (in local coords)
void setSelectorPos(const ColorF & color);
Point2I getSelectorPos() {return mSelectorPos;}
/// @}

View file

@ -128,6 +128,8 @@ GuiTextEditCtrl::GuiTextEditCtrl()
mActive = true;
mTextValid = true;
mTextOffsetReset = true;
mHistoryDirty = false;
@ -1257,15 +1259,21 @@ void GuiTextEditCtrl::onRender(Point2I offset, const RectI &updateRect)
//if opaque, fill the update rect with the fill color
if ( mProfile->mOpaque )
{
if(isFirstResponder())
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorHL );
else
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColor );
if (!mTextValid)
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColorNA);
else if (isFirstResponder())
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColorHL);
else
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColor);
}
//if there's a border, draw the border
if ( mProfile->mBorder )
renderBorder( ctrlRect, mProfile );
if (mProfile->mBorder)
{
renderBorder(ctrlRect, mProfile);
if (!mTextValid)
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColorNA);
}
drawText( ctrlRect, isFirstResponder() );
}
@ -1491,6 +1499,24 @@ bool GuiTextEditCtrl::hasText()
return (mTextBuffer.length());
}
void GuiTextEditCtrl::invalidText(bool playSound)
{
mTextValid = false;
if (playSound)
playDeniedSound();
}
void GuiTextEditCtrl::validText()
{
mTextValid = true;
}
bool GuiTextEditCtrl::isValidText()
{
return mTextValid;
}
void GuiTextEditCtrl::playDeniedSound()
{
if ( mDeniedSound )
@ -1518,27 +1544,29 @@ void GuiTextEditCtrl::handleCharInput( U16 ascii )
//see if it's a number field
if ( mProfile->mNumbersOnly )
{
if ( ascii == '-')
{
//a minus sign only exists at the beginning, and only a single minus sign
if ( mCursorPos != 0 && !isAllTextSelected() )
{
playDeniedSound();
return;
}
if (ascii == '-')
{
//a minus sign only exists at the beginning, and only a single minus sign
if (mCursorPos != 0 && !isAllTextSelected())
{
invalidText();
return;
}
if ( mInsertOn && ( mTextBuffer.getChar(0) == '-' ) )
{
playDeniedSound();
return;
}
}
// BJTODO: This is probably not unicode safe.
else if ( ascii != '.' && (ascii < '0' || ascii > '9') )
{
playDeniedSound();
return;
}
if (mInsertOn && (mTextBuffer.getChar(0) == '-'))
{
invalidText();
return;
}
}
// BJTODO: This is probably not unicode safe.
else if (ascii != '.' && (ascii < '0' || ascii > '9'))
{
invalidText();
return;
}
else
validText();
}
//save the current state
@ -1746,3 +1774,24 @@ DefineEngineMethod( GuiTextEditCtrl, forceValidateText, void, (),,
{
object->forceValidateText();
}
DefineEngineMethod(GuiTextEditCtrl, invalidText, void, (bool playSound), (true),
"@brief Trigger the invalid sound and make the box red.nn"
"@param playSound Play the invalid text sound or not.n")
{
object->invalidText(playSound);
}
DefineEngineMethod(GuiTextEditCtrl, validText, void, (), ,
"@brief Restores the box to normal color.nn")
{
object->validText();
}
DefineEngineMethod(GuiTextEditCtrl, isValidText, bool, (), ,
"@brief Returns if the text is set to valid or not.n"
"@Return true if text is set to valid, false if not.nn")
{
return object->isValidText();
}

View file

@ -93,6 +93,8 @@ protected:
void playDeniedSound();
void execConsoleCallback();
bool mTextValid;
virtual void handleCharInput( U16 ascii );
S32 findNextWord();
@ -119,6 +121,10 @@ public:
S32 getCursorPos() { return( mCursorPos ); }
void setCursorPos( const S32 newPos );
void invalidText(bool playSound = true);
void validText();
bool isValidText();
bool isAllTextSelected();
void selectAllText();
void clearSelectedText();