summaryrefslogtreecommitdiff
path: root/vgui2/matsys_controls/colorpickerpanel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/matsys_controls/colorpickerpanel.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'vgui2/matsys_controls/colorpickerpanel.cpp')
-rw-r--r--vgui2/matsys_controls/colorpickerpanel.cpp1255
1 files changed, 1255 insertions, 0 deletions
diff --git a/vgui2/matsys_controls/colorpickerpanel.cpp b/vgui2/matsys_controls/colorpickerpanel.cpp
new file mode 100644
index 0000000..848f78a
--- /dev/null
+++ b/vgui2/matsys_controls/colorpickerpanel.cpp
@@ -0,0 +1,1255 @@
+//========= 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 );
+}