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 /utils/hlfaceposer/mxexpressionslider.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/hlfaceposer/mxexpressionslider.cpp')
| -rw-r--r-- | utils/hlfaceposer/mxexpressionslider.cpp | 723 |
1 files changed, 723 insertions, 0 deletions
diff --git a/utils/hlfaceposer/mxexpressionslider.cpp b/utils/hlfaceposer/mxexpressionslider.cpp new file mode 100644 index 0000000..0e82fc9 --- /dev/null +++ b/utils/hlfaceposer/mxexpressionslider.cpp @@ -0,0 +1,723 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include <stdio.h> +#include <windows.h> +#include "mxExpressionSlider.h" +#include "expressiontool.h" +#include "mathlib/mathlib.h" +#include "hlfaceposer.h" +#include "choreowidgetdrawhelper.h" + +mxExpressionSlider::mxExpressionSlider (mxWindow *parent, int x, int y, int w, int h, int id ) + : mxWindow( parent, x, y, w, h ) +{ + setId( id ); + setType( MX_SLIDER ); + + FacePoser_AddWindowStyle( this, WS_CLIPCHILDREN | WS_CLIPSIBLINGS ); + + m_flMin[ 0 ] = 0.0; + m_flMax[ 0 ] = 1.0f; + m_nTicks[ 0 ] = 20; + m_flCurrent[ 0 ] = 0.0f; + + m_flMin[ 1 ] = 0.0; + m_flMax[ 1 ] = 1.0f; + m_nTicks[ 1 ] = 20; + m_flCurrent[ 1 ] = 0.5f; + + m_flSetting[ 0 ] = 0.0; + m_flSetting[ 1 ] = 0.0; + + m_bIsEdited[ 0 ] = false; + m_bIsEdited[ 1 ] = false; + + m_bDraggingThumb = false; + m_nCurrentBar = 0; + + m_bPaired = false; + + m_nTitleWidth = 120; + m_bDrawTitle = true; + + m_pInfluence = new mxCheckBox( this, 2, 4, 12, 12, "", IDC_INFLUENCE ); +} + +mxExpressionSlider::~mxExpressionSlider( void ) +{ +} + +void mxExpressionSlider::SetTitleWidth( int width ) +{ + m_nTitleWidth = width; + redraw(); +} + +void mxExpressionSlider::SetDrawTitle( bool drawTitle ) +{ + m_bDrawTitle = drawTitle; + redraw(); +} + + +void mxExpressionSlider::SetMode( bool paired ) +{ + if ( m_bPaired != paired ) + { + m_bPaired = paired; + redraw(); + } +} + +void mxExpressionSlider::BoundValue( void ) +{ + for ( int i = 0; i < NUMBARS; i++ ) + { + if ( m_flCurrent[ i ] > m_flMax[ i ] ) + { + m_flCurrent[ i ] = m_flMax[ i ]; + } + if ( m_flCurrent[ i ] < m_flMin[ i ] ) + { + m_flCurrent[ i ] = m_flMin[ i ]; + } + } +} + + +void mxExpressionSlider::setValue( int barnum, float value ) +{ + if (m_flSetting[ barnum ] == value && m_bIsEdited[ barnum ] == false) + return; + + m_flSetting[ barnum ] = value; + m_bIsEdited[ barnum ] = false; + + if (m_bPaired) + { + if (m_flSetting[ 0 ] < m_flSetting[ 1 ]) + { + m_flCurrent[ 0 ] = m_flSetting[ 1 ]; + m_flCurrent[ 1 ] = 1.0 - (m_flSetting[ 0 ] / m_flSetting[ 1 ]) * 0.5; + } + else if (m_flSetting[ 0 ] > m_flSetting[ 1 ]) + { + m_flCurrent[ 0 ] = m_flSetting[ 0 ]; + m_flCurrent[ 1 ] = (m_flSetting[ 1 ] / m_flSetting[ 0 ]) * 0.5; + } + else + { + m_flCurrent[ 0 ] = m_flSetting[ 0 ]; + m_flCurrent[ 1 ] = 0.5; + } + } + else + { + m_flCurrent[ barnum ] = value; + } + + BoundValue(); + // FIXME: delay this until all sliders are set + if (!m_bPaired || barnum == 1) + redraw(); +} + +void mxExpressionSlider::setRange( int barnum, float min, float max, int ticks /*= 100*/ ) +{ + m_flMin[ barnum ] = min; + m_flMax[ barnum ] = max; + + Assert( m_flMax[ barnum ] > m_flMin[ barnum ] ); + + m_nTicks[ barnum ] = ticks; + + BoundValue(); + + redraw(); +} + +void mxExpressionSlider::setInfluence( float value ) +{ + bool bWasChecked = m_pInfluence->isChecked( ); + bool bNowChecked = value > 0.0f ? true : false; + if (bNowChecked != bWasChecked) + { + m_pInfluence->setChecked( bNowChecked ); + redraw(); + } +} + +float mxExpressionSlider::getRawValue( int barnum ) const +{ + return m_flCurrent[ barnum ]; +} + +float mxExpressionSlider::getValue( int barnum ) const +{ + float scale = 1.0; + if (m_bPaired) + { + // if it's paired, this is assuming that m_flCurrent[0] holds the max value, + // and m_flCurrent[1] is a weighting from 0 to 1, with 0.5 being even + if (barnum == 0 && m_flCurrent[ 1 ] > 0.5) + { + scale = (1.0 - m_flCurrent[ 1 ]) / 0.5; + } + else if (barnum == 1 && m_flCurrent[ 1 ] < 0.5) + { + scale = (m_flCurrent[ 1 ] / 0.5); + } + } + + return m_flCurrent[ 0 ] * scale; +} + +float mxExpressionSlider::getMinValue( int barnum ) const +{ + return m_flMin[ barnum ]; +} + +float mxExpressionSlider::getMaxValue( int barnum ) const +{ + return m_flMax[ barnum ]; +} + +float mxExpressionSlider::getInfluence( ) const +{ + return m_pInfluence->isChecked() ? 1.0f : 0.0f; +} + +void mxExpressionSlider::setEdited( int barnum, bool isEdited ) +{ + if (m_bIsEdited[ barnum ] == isEdited) + return; + + m_bIsEdited[ barnum ] = isEdited; + redraw(); +} + +bool mxExpressionSlider::isEdited( int barnum ) const +{ + return (m_bIsEdited[ barnum ]); +} + +void mxExpressionSlider::GetSliderRect( RECT& rc ) +{ + HWND wnd = (HWND)getHandle(); + if ( !wnd ) + return; + + GetClientRect( wnd, &rc ); + + if ( m_bDrawTitle ) + { + rc.left += m_nTitleWidth; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &rc - +//----------------------------------------------------------------------------- +void mxExpressionSlider::GetBarRect( RECT &rcBar ) +{ + RECT rc; + GetSliderRect( rc ); + + rcBar = rc; + + InflateRect( &rcBar, -10, 0 ); + rcBar.top += 5; + rcBar.bottom = rcBar.top + 2; + + int midy = ( rcBar.top + rcBar.bottom ) / 2; + rcBar.top = midy - 1; + rcBar.bottom = midy + 1; +} + + +void mxExpressionSlider::GetThumbRect( int barnum, RECT &rcThumb ) +{ + RECT rc; + GetSliderRect( rc ); + + RECT rcBar = rc; + GetBarRect( rcBar ); + + float frac = 0.0f; + + if ( m_flMax[ barnum ] - m_flMin[ barnum ] > 0 ) + { + frac = (m_flCurrent[ barnum ] - m_flMin[ barnum ]) / ( m_flMax[ barnum ] - m_flMin[ barnum ] ); + } + + int tickmark = (int)( frac * m_nTicks[ barnum ] + 0.5 ); + tickmark = min( m_nTicks[ barnum ], tickmark ); + tickmark = max( 0, tickmark ); + + int thumbwidth = 20; + int thumbheight = 14; + int xoffset = -thumbwidth / 2; + int yoffset = -thumbheight / 2 + 2; + + int leftedge = rcBar.left + (int)( (float)( rcBar.right - rcBar.left ) * (float)(tickmark) / (float)m_nTicks[ barnum ] ); + + rcThumb.left = leftedge + xoffset; + rcThumb.right = rcThumb.left + thumbwidth; + rcThumb.top = rcBar.top + yoffset; + rcThumb.bottom = rcThumb.top + thumbheight; +} + +void mxExpressionSlider::DrawBar( HDC& dc ) +{ + RECT rcBar; + + GetBarRect( rcBar ); + + HPEN oldPen; + + HPEN shadow; + HBRUSH face; + HPEN hilight; + + shadow = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) ); + hilight = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DHIGHLIGHT ) ); + face = CreateSolidBrush( GetSysColor( COLOR_3DFACE ) ); + + oldPen = (HPEN)SelectObject( dc, hilight ); + + MoveToEx( dc, rcBar.left, rcBar.bottom, NULL ); + LineTo( dc, rcBar.left, rcBar.top ); + LineTo( dc, rcBar.right, rcBar.top ); + + SelectObject( dc, shadow ); + + LineTo( dc, rcBar.right, rcBar.bottom ); + LineTo( dc, rcBar.left, rcBar.bottom ); + + rcBar.left += 1; + //rcBar.right -= 1; + rcBar.top += 1; + rcBar.bottom -= 1; + + FillRect( dc, &rcBar, face ); + + SelectObject( dc, oldPen ); + + DeleteObject( face ); + DeleteObject( shadow ); + DeleteObject( hilight ); +} + +void mxExpressionSlider::DrawThumb( int barnum, HDC& dc ) +{ + RECT rcThumb; + + GetThumbRect( barnum, rcThumb ); + + // Draw it + + + HPEN oldPen; + + HPEN shadow; + HBRUSH face; + HPEN hilight; + + shadow = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DDKSHADOW ) ); + hilight = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DHIGHLIGHT ) ); + + switch ( barnum ) + { + default: + case MAGNITUDE_BAR: + { + float frac; + if (m_flCurrent[ barnum ] < 0) + { + frac = m_flCurrent[ barnum ] / m_flMin[ barnum ]; + } + else + { + frac = m_flCurrent[ barnum ] / m_flMax[ barnum ]; + } + frac = min( 1.0f, frac ); + frac = max( 0.0f, frac ); + + COLORREF clr = GetSysColor( COLOR_3DFACE ); + int r, g, b; + r = GetRValue( clr ); + g = GetRValue( clr ); + b = GetRValue( clr ); + + // boost colors + r = (int)( (1-frac) * b ); + b = min( 255, (int)(r + ( 255 - r ) * frac ) ); + g = (int)( (1-frac) * g ); + + face = CreateSolidBrush( RGB( r, g, b ) ); + } + break; + case BALANCE_BAR: + { + float frac = m_flCurrent[ barnum ]; + frac = min( 1.0f, frac ); + frac = max( 0.0f, frac ); + + COLORREF clr = GetSysColor( COLOR_3DFACE ); + int r, g, b; + r = GetRValue( clr ); + g = GetRValue( clr ); + b = GetRValue( clr ); + + // boost colors toward red if we are not at 0.5 + float boost = 2.0 * ( fabs( frac - 0.5f ) ); + + r = r + ( 255 - r ) * boost; + g = ( 1 - boost ) * g; + b = ( 1 - boost ) * b; + + face = CreateSolidBrush( RGB( r, g, b ) ); + } + break; + } + + //rcThumb.left += 1; + //rcThumb.right -= 1; + //rcThumb.top += 1; + //rcThumb.bottom -= 1; + + //FillRect( dc, &rcThumb, face ); + POINT region[3]; + int cPoints = 3; + + InflateRect( &rcThumb, -2, 0 ); + +// int height = rcThumb.bottom - rcThumb.top; +// int offset = height / 2 + 1; + int offset = 2; + + switch ( barnum ) + { + case MAGNITUDE_BAR: + default: + { + region[ 0 ].x = rcThumb.left; + region[ 0 ].y = rcThumb.top; + + region[ 1 ].x = rcThumb.right; + region[ 1 ].y = rcThumb.top; + + region[ 2 ].x = ( rcThumb.left + rcThumb.right ) / 2; + region[ 2 ].y = rcThumb.bottom - offset; + } + break; + case BALANCE_BAR: + { + region[ 0 ].x = ( rcThumb.left + rcThumb.right ) / 2; + region[ 0 ].y = rcThumb.top + offset; + + region[ 1 ].x = rcThumb.left; + region[ 1 ].y = rcThumb.bottom; + + region[ 2 ].x = rcThumb.right; + region[ 2 ].y = rcThumb.bottom; + + } + break; + } + + HRGN rgn = CreatePolygonRgn( region, cPoints, ALTERNATE ); + + int oldPF = SetPolyFillMode( dc, ALTERNATE ); + FillRgn( dc, rgn, face ); + SetPolyFillMode( dc, oldPF ); + + DeleteObject( rgn ); + + oldPen = (HPEN)SelectObject( dc, hilight ); + + MoveToEx( dc, region[0].x, region[0].y, NULL ); + LineTo( dc, region[1].x, region[1].y ); + SelectObject( dc, shadow ); + LineTo( dc, region[2].x, region[2].y ); + SelectObject( dc, hilight ); + LineTo( dc, region[0].x, region[0].y ); + + SelectObject( dc, oldPen ); + + DeleteObject( face ); + DeleteObject( shadow ); + DeleteObject( hilight ); +} + +void mxExpressionSlider::DrawTitle( HDC &dc ) +{ + if ( !m_bDrawTitle ) + return; + + HWND wnd = (HWND)getHandle(); + if ( !wnd ) + return; + + RECT rc; + GetClientRect( wnd, &rc ); + rc.right = m_nTitleWidth; + rc.left += 16; + + InflateRect( &rc, -5, -2 ); + + char sz[ 128 ]; + sprintf( sz, "%s", getLabel() ); + + HFONT fnt, oldfont; + + fnt = CreateFont( + -12 // H + , 0 // W + , 0 // Escapement + , 0 // Orient + , FW_NORMAL // Wt. (BOLD) + , 0 // Ital. + , 0 // Underl. + , 0 // SO + , ANSI_CHARSET // Charset + , OUT_TT_PRECIS // Out prec. + , CLIP_DEFAULT_PRECIS // Clip prec. + , PROOF_QUALITY // Qual. + , VARIABLE_PITCH | FF_DONTCARE // Pitch and Fam. + , "Arial" ); + + COLORREF oldColor; + + if (!isEdited( 0 )) + { + oldColor = SetTextColor( dc, GetSysColor( COLOR_BTNTEXT ) ); + } + else + { + oldColor = SetTextColor( dc, RGB( 255, 0, 0 ) ); + } + int oldMode = SetBkMode( dc, TRANSPARENT ); + oldfont = (HFONT)SelectObject( dc, fnt ); + + DrawText( dc, sz, -1, &rc, DT_NOPREFIX | DT_VCENTER | DT_SINGLELINE | DT_LEFT | DT_WORD_ELLIPSIS ); + + SelectObject( dc, oldfont ); + DeleteObject( fnt ); + SetBkMode( dc, oldMode ); + SetTextColor( dc, oldColor ); +} + +void mxExpressionSlider::redraw() +{ + HWND wnd = (HWND)getHandle(); + if ( !wnd ) + return; + + HDC finalDC = GetDC( wnd ); + if ( !finalDC ) + return; + + RECT rc; + GetClientRect( wnd, &rc ); + + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + HDC dc = CreateCompatibleDC( finalDC ); + HBITMAP oldbm, bm; + + bm = CreateCompatibleBitmap( finalDC, w, h ); + + oldbm = (HBITMAP)SelectObject( dc, bm ); + + HBRUSH br = CreateSolidBrush( GetSysColor( COLOR_3DFACE ) ); + + FillRect( dc, &rc, br ); + + DeleteObject( br ); + + DrawTitle( dc ); + + DrawBar( dc ); + + // Draw slider + for ( int i = ( m_bPaired ? 1 : 0 ); i >= 0 ; i-- ) + { + DrawThumb( i, dc ); + } + + BitBlt( finalDC, 0, 0, w, h, dc, 0, 0, SRCCOPY ); + + SelectObject( dc, oldbm ); + + DeleteObject( bm ); + + DeleteDC( dc ); + + ReleaseDC( wnd, finalDC ); + ValidateRect( wnd, &rc ); +} + +void mxExpressionSlider::MoveThumb( int barnum, int xpos, bool finish ) +{ + RECT rcBar; + + GetBarRect( rcBar ); + + if ( xpos < rcBar.left ) + { + m_flCurrent[ barnum ] = m_flMin[ barnum ]; + } + else if ( xpos > rcBar.right ) + { + m_flCurrent[ barnum ] = m_flMax[ barnum ]; + } + else + { + float frac = (float)( xpos - rcBar.left ) / (float)( rcBar.right - rcBar.left ); + // snap slider to nearest "tick" so that it get drawn in the correct place + int curtick = (int)( frac * m_nTicks[ 0 ] + 0.5); + m_flCurrent[ barnum ] = m_flMin[ barnum ] + ((float)curtick / (float)m_nTicks[ 0 ]) * (m_flMax[ barnum ] - m_flMin[ barnum ]); + } + + // update equivalent setting + m_flSetting[ 0 ] = getValue( 0 ); + m_flSetting[ 1 ] = getValue( 1 ); + + m_bIsEdited[ 0 ] = true; + m_bIsEdited[ 1 ] = true; + + // Send message to parent + HWND parent = (HWND)( getParent() ? getParent()->getHandle() : NULL ); + if ( parent ) + { + LPARAM lp; + WPARAM wp; + + wp = MAKEWPARAM( finish ? SB_ENDSCROLL : SB_THUMBPOSITION, barnum ); + lp = (long)getHandle(); + + SendMessage( parent, WM_HSCROLL, wp, lp ); + } + + BoundValue(); + redraw(); +} + +bool mxExpressionSlider::PaintBackground( void ) +{ + return false; +} + +int mxExpressionSlider::handleEvent( mxEvent *event ) +{ + int iret = 0; + switch ( event->event ) + { + case mxEvent::Action: + { + iret = 1; + switch ( event->action ) + { + default: + iret = 0; + break; + case IDC_INFLUENCE: + { + SetFocus( (HWND)getHandle() ); + + setEdited( 0, false ); + setEdited( 1, false ); + + // Send message to parent + HWND parent = (HWND)( getParent() ? getParent()->getHandle() : NULL ); + if ( parent ) + { + LPARAM lp; + WPARAM wp; + + wp = MAKEWPARAM( SB_ENDSCROLL, m_nCurrentBar ); + lp = (long)getHandle(); + + SendMessage( parent, WM_HSCROLL, wp, lp ); + } + break; + } + } + } + break; + case mxEvent::MouseDown: + { + SetFocus( (HWND)getHandle() ); + + if ( !m_bDraggingThumb ) + { + RECT rcThumb; + POINT pt; + + pt.x = (short)event->x; + pt.y = (short)event->y; + + m_nCurrentBar = ( event->buttons & mxEvent::MouseRightButton ) ? BALANCE_BAR : MAGNITUDE_BAR; + GetThumbRect( m_nCurrentBar, rcThumb ); + + if ( PtInRect( &rcThumb, pt ) ) + { + m_bDraggingThumb = true; + } + + // Snap position if they didn't click on the thumb itself +#if 0 + else + { + m_bDraggingThumb = true; + MoveThumb( m_nCurrentBar, (short)event->x, false ); + } +#endif + } + iret = 1; + } + break; + case mxEvent::MouseDrag: + case mxEvent::MouseMove: + { + if ( m_bDraggingThumb ) + { + m_pInfluence->setChecked( true ); + MoveThumb( m_nCurrentBar, (short)event->x, false ); + iret = 1; + } + } + break; + case mxEvent::MouseUp: + { + if ( m_bDraggingThumb ) + { + m_pInfluence->setChecked( true ); + m_bDraggingThumb = false; + MoveThumb( m_nCurrentBar, (short)event->x, true ); + m_nCurrentBar = 0; + } + iret = 1; + } + break; + case mxEvent::KeyDown: + { + if ( event->key == VK_RETURN || + event->key == 'S' ) + { + // See if there is an event in the flex animation window + g_pExpressionTool->OnSetSingleKeyFromFlex( getLabel() ); + } + } + break; + } + + return iret; +} |