source-engine/vgui2/matsys_controls/colorpickerpanel.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

1256 lines
35 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/colorpickerpanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "matsys_controls/proceduraltexturepanel.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/itexture.h"
#include "pixelwriter.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/RadioButton.h"
#include "vgui/IInput.h"
#include "tier1/KeyValues.h"
#include "bitmap/imageformat.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Color picker
//-----------------------------------------------------------------------------
enum ColorType_t
{
COLOR_TYPE_RGB = 0,
COLOR_TYPE_HSV,
};
enum ColorChannel_t
{
CHANNEL_RED = 0,
CHANNEL_GREEN,
CHANNEL_BLUE,
CHANNEL_HUE = 0,
CHANNEL_SATURATION,
CHANNEL_VALUE,
};
//-----------------------------------------------------------------------------
// Converts RGB to normalized
//-----------------------------------------------------------------------------
static void RGB888ToVector( RGB888_t inColor, Vector *pOutVector )
{
pOutVector->Init( inColor.r / 255.0f, inColor.g / 255.0f, inColor.b / 255.0f );
}
static void VectorToRGB888( const Vector &inVector, RGB888_t &outColor )
{
int r = (int)((inVector.x * 255.0f) + 0.5f);
int g = (int)((inVector.y * 255.0f) + 0.5f);
int b = (int)((inVector.z * 255.0f) + 0.5f);
outColor.r = clamp( r, 0, 255 );
outColor.g = clamp( g, 0, 255 );
outColor.b = clamp( b, 0, 255 );
}
//-----------------------------------------------------------------------------
// Convert RGB to HSV
//-----------------------------------------------------------------------------
static inline void RGBtoHSV( const RGB888_t &rgb, Vector &hsv )
{
Vector vecRGB;
RGB888ToVector( rgb, &vecRGB );
RGBtoHSV( vecRGB, hsv );
}
//-----------------------------------------------------------------------------
// Convert HSV to RGB
//-----------------------------------------------------------------------------
static inline void HSVtoRGB( const Vector &hsv, RGB888_t &rgb )
{
Vector vecRGB;
HSVtoRGB( hsv, vecRGB );
VectorToRGB888( vecRGB, rgb );
}
//-----------------------------------------------------------------------------
// This previews the 'xy' color
//-----------------------------------------------------------------------------
class CColorXYPreview : public CProceduralTexturePanel
{
DECLARE_CLASS_SIMPLE( CColorXYPreview, CProceduralTexturePanel );
public:
// constructor
CColorXYPreview( vgui::Panel *pParent, const char *pName );
virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect );
virtual void Paint( void );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnMouseReleased( vgui::MouseCode code );
virtual void OnCursorMoved( int x, int y );
void SetMode( ColorType_t type, ColorChannel_t channel );
void SetColor( const RGB888_t &color, const Vector &hsvColor );
private:
// Computes a color given a particular x,y value
void ComputeColorForPoint( int x, int y, RGB888_t &color );
void ComputeHSVColorForPoint( int x, int y, Vector &vscHSV );
// Updates the color based on the mouse position
void UpdateColorFromMouse( int x, int y );
static ColorChannel_t s_pHSVRemapX[3];
static ColorChannel_t s_pHSVRemapY[3];
static ColorChannel_t s_pRGBRemapX[3];
static ColorChannel_t s_pRGBRemapY[3];
ColorType_t m_Type;
ColorChannel_t m_Channel;
RGB888_t m_CurrentColor;
Vector m_CurrentHSVColor;
vgui::HCursor m_hPickerCursor;
bool m_bDraggingMouse;
};
ColorChannel_t CColorXYPreview::s_pHSVRemapX[3] =
{
CHANNEL_SATURATION, CHANNEL_HUE, CHANNEL_HUE
};
ColorChannel_t CColorXYPreview::s_pHSVRemapY[3] =
{
CHANNEL_VALUE, CHANNEL_VALUE, CHANNEL_SATURATION
};
ColorChannel_t CColorXYPreview::s_pRGBRemapX[3] =
{
CHANNEL_BLUE, CHANNEL_BLUE, CHANNEL_RED
};
ColorChannel_t CColorXYPreview::s_pRGBRemapY[3] =
{
CHANNEL_GREEN, CHANNEL_RED, CHANNEL_GREEN
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CColorXYPreview::CColorXYPreview( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
Init( 256, 256, false );
m_CurrentColor.r = m_CurrentColor.g = m_CurrentColor.b = 255;
SetMode( COLOR_TYPE_HSV, CHANNEL_HUE );
SetMouseInputEnabled( true );
m_hPickerCursor = surface()->CreateCursorFromFile( "resource/colorpicker.cur" );
SetCursor( m_hPickerCursor );
m_bDraggingMouse = false;
}
//-----------------------------------------------------------------------------
// Sets the mode for the preview
//-----------------------------------------------------------------------------
void CColorXYPreview::SetMode( ColorType_t type, ColorChannel_t channel )
{
if ( m_Type != type || m_Channel != channel )
{
m_Type = type;
m_Channel = channel;
DownloadTexture();
}
}
void CColorXYPreview::SetColor( const RGB888_t &color, const Vector &hsvColor )
{
if ( color != m_CurrentColor || m_CurrentHSVColor != hsvColor )
{
m_CurrentColor = color;
m_CurrentHSVColor = hsvColor;
DownloadTexture();
}
}
//-----------------------------------------------------------------------------
// Computes a color given a particular x,y value
//-----------------------------------------------------------------------------
void CColorXYPreview::ComputeColorForPoint( int x, int y, RGB888_t &color )
{
color = m_CurrentColor;
((unsigned char*)&color)[ s_pRGBRemapX[m_Channel] ] = x;
((unsigned char*)&color)[ s_pRGBRemapY[m_Channel] ] = GetImageHeight() - y - 1;
}
void CColorXYPreview::ComputeHSVColorForPoint( int x, int y, Vector &vscHSV )
{
vscHSV = m_CurrentHSVColor;
vscHSV[ s_pHSVRemapX[m_Channel] ] = (float)x / 255.0f;
vscHSV[ s_pHSVRemapY[m_Channel] ] = (float)(GetImageHeight() - y - 1) / 255.0f;
if ( vscHSV.y == 0.0f )
{
vscHSV.x = -1.0f;
}
if ( m_Channel != CHANNEL_HUE )
{
if ( vscHSV.x != -1.0f )
{
vscHSV.x *= 360.0f;
}
}
}
//-----------------------------------------------------------------------------
// Fills the texture w/ the image buffer
//-----------------------------------------------------------------------------
void CColorXYPreview::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
{
Assert( pVTFTexture->FrameCount() == 1 );
Assert( pVTFTexture->FaceCount() == 1 );
Assert( !pTexture->IsMipmapped() );
int nWidth, nHeight, nDepth;
pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
Assert( nDepth == 1 );
Assert( nWidth == m_nWidth && nHeight == m_nHeight );
CPixelWriter pixelWriter;
pixelWriter.SetPixelMemory( pVTFTexture->Format(),
pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
for ( int y = 0; y < nHeight; ++y )
{
pixelWriter.Seek( 0, y );
for ( int x = 0; x < nWidth; ++x )
{
RGB888_t color;
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSV;
ComputeHSVColorForPoint( x, y, vecHSV );
HSVtoRGB( vecHSV, color );
}
else
{
ComputeColorForPoint( x, y, color );
}
pixelWriter.WritePixel( color.r, color.g, color.b, 255 );
}
}
}
//-----------------------------------------------------------------------------
// Paints a circle over the currently selected color
//-----------------------------------------------------------------------------
void CColorXYPreview::Paint( void )
{
BaseClass::Paint();
int x, y;
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSVNormalized = m_CurrentHSVColor;
if ( vecHSVNormalized.x != -1.0f )
{
vecHSVNormalized.x *= 255.0f / 360.0f;
}
vecHSVNormalized.y *= 255.0f;
vecHSVNormalized.z *= 255.0f;
x = (int)( vecHSVNormalized[ s_pHSVRemapX[m_Channel] ] + 0.5f);
y = GetImageHeight() - 1 - (int)( vecHSVNormalized[ s_pHSVRemapY[m_Channel] ] + 0.5f );
}
else
{
x = ((unsigned char*)&m_CurrentColor)[ s_pRGBRemapX[m_Channel] ];
y = GetImageHeight() - 1 - ((unsigned char*)&m_CurrentColor)[ s_pRGBRemapY[m_Channel] ];
}
// Renormalize x, y to actual size
int w, h;
GetSize( w, h );
x = (int)( w * (float)x / 255.0f + 0.5f );
y = (int)( h * (float)y / 255.0f + 0.5f );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
vgui::surface()->DrawOutlinedCircle( x, y, 5, 8 );
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawOutlinedCircle( x, y, 6, 8 );
}
//-----------------------------------------------------------------------------
// Updates the color based on the mouse position
//-----------------------------------------------------------------------------
void CColorXYPreview::UpdateColorFromMouse( int x, int y )
{
int w, h;
GetSize( w, h );
float flNormalizedX = (float)x / (w-1);
float flNormalizedY = (float)y / (h-1);
flNormalizedX = clamp( flNormalizedX, 0.0f, 1.0f );
flNormalizedY = clamp( flNormalizedY, 0.0f, 1.0f );
int tx = (int)( (GetImageWidth()-1) * flNormalizedX + 0.5f );
int ty = (int)( (GetImageHeight()-1) * flNormalizedY + 0.5f );
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSV;
ComputeHSVColorForPoint( tx, ty, vecHSV );
KeyValues *pKeyValues = new KeyValues( "HSVSelected" );
pKeyValues->SetFloat( "hue", vecHSV.x );
pKeyValues->SetFloat( "saturation", vecHSV.y );
pKeyValues->SetFloat( "value", vecHSV.z );
PostActionSignal( pKeyValues );
// This prevents a 1-frame lag in the current color position
RGB888_t color;
HSVtoRGB( vecHSV, color );
SetColor( color, vecHSV );
}
else
{
RGB888_t color;
ComputeColorForPoint( tx, ty, color );
Color c( color.r, color.g, color.b, 255 );
KeyValues *pKeyValues = new KeyValues( "ColorSelected" );
pKeyValues->SetColor( "color", c );
PostActionSignal( pKeyValues );
// This prevents a 1-frame lag in the current color position
Vector vecHSV;
RGBtoHSV( color, vecHSV );
SetColor( color, vecHSV );
}
}
//-----------------------------------------------------------------------------
// Handle input
//-----------------------------------------------------------------------------
void CColorXYPreview::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
if ( code == MOUSE_LEFT )
{
if ( !m_bDraggingMouse )
{
m_bDraggingMouse = true;
input()->SetMouseCapture(GetVPanel());
int x, y;
input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
UpdateColorFromMouse( x, y );
}
}
}
void CColorXYPreview::OnMouseReleased( vgui::MouseCode code )
{
BaseClass::OnMouseReleased( code );
if ( code == MOUSE_LEFT )
{
if ( m_bDraggingMouse )
{
m_bDraggingMouse = false;
input()->SetMouseCapture( (VPANEL)0 );
}
}
}
void CColorXYPreview::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
if ( m_bDraggingMouse )
{
UpdateColorFromMouse( x, y );
}
}
//-----------------------------------------------------------------------------
// This previews the 'z' color
//-----------------------------------------------------------------------------
class CColorZPreview : public CProceduralTexturePanel
{
DECLARE_CLASS_SIMPLE( CColorZPreview, CProceduralTexturePanel );
public:
// constructor
CColorZPreview( vgui::Panel *pParent, const char *pName );
virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect );
virtual void PerformLayout();
virtual void Paint( void );
virtual void OnCursorMoved( int x,int y );
virtual void OnMousePressed( vgui::MouseCode code );
virtual void OnMouseReleased( vgui::MouseCode code );
void SetMode( ColorType_t type, ColorChannel_t channel );
void SetColor( const RGB888_t &color, const Vector &hsvColor );
// Computes a color given a particular x,y value
void ComputeColorForPoint( int y, RGB888_t &color );
void ComputeHSVColorForPoint( int y, bool bProceduralTexture, Vector &vecHSV );
private:
// Updates the color based on the mouse position
void UpdateColorFromMouse( int x, int y );
ColorType_t m_Type;
ColorChannel_t m_Channel;
RGB888_t m_CurrentColor;
Vector m_CurrentHSVColor;
bool m_bDraggingMouse;
};
#define MARKER_WIDTH 6
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CColorZPreview::CColorZPreview( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
Init( 8, 256, false );
m_CurrentColor.r = m_CurrentColor.g = m_CurrentColor.b = 255;
Vector vecRGB;
RGB888ToVector( m_CurrentColor, &vecRGB );
RGBtoHSV( vecRGB, m_CurrentHSVColor );
m_bDraggingMouse = false;
SetMouseInputEnabled( true );
SetMode( COLOR_TYPE_HSV, CHANNEL_HUE );
}
//-----------------------------------------------------------------------------
// Sets the mode for the preview
//-----------------------------------------------------------------------------
void CColorZPreview::SetMode( ColorType_t type, ColorChannel_t channel )
{
if ( m_Type != type || m_Channel != channel )
{
m_Type = type;
m_Channel = channel;
DownloadTexture();
}
}
void CColorZPreview::SetColor( const RGB888_t &color, const Vector &hsvColor )
{
if ( color != m_CurrentColor || m_CurrentHSVColor != hsvColor )
{
m_CurrentColor = color;
m_CurrentHSVColor = hsvColor;
DownloadTexture();
}
}
//-----------------------------------------------------------------------------
// Lays out the panel
//-----------------------------------------------------------------------------
void CColorZPreview::PerformLayout()
{
BaseClass::PerformLayout();
int w, h;
GetSize( w, h );
Rect_t r;
r.x = MARKER_WIDTH;
r.y = MARKER_WIDTH;
r.width = w - (MARKER_WIDTH*2);
r.height = h - (MARKER_WIDTH*2);
SetPaintRect( &r );
}
//-----------------------------------------------------------------------------
// Computes a color given a particular x,y value
//-----------------------------------------------------------------------------
void CColorZPreview::ComputeColorForPoint( int y, RGB888_t &color )
{
color = m_CurrentColor;
((unsigned char*)&color)[ m_Channel ] = GetImageHeight() - y - 1;
}
void CColorZPreview::ComputeHSVColorForPoint( int y, bool bProceduralTexture, Vector &vecHSV )
{
vecHSV = m_CurrentHSVColor;
vecHSV[ m_Channel ] = (float)(GetImageHeight() - y - 1) / 255.0f;
if ( m_Channel == CHANNEL_HUE )
{
if ( vecHSV.x != -1.0f )
{
vecHSV.x *= 360.0f;
}
if ( bProceduralTexture )
{
vecHSV.y = 1.0f;
vecHSV.z = 1.0f;
}
}
}
//-----------------------------------------------------------------------------
// Fills the texture w/ the image buffer
//-----------------------------------------------------------------------------
void CColorZPreview::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
{
Assert( pVTFTexture->FrameCount() == 1 );
Assert( pVTFTexture->FaceCount() == 1 );
Assert( !pTexture->IsMipmapped() );
int nWidth, nHeight, nDepth;
pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
Assert( nDepth == 1 );
Assert( nWidth == m_nWidth && nHeight == m_nHeight );
CPixelWriter pixelWriter;
pixelWriter.SetPixelMemory( pVTFTexture->Format(),
pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
for ( int y = 0; y < nHeight; ++y )
{
pixelWriter.Seek( 0, y );
RGB888_t color;
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSV;
ComputeHSVColorForPoint( y, true, vecHSV );
HSVtoRGB( vecHSV, color );
}
else
{
ComputeColorForPoint( y, color );
}
for ( int x = 0; x < nWidth; ++x )
{
pixelWriter.WritePixel( color.r, color.g, color.b, 255 );
}
}
}
//-----------------------------------------------------------------------------
// Updates the color based on the mouse position
//-----------------------------------------------------------------------------
void CColorZPreview::UpdateColorFromMouse( int x, int y )
{
int w, h;
GetSize( w, h );
h -= 2 * MARKER_WIDTH;
float flNormalizedY = (float)( y - MARKER_WIDTH ) / (h-1);
flNormalizedY = clamp( flNormalizedY, 0.0f, 1.0f );
int ty = (int)( (GetImageHeight() - 1) * flNormalizedY + 0.5f );
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSV;
ComputeHSVColorForPoint( ty, false, vecHSV );
KeyValues *pKeyValues = new KeyValues( "HSVSelected" );
pKeyValues->SetFloat( "hue", vecHSV.x );
pKeyValues->SetFloat( "saturation", vecHSV.y );
pKeyValues->SetFloat( "value", vecHSV.z );
PostActionSignal( pKeyValues );
// This prevents a 1-frame lag in the current color position
RGB888_t color;
HSVtoRGB( vecHSV, color );
SetColor( color, vecHSV );
}
else
{
RGB888_t color;
ComputeColorForPoint( ty, color );
Color c( color.r, color.g, color.b, 255 );
KeyValues *pKeyValues = new KeyValues( "ColorSelected" );
pKeyValues->SetColor( "color", c );
PostActionSignal( pKeyValues );
// This prevents a 1-frame lag in the current color position
Vector vecHSV;
RGBtoHSV( color, vecHSV );
SetColor( color, vecHSV );
}
}
//-----------------------------------------------------------------------------
// Handle input
//-----------------------------------------------------------------------------
void CColorZPreview::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
if ( code == MOUSE_LEFT )
{
if ( !m_bDraggingMouse )
{
m_bDraggingMouse = true;
input()->SetMouseCapture(GetVPanel());
int x, y;
input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
UpdateColorFromMouse( x, y );
}
}
}
void CColorZPreview::OnMouseReleased( vgui::MouseCode code )
{
BaseClass::OnMouseReleased( code );
if ( code == MOUSE_LEFT )
{
if ( m_bDraggingMouse )
{
m_bDraggingMouse = false;
input()->SetMouseCapture( (VPANEL)0 );
}
}
}
void CColorZPreview::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
if ( m_bDraggingMouse )
{
UpdateColorFromMouse( x, y );
}
}
//-----------------------------------------------------------------------------
// Paints the panel (the two arrows, specifically)
//-----------------------------------------------------------------------------
void CColorZPreview::Paint( void )
{
BaseClass::Paint();
int y;
if ( m_Type != COLOR_TYPE_RGB )
{
Vector vecHSVNormalized = m_CurrentHSVColor;
if ( vecHSVNormalized.x != -1.0f )
{
vecHSVNormalized.x *= 255.0f / 360.0f;
}
vecHSVNormalized.y *= 255.0f;
vecHSVNormalized.z *= 255.0f;
y = GetImageHeight() - 1 - (int)( vecHSVNormalized[ m_Channel ] + 0.5f );
}
else
{
y = GetImageHeight() - 1 - ((unsigned char*)&m_CurrentColor)[ m_Channel ];
}
// Renormalize y to actual size
int w, h;
GetSize( w, h );
h -= 2 * MARKER_WIDTH;
y = (int)( h * (float)y / 255.0f + 0.5f );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
int px[3] = { 0, 0, MARKER_WIDTH };
int py[3] = { MARKER_WIDTH + y - MARKER_WIDTH, MARKER_WIDTH + y + MARKER_WIDTH, MARKER_WIDTH + y };
vgui::surface()->DrawPolyLine( px, py, 3 );
px[0] = px[1] = w-1;
px[2] = w - 1 - MARKER_WIDTH;
vgui::surface()->DrawPolyLine( px, py, 3 );
}
//-----------------------------------------------------------------------------
//
// Color picker panel
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
CColorPickerPanel::CColorPickerPanel( vgui::Panel *pParent, const char *pName ) :
BaseClass( pParent, pName )
{
m_pColorXYPreview = new CColorXYPreview( this, "ColorXYPreview" );
m_pColorZPreview = new CColorZPreview( this, "ColorZPreview" );
m_pColorXYPreview->AddActionSignalTarget( this );
m_pHueRadio = new RadioButton( this, "HueRadio", "H" );
m_pSaturationRadio = new RadioButton( this, "SaturationRadio", "S" );
m_pValueRadio = new RadioButton( this, "ValueRadio", "V" );
m_pRedRadio = new RadioButton( this, "RedRadio", "R" );
m_pGreenRadio = new RadioButton( this, "GreenRadio", "G" );
m_pBlueRadio = new RadioButton( this, "BlueRadio", "B" );
m_pHueText = new TextEntry( this, "HueText" );
m_pSaturationText = new TextEntry( this, "SaturationText");
m_pValueText = new TextEntry( this, "ValueText" );
m_pRedText = new TextEntry( this, "RedText" );
m_pGreenText = new TextEntry( this, "GreenText" );
m_pBlueText = new TextEntry( this, "BlueText" );
m_pAlphaText= new TextEntry( this, "AlphaText" );
m_pInitialColor = new Panel( this, "InitialColor" );
m_pCurrentColor = new Panel( this, "CurrentColor" );
m_pInitialColor->SetVisible( true );
m_pCurrentColor->SetVisible( true );
m_pInitialColor->SetPaintBackgroundEnabled( true );
m_pCurrentColor->SetPaintBackgroundEnabled( true );
m_pInitialColor->SetMouseInputEnabled( false );
SetMouseInputEnabled( true );
Color c( 255, 255, 255, 255 );
SetInitialColor( c );
LoadControlSettings( "resource/colorpicker.res" );
}
//-----------------------------------------------------------------------------
// Sets the initial color
//-----------------------------------------------------------------------------
void CColorPickerPanel::SetInitialColor( Color initialColor )
{
m_InitialColor.r = initialColor.r();
m_InitialColor.g = initialColor.g();
m_InitialColor.b = initialColor.b();
m_CurrentAlpha = initialColor.a();
m_InitialAlpha = m_CurrentAlpha;
m_CurrentColor = m_InitialColor;
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
if ( m_CurrentHSVColor.x == -1 )
{
m_CurrentHSVColor.x = 0;
}
OnColorChanged();
}
//-----------------------------------------------------------------------------
// Handle input
//-----------------------------------------------------------------------------
void CColorPickerPanel::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
if ( code == MOUSE_LEFT )
{
// Clicking inside the initial color window
// resets the current color to the initial color
int x, y;
input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
int cx, cy, cw, ch;
m_pInitialColor->GetBounds( cx, cy, cw, ch );
if ( ( cx <= x ) && ( cx+cw > x ) && ( cy <= y ) && ( cy+ch > y ) )
{
m_CurrentColor = m_InitialColor;
m_CurrentAlpha = m_InitialAlpha;
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
if ( m_CurrentHSVColor.x == -1 )
{
m_CurrentHSVColor.x = 0;
}
OnColorChanged();
}
}
}
//-----------------------------------------------------------------------------
// Gets the current/initial color
//-----------------------------------------------------------------------------
void CColorPickerPanel::GetCurrentColor( Color *pColor )
{
pColor->SetColor( m_CurrentColor.r, m_CurrentColor.g, m_CurrentColor.b, m_CurrentAlpha );
}
void CColorPickerPanel::GetInitialColor( Color *pColor )
{
pColor->SetColor( m_InitialColor.r, m_InitialColor.g, m_InitialColor.b, m_InitialAlpha );
}
//-----------------------------------------------------------------------------
// Updates the preview colors
//-----------------------------------------------------------------------------
void CColorPickerPanel::UpdatePreviewColors()
{
Color c;
c.SetColor( m_InitialColor.r, m_InitialColor.g, m_InitialColor.b, 255 );
m_pInitialColor->SetBgColor( c );
c.SetColor( m_CurrentColor.r, m_CurrentColor.g, m_CurrentColor.b, 255 );
m_pCurrentColor->SetBgColor( c );
}
//-----------------------------------------------------------------------------
// Used to make sure we win over the scheme settings
//-----------------------------------------------------------------------------
void CColorPickerPanel::ApplySchemeSettings(IScheme *pScheme)
{
// Need to override the scheme settings for this button
BaseClass::ApplySchemeSettings( pScheme );
UpdatePreviewColors();
}
//-----------------------------------------------------------------------------
// Callbacks from the color preview dialogs
//-----------------------------------------------------------------------------
void CColorPickerPanel::OnHSVSelected( KeyValues *data )
{
m_CurrentHSVColor.x = data->GetFloat( "hue" );
m_CurrentHSVColor.y = data->GetFloat( "saturation" );
m_CurrentHSVColor.z = data->GetFloat( "value" );
HSVtoRGB( m_CurrentHSVColor, m_CurrentColor );
OnColorChanged();
}
void CColorPickerPanel::OnColorSelected( KeyValues *data )
{
Color c = data->GetColor( "color" );
m_CurrentColor.r = c.r();
m_CurrentColor.g = c.g();
m_CurrentColor.b = c.b();
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
OnColorChanged();
}
//-----------------------------------------------------------------------------
// Radio buttons
//-----------------------------------------------------------------------------
void CColorPickerPanel::OnRadioButtonChecked( KeyValues *pKeyValues )
{
// NOTE: The radio button command strings are defined in the colorpicker.res file
// in game/platform/resource.
vgui::Panel *pPanel = (vgui::Panel *)pKeyValues->GetPtr( "panel" );
if ( pPanel == m_pRedRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_RED );
m_pColorZPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_RED );
}
else if ( pPanel == m_pGreenRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_GREEN );
m_pColorZPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_GREEN );
}
else if ( pPanel == m_pBlueRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_BLUE );
m_pColorZPreview->SetMode( COLOR_TYPE_RGB, CHANNEL_BLUE );
}
else if ( pPanel == m_pHueRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_HUE );
m_pColorZPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_HUE );
}
else if ( pPanel == m_pSaturationRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_SATURATION );
m_pColorZPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_SATURATION );
}
else if ( pPanel == m_pValueRadio )
{
m_pColorXYPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_VALUE );
m_pColorZPreview->SetMode( COLOR_TYPE_HSV, CHANNEL_VALUE );
}
}
//-----------------------------------------------------------------------------
// Called when the color changes
//-----------------------------------------------------------------------------
void CColorPickerPanel::OnColorChanged( vgui::TextEntry *pChanged )
{
char temp[256];
if ( pChanged != m_pRedText )
{
Q_snprintf( temp, sizeof(temp), "%d", m_CurrentColor.r );
m_pRedText->SetText( temp );
}
if ( pChanged != m_pGreenText )
{
Q_snprintf( temp, sizeof(temp), "%d", m_CurrentColor.g );
m_pGreenText->SetText( temp );
}
if ( pChanged != m_pBlueText )
{
Q_snprintf( temp, sizeof(temp), "%d", m_CurrentColor.b );
m_pBlueText->SetText( temp );
}
if ( pChanged != m_pAlphaText )
{
Q_snprintf( temp, sizeof( temp ), "%d", m_CurrentAlpha );
m_pAlphaText->SetText( temp );
}
if ( pChanged != m_pHueText )
{
Q_snprintf( temp, sizeof(temp), "%d", (int)(m_CurrentHSVColor.x + 0.5f) );
m_pHueText->SetText( temp );
}
if ( pChanged != m_pSaturationText )
{
Q_snprintf( temp, sizeof(temp), "%d", (int)(m_CurrentHSVColor.y * 100 + 0.5f) );
m_pSaturationText->SetText( temp );
}
if ( pChanged != m_pValueText )
{
Q_snprintf( temp, sizeof(temp), "%d", (int)(m_CurrentHSVColor.z * 100 + 0.5f) );
m_pValueText->SetText( temp );
}
m_pColorXYPreview->SetColor( m_CurrentColor, m_CurrentHSVColor );
m_pColorZPreview->SetColor( m_CurrentColor, m_CurrentHSVColor );
UpdatePreviewColors();
PostActionSignal( new KeyValues( "command", "command", "preview" ) );
}
//-----------------------------------------------------------------------------
// Called when the color text entry panels change
//-----------------------------------------------------------------------------
void CColorPickerPanel::OnTextChanged( KeyValues *data )
{
Panel *pPanel = (Panel *)data->GetPtr( "panel", NULL );
float flHue = m_CurrentHSVColor.x;
char buf[256];
if ( pPanel == m_pRedText )
{
m_pRedText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
m_CurrentColor.r = clamp( val, 0, 255 );
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
}
else if ( pPanel == m_pGreenText )
{
m_pGreenText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
m_CurrentColor.g = clamp( val, 0, 255 );
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
}
else if ( pPanel == m_pBlueText )
{
m_pBlueText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
m_CurrentColor.b = clamp( val, 0, 255 );
RGBtoHSV( m_CurrentColor, m_CurrentHSVColor );
}
else if ( pPanel == m_pAlphaText )
{
m_pAlphaText->GetText( buf, sizeof( buf ) );
int val = atoi( buf );
m_CurrentAlpha = clamp( val, 0, 255 );
}
else if ( pPanel == m_pHueText )
{
m_pHueText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
m_CurrentHSVColor.x = clamp( val, 0, 360 );
HSVtoRGB( m_CurrentHSVColor, m_CurrentColor );
}
else if ( pPanel == m_pSaturationText )
{
m_pSaturationText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
val = clamp( val, 0, 100 );
m_CurrentHSVColor.y = (float)val / 100.0f;
HSVtoRGB( m_CurrentHSVColor, m_CurrentColor );
}
else if ( pPanel == m_pValueText )
{
m_pValueText->GetText( buf, sizeof(buf) );
int val = atoi( buf );
val = clamp( val, 0, 100 );
m_CurrentHSVColor.z = (float)val / 100.0f;
HSVtoRGB( m_CurrentHSVColor, m_CurrentColor );
}
// Preserve hue
if ( m_CurrentHSVColor.x == -1 )
{
m_CurrentHSVColor.x = flHue;
}
OnColorChanged( static_cast<vgui::TextEntry*>(pPanel) );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CColorPickerFrame::CColorPickerFrame( vgui::Panel *pParent, const char *pTitle ) :
BaseClass( pParent, "ColorPickerFrame" )
{
m_pContextKeys = NULL;
SetDeleteSelfOnClose( true );
m_pPicker = new CColorPickerPanel( this, "ColorPicker" );
m_pPicker->AddActionSignalTarget( this );
m_pOpenButton = new Button( this, "OkButton", "Ok", this, "Ok" );
m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
SetBlockDragChaining( true );
LoadControlSettings( "resource/colorpickerframe.res" );
int w, h;
GetSize( w, h );
SetMinimumSize( w, h );
SetTitle( pTitle, false );
}
CColorPickerFrame::~CColorPickerFrame()
{
CleanUpMessage();
}
//-----------------------------------------------------------------------------
// Deletes the message
//-----------------------------------------------------------------------------
void CColorPickerFrame::CleanUpMessage()
{
if ( m_pContextKeys )
{
m_pContextKeys->deleteThis();
m_pContextKeys = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Activate the dialog
//-----------------------------------------------------------------------------
void CColorPickerFrame::DoModal( Color initialColor, KeyValues *pContextKeys )
{
CleanUpMessage();
m_pPicker->SetInitialColor( initialColor );
m_pContextKeys = pContextKeys;
BaseClass::DoModal();
}
//-----------------------------------------------------------------------------
// Gets the initial color
//-----------------------------------------------------------------------------
void CColorPickerFrame::GetInitialColor( Color *pColor )
{
m_pPicker->GetInitialColor( pColor );
}
//-----------------------------------------------------------------------------
// On command
//-----------------------------------------------------------------------------
void CColorPickerFrame::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "Ok" ) )
{
Color c;
m_pPicker->GetCurrentColor( &c );
KeyValues *pActionKeys = new KeyValues( "ColorPickerPicked" );
pActionKeys->SetColor( "color", c );
if ( m_pContextKeys )
{
pActionKeys->AddSubKey( m_pContextKeys );
m_pContextKeys = NULL;
}
CloseModal();
PostActionSignal( pActionKeys );
return;
}
if ( !Q_stricmp( pCommand, "Cancel" ) )
{
vgui::input()->ReleaseAppModalSurface();
KeyValues *pActionKeys = new KeyValues( "ColorPickerCancel" );
if ( m_pContextKeys )
{
pActionKeys->AddSubKey( m_pContextKeys );
m_pContextKeys = NULL;
}
CloseModal();
PostActionSignal( pActionKeys );
return;
}
if ( !Q_stricmp( pCommand, "Preview" ) )
{
Color c;
m_pPicker->GetCurrentColor( &c );
KeyValues *pActionKeys = new KeyValues( "ColorPickerPreview" );
pActionKeys->SetColor( "color", c );
if ( m_pContextKeys )
{
pActionKeys->AddSubKey( m_pContextKeys->MakeCopy() );
}
PostActionSignal( pActionKeys );
return;
}
BaseClass::OnCommand( pCommand );
}
//-----------------------------------------------------------------------------
//
// Purpose: A button which brings up the color picker
//
//-----------------------------------------------------------------------------
CColorPickerButton::CColorPickerButton( vgui::Panel *pParent, const char *pName, vgui::Panel *pActionSignalTarget ) :
BaseClass( pParent, pName, "" )
{
m_CurrentColor.SetColor( 255, 255, 255, 255 );
if ( pActionSignalTarget )
{
AddActionSignalTarget( pActionSignalTarget );
}
}
CColorPickerButton::~CColorPickerButton()
{
}
void CColorPickerButton::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
UpdateButtonColor();
}
//-----------------------------------------------------------------------------
// Called when the picker gets a new color
//-----------------------------------------------------------------------------
void CColorPickerButton::OnPicked( KeyValues *data )
{
SetColor( data->GetColor( "color" ) );
// Fire normal action signal messages
KeyValues *pMessage = new KeyValues( "ColorPickerPicked" );
pMessage->SetColor( "color", m_CurrentColor );
PostActionSignal( pMessage );
PlayButtonReleasedSound();
SetSelected( false );
}
//-----------------------------------------------------------------------------
// Called when a color is previewed
//-----------------------------------------------------------------------------
void CColorPickerButton::OnPreview( KeyValues *data )
{
KeyValues *pMessage = new KeyValues( "ColorPickerPreview" );
pMessage->SetColor( "color", data->GetColor( "color" ) );
PostActionSignal( pMessage );
}
//-----------------------------------------------------------------------------
// Called when cancel is hit in the picker
//-----------------------------------------------------------------------------
void CColorPickerButton::OnCancelled( )
{
SetSelected( false );
KeyValues *pMessage = new KeyValues( "ColorPickerCancel" );
pMessage->SetColor( "startingColor", m_CurrentColor );
PostActionSignal( pMessage );
}
//-----------------------------------------------------------------------------
// Perform the click
//-----------------------------------------------------------------------------
void CColorPickerButton::DoClick()
{
SetSelected( true );
CColorPickerFrame *pColorPickerDialog = new CColorPickerFrame( this, "Select Color" );
pColorPickerDialog->AddActionSignalTarget( this );
pColorPickerDialog->DoModal( m_CurrentColor );
}
//-----------------------------------------------------------------------------
// Set current color
//-----------------------------------------------------------------------------
void CColorPickerButton::SetColor( const Color& clr )
{
m_CurrentColor = clr;
UpdateButtonColor();
}
void CColorPickerButton::SetColor( int r, int g, int b, int a )
{
m_CurrentColor.SetColor( r, g, b, a );
UpdateButtonColor();
}
//-----------------------------------------------------------------------------
// Update button color
//-----------------------------------------------------------------------------
void CColorPickerButton::UpdateButtonColor()
{
SetDefaultColor( m_CurrentColor, m_CurrentColor );
SetArmedColor( m_CurrentColor, m_CurrentColor );
SetDepressedColor( m_CurrentColor, m_CurrentColor );
}