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/mxexpressiontray.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/hlfaceposer/mxexpressiontray.cpp')
| -rw-r--r-- | utils/hlfaceposer/mxexpressiontray.cpp | 1212 |
1 files changed, 1212 insertions, 0 deletions
diff --git a/utils/hlfaceposer/mxexpressiontray.cpp b/utils/hlfaceposer/mxexpressiontray.cpp new file mode 100644 index 0000000..57bdd6d --- /dev/null +++ b/utils/hlfaceposer/mxexpressiontray.cpp @@ -0,0 +1,1212 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "hlfaceposer.h" +#include <windows.h> +#include <stdio.h> +#include <mxtk/mxWindow.h> +#include <mxtk/mxScrollBar.h> +#include "mxexpressiontray.h" +#include "expressions.h" +#include "expclass.h" +#include "ControlPanel.h" +#include "FlexPanel.h" +#include <mxtk/mxPopupMenu.h> +#include "ChoreoView.h" +#include "StudioModel.h" +#include "ExpressionProperties.h" +#include "InputProperties.h" +#include "ViewerSettings.h" +#include "mxExpressionTab.h" +#include "choreowidgetdrawhelper.h" +#include "ExpressionTool.h" +#include "faceposer_models.h" +#include "tier0/icommandline.h" +#include "filesystem.h" + +#define MAX_THUMBNAILSIZE 256 +#define MIN_THUMBNAILSIZE 64 +#define THUMBNAIL_SIZE_STEP 4 +#define DEFAULT_THUMBNAIL_SIZE 128 +#define TOP_GAP 45 + +mxExpressionTray *g_pExpressionTrayTool = 0; + +mxExpressionTray::mxExpressionTray( mxWindow *parent, int id /*=0*/ ) +: IFacePoserToolWindow( "ExpressionTrayTool", "Expressions" ), mxWindow( parent, 0, 0, 0, 0, "ExpressionTrayTool", id ) +{ + setId( id ); + + m_nTopOffset = 0; + slScrollbar = new mxScrollbar( this, 0, 0, 18, 100, IDC_TRAYSCROLL, mxScrollbar::Vertical ); + + m_nLastNumExpressions = -1; + + m_nGranularity = 10; + + m_nPrevCell = -1; + m_nCurCell = -1; + + m_nClickedCell = -1; + + m_nButtonSquare = 16; + + m_nGap = 4; + m_nDescriptionHeight = 34; + m_nSnapshotWidth = g_viewerSettings.thumbnailsize; + m_nSnapshotWidth = max( MIN_THUMBNAILSIZE, m_nSnapshotWidth ); + m_nSnapshotWidth = min( MAX_THUMBNAILSIZE, m_nSnapshotWidth ); + + g_viewerSettings.thumbnailsize = m_nSnapshotWidth; + + m_nSnapshotHeight = m_nSnapshotWidth + m_nDescriptionHeight; + + m_pButtons = NULL; + + m_nPreviousExpressionCount = -1; + + m_bDragging = false; + m_nDragCell = -1; + + CreateButtons(); + + g_pExpressionClass = new mxExpressionTab( this, 5, 5, 500, 20, IDC_EXPRESSIONCLASS ); + + m_pABButton = new mxButton( this, 520, 8, 50, 18, "A/B", IDC_AB ); + m_pThumbnailIncreaseButton = new mxButton( this, 0, 0, 18, 18, "+", IDC_THUMBNAIL_INCREASE ); + m_pThumbnailDecreaseButton = new mxButton( this, 0, 0, 18, 18, "-", IDC_THUMBNAIL_DECREASE ); + +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : mxExpressionTray::~mxExpressionTray +//----------------------------------------------------------------------------- +mxExpressionTray::~mxExpressionTray ( void ) +{ + DeleteAllButtons(); + g_pExpressionTrayTool = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : cellsize - +//----------------------------------------------------------------------------- +void mxExpressionTray::SetCellSize( int cellsize ) +{ + m_nSnapshotWidth = cellsize; + m_nSnapshotHeight = cellsize + m_nDescriptionHeight; + + DeleteAllButtons(); + CreateButtons(); + + redraw(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::Deselect( void ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( active ) + { + for ( int i = 0 ; i < active->GetNumExpressions(); i++ ) + { + CExpression *exp = active->GetExpression( i ); + if ( exp ) + { + exp->SetSelected( false ); + } + } + } + + m_nCurCell = m_nPrevCell = -1; + redraw(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : exp - +//----------------------------------------------------------------------------- +void mxExpressionTray::Select( int exp, bool deselect /*=true*/ ) +{ + int oldcell = m_nCurCell; + + if ( deselect ) + { + Deselect(); + } + + m_nPrevCell = oldcell; + m_nCurCell = exp; + + if ( m_nCurCell >= 0 ) + { + CExpClass *active = expressions->GetActiveClass(); + if ( active ) + { + CExpression *exp = active->GetExpression( m_nCurCell ); + if ( exp ) + { + exp->SetSelected( true ); + } + } + } + + redraw(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *btn - +//----------------------------------------------------------------------------- +void mxExpressionTray::AddButton( const char *name, const char *tooltip, const char *bitmap, ETMEMBERFUNC pfnCallback, + bool active, int x, int y, int w, int h ) +{ + mxETButton *btn = new mxETButton; + strcpy( btn->m_szName, name ); + strcpy( btn->m_szToolTip, tooltip ); + btn->m_bActive = active; + btn->m_rc.left = x; + btn->m_rc.top = y; + btn->m_rc.right = x + w; + btn->m_rc.bottom = y + h; + + btn->m_pImage = new mxbitmapdata_t; + Assert( btn->m_pImage ); + btn->m_pImage->valid = false; + LoadBitmapFromFile( bitmap, *btn->m_pImage ); + + btn->m_fnCallback = pfnCallback; + + btn->next = m_pButtons; + m_pButtons = btn; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::CreateButtons( void ) +{ + int x = m_nSnapshotWidth - 2 * ( m_nButtonSquare + 4 ); + int y = 4; + + AddButton( "undo", "Undo", "gfx/hlfaceposer/undo.bmp", &mxExpressionTray::ET_Undo, true, x, y, m_nButtonSquare, m_nButtonSquare ); + + x += ( m_nButtonSquare + 4 ); + + AddButton( "redo", "Redo", "gfx/hlfaceposer/redo.bmp", &mxExpressionTray::ET_Redo, true, x, y, m_nButtonSquare, m_nButtonSquare ); +} + +void mxExpressionTray::ActivateButton( const char *name, bool active ) +{ + mxETButton *btn = FindButton( name ); + if ( !name ) + return; + + btn->m_bActive = active; +} + +mxExpressionTray::mxETButton *mxExpressionTray::FindButton( const char *name ) +{ + mxETButton *p = m_pButtons; + while ( p ) + { + if ( !stricmp( p->m_szName, name ) ) + return p; + p = p->next; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::DeleteAllButtons( void ) +{ + mxETButton *p = m_pButtons, *n; + while ( p ) + { + n = p->next; + delete p->m_pImage; + delete p; + p = n; + } + m_pButtons = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : x - +// y - +// Output : mxExpressionTray::mxETButton +//----------------------------------------------------------------------------- +mxExpressionTray::mxETButton *mxExpressionTray::GetItemUnderCursor( int x, int y ) +{ + // Convert to cell space + int cell = GetCellUnderPosition( x, y ); + if ( cell == -1 ) + { + return NULL; + } + + // Cell is off screen? + int cx, cy, cw, ch; + if ( !ComputeRect( cell, cx, cy, cw, ch ) ) + { + return NULL; + } + + + mxETButton *p = m_pButtons; + while ( p ) + { + if ( p->m_bActive && + x >= cx && + x <= cx + cw && + y >= cy && + y <= cy + ch ) + { + // In-side cell + int cellx = x - cx; + int celly = y - cy; + + if ( cellx >= p->m_rc.left && + cellx <= p->m_rc.right && + celly >= p->m_rc.top && + celly <= p->m_rc.bottom ) + { + return p; + } + } + p = p->next; + } + + return NULL; +} + +void mxExpressionTray::DrawButton( CChoreoWidgetDrawHelper& helper, int cell, mxETButton *btn ) +{ + if ( !btn || !btn->m_pImage || !btn->m_pImage->valid ) + return; + + if ( !btn->m_bActive ) + return; + + int x, y, w, h; + if ( !ComputeRect( cell, x, y, w, h ) ) + return; + + x += btn->m_rc.left; + y += btn->m_rc.top; + w = btn->m_rc.right - btn->m_rc.left; + h = btn->m_rc.bottom - btn->m_rc.top; + + HDC dc = helper.GrabDC(); + + DrawBitmapToDC( dc, x, y, w, h, *btn->m_pImage ); + helper.DrawOutlinedRect( RGB( 170, 170, 170 ), PS_SOLID, 1, x, y, x + w, y + h ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : int +//----------------------------------------------------------------------------- +int mxExpressionTray::ComputePixelsNeeded( void ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return 100; + + // Remove scroll bar + int w = this->w2() - 16; + + int colsperrow; + + colsperrow = ( w - m_nGap ) / ( m_nSnapshotWidth + m_nGap ); + // At least one + colsperrow = max( 1, colsperrow ); + + int rowsneeded = ( ( active->GetNumExpressions() + colsperrow - 1 ) / colsperrow ); + return rowsneeded * ( m_nSnapshotHeight + m_nGap ) + m_nGap + TOP_GAP + GetCaptionHeight(); +} + +bool mxExpressionTray::ComputeRect( int cell, int& rcx, int& rcy, int& rcw, int& rch ) +{ + // Remove scroll bar + int w = this->w2() - 16; + + int colsperrow; + + colsperrow = ( w - m_nGap ) / ( m_nSnapshotWidth + m_nGap ); + // At least one + colsperrow = max( 1, colsperrow ); + + int row, col; + + row = cell / colsperrow; + col = cell % colsperrow; + + // don't allow partial columns + + rcx = m_nGap + col * ( m_nSnapshotWidth + m_nGap ); + rcy = GetCaptionHeight() + TOP_GAP + ( -m_nTopOffset * m_nGranularity ) + m_nGap + row * ( m_nSnapshotHeight + m_nGap ); + + // Starts off screen + if ( rcx < 0 ) + return false; + + // Ends off screen + if ( rcx + m_nSnapshotWidth + m_nGap > this->w2() ) + return false; + + // Allow partial in y direction + if ( rcy > this->h2() ) + return false; + + if ( rcy + m_nSnapshotHeight + m_nGap < 0 ) + return false; + + // Some portion is onscreen + rcw = m_nSnapshotWidth; + rch = m_nSnapshotHeight; + return true; +} + +void mxExpressionTray::DrawExpressionFocusRect( CChoreoWidgetDrawHelper& helper, int x, int y, int w, int h, COLORREF clr ) +{ + helper.DrawOutlinedRect( clr, PS_SOLID, 4, x, y, x + w, y + h ); +} + +void mxExpressionTray::DrawExpressionDescription( CChoreoWidgetDrawHelper& helper, int x, int y, int w, int h, const char *expressionname, const char *description ) +{ + int textheight = 15; + + RECT textRect; + textRect.left = x + 5; + textRect.top = y + h - 2 * textheight - 12; + textRect.right = x + w - 10; + textRect.bottom = y + h - 12; + + helper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 0, 0, 0 ), textRect, "%s", expressionname ); + +// DrawText( hdc, expressionname, strlen( expressionname ), &textRect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_WORD_ELLIPSIS ); + + OffsetRect( &textRect, 0, textheight ); + + helper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 63, 63, 63 ), textRect, "%s", description ); + +// DrawText( hdc, description, strlen( description ), &textRect, DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_WORD_ELLIPSIS ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dc - +// current - +// rcx - +// rcy - +// rcw - +// rch - +//----------------------------------------------------------------------------- +void mxExpressionTray::DrawDirtyFlag( CChoreoWidgetDrawHelper& helper, CExpression *current, int rcx, int rcy, int rcw, int rch ) +{ + // Not dirty + if ( !current || ( !current->CanUndo() && !current->GetDirty() ) ) + return; + + int fontsize = 14; + + RECT textRect; + textRect.left = rcx + 5; + textRect.right = rcx + rcw; + textRect.top = rcy + 5; + textRect.bottom = textRect.top + fontsize + 2; + + helper.DrawColoredText( "Arial", fontsize, FW_NORMAL, RGB( 100, 240, 255 ), textRect, "*" ); +} + +bool mxExpressionTray::PaintBackground( void ) +{ + redraw(); + return false; +} + +void mxExpressionTray::DrawThumbNail( CExpClass *active, CExpression *current, CChoreoWidgetDrawHelper& helper, int rcx, int rcy, int rcw, int rch, int c, int selected, bool updateselection ) +{ + if ( !current ) + return; + + HDC dc = helper.GrabDC(); + + helper.DrawFilledRect( GetSysColor( COLOR_BTNFACE ), rcx, rcy, rcw + rcx, rch + rcy ); + + if ( current->m_Bitmap[ models->GetActiveModelIndex() ].valid ) + { + DrawBitmapToDC( dc, rcx, rcy, rcw, rch - m_nDescriptionHeight, current->m_Bitmap[ models->GetActiveModelIndex() ] ); + helper.DrawOutlinedRect( RGB( 127, 127, 127 ), PS_SOLID, 1, rcx, rcy, rcx + rcw, rcy + rch - m_nDescriptionHeight ); + } + + DrawDirtyFlag( helper, current, rcx, rcy, rcw, rch ); + + DrawExpressionDescription( helper, rcx, rcy, rcw, rch, current->name, current->description ); + + if ( c == selected ) + { + DrawExpressionFocusRect( helper, rcx, rcy, rcw, rch - m_nDescriptionHeight, RGB( 255, 100, 63 ) ); + + if ( updateselection ) + { + m_nPrevCell = -1; + m_nCurCell = c; + } + + if ( current->CanUndo() || current->CanRedo() ) + { + if ( current->CanUndo() ) + { + DrawButton( helper, c, FindButton( "undo" ) ); + } + + if ( current->CanRedo() ) + { + DrawButton( helper, c, FindButton( "redo" ) ); + } + + RECT rc; + rc.left = rcx + rcw - 2 * ( m_nButtonSquare + 4 ); + rc.top = rcy + m_nButtonSquare + 6; + rc.right = rc.left + 2 * ( m_nButtonSquare + 4 ); + rc.bottom = rc.top + 15; + + helper.DrawColoredText( "Arial", 9, FW_NORMAL, RGB( 200, 200, 200 ), rc, + "%i/%i", current->UndoCurrent(), current->UndoLevels() ); + } + + } + else + { + if ( current->GetSelected() ) + { + DrawExpressionFocusRect( helper, rcx, rcy, rcw, rch - m_nDescriptionHeight, RGB( 127, 127, 220 ) ); + } + } +} + +void mxExpressionTray::redraw() +{ + if ( !ToolCanDraw() ) + return; + + bool updateSelection = false; + + CExpClass *active = expressions->GetActiveClass(); + if ( active && active->GetNumExpressions() != m_nPreviousExpressionCount ) + { + m_nTopOffset = 0; + + RepositionSlider(); + m_nPreviousExpressionCount = active->GetNumExpressions(); + } + + CChoreoWidgetDrawHelper helper( this, GetSysColor( COLOR_BTNFACE ) ); + HandleToolRedraw( helper ); + + int w, h; + w = w2(); + h = h2(); + + if ( active ) + { + RECT clipRect; + helper.GetClientRect( clipRect ); + + clipRect.top += TOP_GAP + GetCaptionHeight(); + + helper.StartClipping( clipRect ); + + if ( m_nLastNumExpressions != active->GetNumExpressions() ) + { + m_nTopOffset = 0; + m_nLastNumExpressions = active->GetNumExpressions(); + RepositionSlider(); + updateSelection = true; + } + + int selected = active->GetSelectedExpression(); + + int rcx, rcy, rcw, rch; + + int c = 0; + while ( c < active->GetNumExpressions() ) + { + if ( !ComputeRect( c, rcx, rcy, rcw, rch ) ) + { + c++; + continue; + } + + CExpression *current = active->GetExpression( c ); + if ( !current ) + break; + + DrawThumbNail( active, current, helper, rcx, rcy, rcw, rch, c, selected, updateSelection ); + + c++; + } + + helper.StopClipping(); + + } + else + { + + RECT rc; + helper.GetClientRect( rc ); + + // Arial 36 normal + char sz[ 256 ]; + sprintf( sz, "No expression file loaded" ); + + int pointsize = 18; + + int textlen = helper.CalcTextWidth( "Arial", pointsize, FW_NORMAL, sz ); + + RECT rcText; + rcText.top = ( rc.bottom - rc.top ) / 2 - pointsize / 2; + rcText.bottom = rcText.top + pointsize + 10; + int fullw = rc.right - rc.left; + + rcText.left = rc.left + ( fullw - textlen ) / 2; + rcText.right = rcText.left + textlen; + + helper.DrawColoredText( "Arial", pointsize, FW_NORMAL, RGB( 80, 80, 80 ), rcText, sz ); + } + + +// ValidateRect( (HWND)getHandle(), &rc ); +} + +int mxExpressionTray::GetCellUnderPosition( int x, int y ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return -1; + + int rcx, rcy, rcw, rch; + int c = 0; + while ( c < active->GetNumExpressions() ) + { + if ( !ComputeRect( c, rcx, rcy, rcw, rch ) ) + { + c++; + continue; + } + + if ( x >= rcx && x <= rcx + rcw && + y >= rcy && y <= rcy + rch ) + { + return c; + } + + c++; + } + return -1; +} + +void mxExpressionTray::RepositionSlider( void ) +{ + int trueh = h2() - GetCaptionHeight(); + + int heightpixels = trueh / m_nGranularity; + int rangepixels = ComputePixelsNeeded() / m_nGranularity; + + if ( rangepixels < heightpixels ) + { + m_nTopOffset = 0; + slScrollbar->setVisible( false ); + } + else + { + slScrollbar->setVisible( true ); + } + + slScrollbar->setBounds( w2() - 16, GetCaptionHeight() + TOP_GAP, 16, trueh - TOP_GAP ); + + m_nTopOffset = max( 0, m_nTopOffset ); + m_nTopOffset = min( rangepixels, m_nTopOffset ); + + slScrollbar->setRange( 0, rangepixels ); + slScrollbar->setValue( m_nTopOffset ); + slScrollbar->setPagesize( heightpixels ); +} + +void mxExpressionTray::AB( void ) +{ + if ( m_nPrevCell == -1 && m_nCurCell == -1 ) + return; + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + if ( m_nPrevCell >= 0 && m_nPrevCell < active->GetNumExpressions() ) + { + active->SelectExpression( m_nPrevCell ); + } +} + +int mxExpressionTray::CountSelected( void ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return 0; + + int c = 0; + for ( int i = 0; i < active->GetNumExpressions(); i++ ) + { + CExpression *exp = active->GetExpression( i ); + if ( !exp ) + continue; + + if ( exp->GetSelected() ) + { + c++; + } + } + + return c; +} + +void mxExpressionTray::SetClickedCell( int cell ) +{ + m_nClickedCell = cell; +} + +void mxExpressionTray::ShowRightClickMenu( int mx, int my ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + mxPopupMenu *pop = new mxPopupMenu(); + Assert( pop ); + + CExpression *exp = NULL; + if ( m_nClickedCell != -1 ) + { + exp = active->GetExpression( m_nClickedCell ); + } + + pop->add( "New Expression...", IDC_CONTEXT_NEWEXP ); + if ( exp ) + { + pop->addSeparator(); + pop->add( va( "Edit '%s'...", exp->name ), IDC_CONTEXT_EDITEXP ); + pop->add( va( "Save '%s'", exp->name ), IDC_CONTEXT_SAVEEXP ); + + if ( exp->CanUndo() || exp->CanRedo() ) + { + pop->add( va( "Revert '%s'", exp->name ), IDC_CONTEXT_REVERT ); + } + pop->addSeparator(); + pop->add( va( "Delete '%s'", exp->name ), IDC_CONTEXT_DELETEXP ); + pop->addSeparator(); + pop->add( va( "Re-create thumbnail for '%s'", exp->name ), IDC_CONTEXT_CREATEBITMAP ); + } + + pop->popup( this, mx, my ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::DrawFocusRect( void ) +{ + HDC dc = GetDC( NULL ); + + ::DrawFocusRect( dc, &m_rcFocus ); + + ReleaseDC( NULL, dc ); +} + +static bool IsWindowOrChild( mxWindow *parent, HWND test ) +{ + HWND parentHwnd = (HWND)parent->getHandle(); + if ( test == parentHwnd || + IsChild( parentHwnd, test ) ) + { + return true; + } + return false; +} + +int mxExpressionTray::handleEvent (mxEvent *event) +{ + MDLCACHE_CRITICAL_SECTION_( g_pMDLCache ); + + int iret = 0; + + if ( HandleToolEvent( event ) ) + { + return iret; + } + + switch ( event->event ) + { + case mxEvent::Action: + { + iret = 1; + switch ( event->action ) + { + default: + iret = 0; + break; + case IDC_EXPRESSIONCLASS: + { + int index = g_pExpressionClass->getSelectedIndex(); + if ( index >= 0 ) + { + CExpClass *current = expressions->GetClass( index ); + if ( current ) + { + // Switch classname + expressions->ActivateExpressionClass( current ); + current->SelectExpression( 0 ); + } + } + } + break; + case IDC_CONTEXT_NEWEXP: + g_pFlexPanel->NewExpression(); + break; + case IDC_CONTEXT_EDITEXP: + if ( m_nClickedCell != -1 ) + { + g_pFlexPanel->EditExpression(); + } + break; + case IDC_CONTEXT_REVERT: + if ( m_nClickedCell != -1 ) + { + g_pFlexPanel->RevertExpression( m_nClickedCell ); + } + break; + case IDC_CONTEXT_SAVEEXP: + if ( m_nClickedCell != -1 ) + { + g_pFlexPanel->SaveExpression( m_nClickedCell ); + } + break; + case IDC_CONTEXT_DELETEXP: + if ( m_nClickedCell != -1 ) + { + g_pControlPanel->DeleteExpression( m_nClickedCell ); + } + break; + case IDC_TRAYSCROLL: + { + if (event->modifiers == SB_THUMBTRACK) + { + int offset = event->height; + + slScrollbar->setValue( offset ); + + m_nTopOffset = offset; + + redraw(); + } + else if ( event->modifiers == SB_PAGEUP ) + { + int offset = slScrollbar->getValue(); + + offset -= m_nGranularity; + offset = max( offset, slScrollbar->getMinValue() ); + + slScrollbar->setValue( offset ); + InvalidateRect( (HWND)slScrollbar->getHandle(), NULL, TRUE ); + + m_nTopOffset = offset; + + redraw(); + } + else if ( event->modifiers == SB_PAGEDOWN ) + { + int offset = slScrollbar->getValue(); + + offset += m_nGranularity; + offset = min( offset, slScrollbar->getMaxValue() ); + + slScrollbar->setValue( offset ); + InvalidateRect( (HWND)slScrollbar->getHandle(), NULL, TRUE ); + + m_nTopOffset = offset; + + redraw(); + } + } + break; + case IDC_AB: + { + AB(); + } + break; + case IDC_THUMBNAIL_INCREASE: + { + ThumbnailIncrease(); + } + break; + case IDC_THUMBNAIL_DECREASE: + { + ThumbnailDecrease(); + } + break; + case IDC_CONTEXT_CREATEBITMAP: + { + if ( m_nClickedCell >= 0 ) + { + CExpClass *active = expressions->GetActiveClass(); + if ( active ) + { + CExpression *exp = active->GetExpression( m_nClickedCell ); + if ( exp ) + { + active->SelectExpression( m_nClickedCell ); + exp->CreateNewBitmap( models->GetActiveModelIndex() ); + redraw(); + } + } + } + } + break; + } + break; + } + case mxEvent::MouseDown: + { + if ( !( event->buttons & mxEvent::MouseRightButton ) ) + { + // Figure out cell # + int cell = GetCellUnderPosition( event->x, event->y ); + CExpClass *active = expressions->GetActiveClass(); + if ( active ) + { + + if ( cell == m_nCurCell && cell >= 0 && cell < active->GetNumExpressions() ) + { + mxETButton *btn = GetItemUnderCursor( event->x, event->y ); + if ( btn && btn->m_fnCallback ) + { + (this->*(btn->m_fnCallback))( cell ); + return iret; + } + } + + if ( cell >= 0 && cell < active->GetNumExpressions() ) + { + active->SelectExpression( cell, event->modifiers & mxEvent::KeyShift ? false : true ); + + int cx, cy, cw, ch; + if ( ComputeRect( cell, cx, cy, cw, ch ) ) + { + m_bDragging = true; + m_nDragCell = cell; + + m_nXStart = (short)event->x; + m_nYStart = (short)event->y; + + m_rcFocus.left = cx; + m_rcFocus.top = cy; + m_rcFocus.right = cx + cw; + m_rcFocus.bottom = cy + ch - m_nDescriptionHeight; + + POINT pt; + pt.x = pt.y = 0; + ClientToScreen( (HWND)getHandle(), &pt ); + + OffsetRect( &m_rcFocus, pt.x, pt.y ); + + m_rcOrig = m_rcFocus; + + DrawFocusRect(); + } + } + else + { + Deselect(); + active->DeselectExpression(); + redraw(); + } + } + } + iret = 1; + } + break; + case mxEvent::MouseDrag: + { + if ( m_bDragging ) + { + // Draw drag line of some kind + DrawFocusRect(); + + // update pos + m_rcFocus = m_rcOrig; + OffsetRect( &m_rcFocus, ( (short)event->x - m_nXStart ), + ( (short)event->y - m_nYStart ) ); + + DrawFocusRect(); + } + iret = 1; + } + break; + case mxEvent::MouseUp: + { + iret = 1; + + if ( event->buttons & mxEvent::MouseRightButton ) + { + SetClickedCell( GetCellUnderPosition( (short)event->x, (short)event->y ) ); + ShowRightClickMenu( (short)event->x, (short)event->y ); + return iret; + } + + int cell = GetCellUnderPosition( event->x, event->y ); + CExpClass *active = expressions->GetActiveClass(); + + if ( m_bDragging ) + { + DrawFocusRect(); + m_bDragging = false; + // See if we let go on top of the choreo view + + if ( active ) + { + // Convert x, y to screen space + POINT pt; + pt.x = (short)event->x; + pt.y = (short)event->y; + ClientToScreen( (HWND)getHandle(), &pt ); + + HWND maybeTool = WindowFromPoint( pt ); + + // Now tell choreo view + CExpression *exp = active->GetExpression( m_nDragCell ); + if ( exp && maybeTool ) + { + if ( IsWindowOrChild( g_pChoreoView, maybeTool ) ) + { + if ( g_pChoreoView->CreateExpressionEvent( pt.x, pt.y, active, exp ) ) + { + return iret; + } + } + + if ( IsWindowOrChild( g_pExpressionTool, maybeTool ) ) + { + if ( g_pExpressionTool->SetFlexAnimationTrackFromExpression( pt.x, pt.y, active, exp ) ) + { + return iret; + } + } + } + } + } + + if ( active ) + { + // Over a new cell + if ( cell >= 0 && + cell < active->GetNumExpressions() && + cell != m_nCurCell && + m_nCurCell != -1 ) + { + // Swap cells + CExpression *exp = active->GetExpression( m_nCurCell ); + if ( exp ) + { + active->SwapExpressionOrder( m_nCurCell, cell ); + active->SetDirty( true ); + active->SelectExpression( cell ); + } + } + } + } + break; + case mxEvent::Size: + { + int width = w2(); + + int ch = GetCaptionHeight(); + + g_pExpressionClass->setBounds( 5, 5 + ch, width - 120, 20 ); + + m_pABButton->setBounds( width - 60, 4 + ch, 60, 16 ); + m_pThumbnailIncreaseButton->setBounds( width - 60 - 40, 4 + ch, 16, 16 ); + m_pThumbnailDecreaseButton->setBounds( width - 60 - 20, 4 + ch, 16, 16 ); + + m_nTopOffset = 0; + RepositionSlider(); + + redraw(); + iret = 1; + } + break; + case mxEvent::MouseWheeled: + { + // Figure out cell # + POINT pt; + + pt.x = event->x; + pt.y = event->y; + + ScreenToClient( (HWND)getHandle(), &pt ); + + if ( event->height < 0 ) + { + m_nTopOffset = min( m_nTopOffset + 10, slScrollbar->getMaxValue() ); + } + else + { + m_nTopOffset = max( m_nTopOffset - 10, 0 ); + } + RepositionSlider(); + redraw(); + iret = 1; + } + break; + }; + + if ( iret ) + { + SetActiveTool( this ); + } + return iret; +} + +void mxExpressionTray::ET_Undo( int cell ) +{ + g_pControlPanel->UndoExpression( cell ); +} + +void mxExpressionTray::ET_Redo( int cell ) +{ + g_pControlPanel->RedoExpression( cell ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::ThumbnailIncrease( void ) +{ + if ( m_nSnapshotWidth + THUMBNAIL_SIZE_STEP <= MAX_THUMBNAILSIZE ) + { + m_nSnapshotWidth += THUMBNAIL_SIZE_STEP; + g_viewerSettings.thumbnailsize = m_nSnapshotWidth; + m_nSnapshotHeight = m_nSnapshotWidth + m_nDescriptionHeight; + + Con_Printf( "Thumbnail size %i x %i\n", m_nSnapshotWidth, m_nSnapshotWidth ); + + redraw(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::ThumbnailDecrease( void ) +{ + if ( m_nSnapshotWidth - THUMBNAIL_SIZE_STEP >= MIN_THUMBNAILSIZE ) + { + m_nSnapshotWidth -= THUMBNAIL_SIZE_STEP; + g_viewerSettings.thumbnailsize = m_nSnapshotWidth; + m_nSnapshotHeight = m_nSnapshotWidth + m_nDescriptionHeight; + + Con_Printf( "Thumbnail size %i x %i\n", m_nSnapshotWidth, m_nSnapshotWidth ); + + redraw(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void mxExpressionTray::RestoreThumbnailSize( void ) +{ + m_nSnapshotWidth = g_viewerSettings.thumbnailsize; + m_nSnapshotWidth = max( MIN_THUMBNAILSIZE, m_nSnapshotWidth ); + m_nSnapshotWidth = min( MAX_THUMBNAILSIZE, m_nSnapshotWidth ); + + g_viewerSettings.thumbnailsize = m_nSnapshotWidth; + + m_nSnapshotHeight = m_nSnapshotWidth + m_nDescriptionHeight; + + redraw(); +} + +void mxExpressionTray::ReloadBitmaps( void ) +{ + CExpClass *cl; + int c = expressions->GetNumClasses(); + EnableStickySnapshotMode(); + for ( int i = 0 ; i < c; i++ ) + { + cl = expressions->GetClass( i ); + if ( !cl ) + continue; + + cl->ReloadBitmaps(); + } + DisableStickySnapshotMode(); + redraw(); +} + +bool IsUsingPerPlayerExpressions() +{ + bool bPerPlayerExpressions = false; + if ( CommandLine()->CheckParm( "-perplayerexpressions" ) ) + { + bPerPlayerExpressions = true; + } + else + { + // Returns the search path, each path is separated by ;s. Returns the length of the string returned + char pSearchPath[2048]; + if ( g_pFullFileSystem->GetSearchPath( "GAME", false, pSearchPath, sizeof(pSearchPath) ) ) + { + Q_FixSlashes( pSearchPath ); + if ( Q_stristr( pSearchPath, "\\tf" ) ) + { + bPerPlayerExpressions = true; + } + } + } + return bPerPlayerExpressions; +} + +void mxExpressionTray::OnModelChanged() +{ + if ( IsUsingPerPlayerExpressions() ) + { + Msg( "Closing current phoneme set\n" ); + + if ( !g_pControlPanel->Closeall() ) + return; + + // See if per-model overrides exist for this model + char fn[ MAX_PATH ]; + Q_snprintf( fn, sizeof( fn ), "expressions/%s/phonemes/phonemes.txt", models->GetActiveModelName() ); + + // Load appropriate classes + char rootDir[ MAX_PATH ]; + Q_snprintf( rootDir, sizeof( rootDir ), "%s/phonemes/", models->GetActiveModelName() ); + FacePoser_SetPhonemeRootDir( rootDir ); + + FacePoser_EnsurePhonemesLoaded(); + } + + ReloadBitmaps(); + RestoreThumbnailSize(); +}
\ No newline at end of file |