diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/matsys_controls/colorpickerpanel.cpp | |
| download | archived-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.cpp | 1255 |
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 ); +} |