mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-19 19:35:26 +00:00
Color Picker
This commit is contained in:
parent
39f0e269d6
commit
03109c9d6d
9 changed files with 2424 additions and 642 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;}
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue