📄 expressiontool.cpp
字号:
#include <stdio.h>
#include "hlfaceposer.h"
#include "ExpressionTool.h"
#include "mdlviewer.h"
#include "choreowidgetdrawhelper.h"
#include "TimelineItem.h"
#include "expressions.h"
#include "expclass.h"
#include "choreoevent.h"
#include "StudioModel.h"
#include "choreoscene.h"
#include "choreoactor.h"
#include "choreochannel.h"
#include "ChoreoView.h"
#include "InputProperties.h"
#include "ControlPanel.h"
#include "FlexPanel.h"
#include "mxExpressionTray.h"
#include "ExpressionProperties.h"
#include "vstdlib/strtools.h"
#include "faceposer_models.h"
#include "UtlBuffer.h"
#include "FileSystem.h"
#include "cmdlib.h"
#include "scriplib.h"
#include "iscenetokenprocessor.h"
#include "MatSysWin.h"
#include "choreoviewcolors.h"
ExpressionTool *g_pExpressionTool = 0;
#define TRAY_HEIGHT 55
#define TRAY_ITEM_INSET 10
#define MAX_TIME_ZOOM 1000
// 10% per step
#define TIME_ZOOM_STEP 2
void SetupFlexControllerTracks( studiohdr_t *hdr, CChoreoEvent *event );
class CExpressionToolWorkspace : public mxWindow
{
public:
CExpressionToolWorkspace( mxWindow *parent );
~CExpressionToolWorkspace();
virtual int handleEvent( mxEvent *event );
virtual void redraw( void );
virtual bool PaintBackground( void )
{
redraw();
return false;
}
void RepositionVSlider( void );
int ComputeVPixelsNeeded( void );
// Playback tick
void Think( float dt );
void LayoutItems( bool force = false );
void HideTimelines( void );
void CollapseAll( TimelineItem *keepExpanded );
void ExpandAll( void );
void ExpandValid( void );
void DisableAllExcept( void );
void EnableValid( void );
TimelineItem *GetItem( int number );
TimelineItem *GetClickedItem( void );
void ClearClickedItem( void );
void OnSnapAll();
void OnDeleteColumn();
void MoveSelectedSamples( float dfdx, float dfdy, bool snap );
void DeleteSelectedSamples( void );
int CountSelectedSamples( void );
void DeselectAll( void );
void SelectPoints( float start, float end );
void DrawEventEnd( CChoreoWidgetDrawHelper& drawHelper );
void OnSortByUsed( void );
void OnSortByName( void );
private:
int GetItemUnderMouse( int mx, int my );
void MouseToToolMouse( int& mx, int& my, char *reason );
TimelineItem *m_pItems[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ];
// The scroll bars
mxScrollbar *m_pVertScrollBar;
int m_nLastVPixelsNeeded;
int m_nTopOffset;
int m_nScrollbarHeight;
int m_nItemGap;
int m_nFocusItem;
};
CExpressionToolWorkspace::CExpressionToolWorkspace( mxWindow *parent ) :
mxWindow( parent, 0, 0, 0, 0 )
{
HWND wnd = (HWND)getHandle();
DWORD style = GetWindowLong( wnd, GWL_STYLE );
style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
SetWindowLong( wnd, GWL_STYLE, style );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
m_pItems[ i ] = new TimelineItem( this );
}
m_nItemGap = 2;
m_nScrollbarHeight = 12;
m_nTopOffset = 0;
m_nLastVPixelsNeeded = -1;
m_pVertScrollBar = new mxScrollbar( this, 0, 0, 12, 100, IDC_EXPRESSIONTOOLVSCROLL, mxScrollbar::Vertical );
m_nFocusItem = -1;
HideTimelines();
LayoutItems();
}
CExpressionToolWorkspace::~CExpressionToolWorkspace()
{
}
void CExpressionToolWorkspace::redraw()
{
CChoreoWidgetDrawHelper drawHelper( this );
DrawEventEnd( drawHelper );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
if ( !item )
continue;
if ( !item->GetVisible() )
continue;
RECT rcBounds;
item->GetBounds( rcBounds );
if ( rcBounds.bottom < 0 )
continue;
if ( rcBounds.top > h2() )
continue;
item->Draw( drawHelper );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *elem1 -
// *elem2 -
// Output : int
//-----------------------------------------------------------------------------
int SortFuncByUse(const void *elem1, const void *elem2 )
{
TimelineItem *item1 = *( TimelineItem ** )elem1;
TimelineItem *item2 = *( TimelineItem ** )elem2;
if ( item1->IsValid() == item2->IsValid() )
return 0;
if ( !item2->IsValid() && item1->IsValid() )
return -1;
return 1;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *elem1 -
// *elem2 -
// Output : int
//-----------------------------------------------------------------------------
int SortFuncByName(const void *elem1, const void *elem2 )
{
TimelineItem *item1 = *( TimelineItem ** )elem1;
TimelineItem *item2 = *( TimelineItem ** )elem2;
CFlexAnimationTrack *track1 = item1->GetSafeTrack();
CFlexAnimationTrack *track2 = item2->GetSafeTrack();
if ( !track1 || !track2 )
{
if ( track1 )
return -1;
if ( track2 )
return 1;
return 0;
}
return stricmp( track1->GetFlexControllerName(), track2->GetFlexControllerName() );
}
void CExpressionToolWorkspace::OnSortByUsed( void )
{
qsort( m_pItems, GLOBAL_STUDIO_FLEX_CONTROL_COUNT, sizeof( TimelineItem * ), SortFuncByUse );
LayoutItems( false );
}
void CExpressionToolWorkspace::OnSortByName( void )
{
qsort( m_pItems, GLOBAL_STUDIO_FLEX_CONTROL_COUNT, sizeof( TimelineItem * ), SortFuncByName );
LayoutItems( false );
}
void CExpressionToolWorkspace::DrawEventEnd( CChoreoWidgetDrawHelper& drawHelper )
{
CChoreoEvent *e = g_pExpressionTool->GetSafeEvent();
if ( !e )
return;
float duration = e->GetDuration();
if ( !duration )
return;
int leftx = g_pExpressionTool->GetPixelForTimeValue( duration ) -5;
if ( leftx >= w2() )
return;
RECT rcClient;
drawHelper.GetClientRect( rcClient );
drawHelper.DrawColoredLine(
COLOR_CHOREO_ENDTIME, PS_SOLID, 1,
leftx, rcClient.top, leftx, rcClient.bottom );
}
int CExpressionToolWorkspace::GetItemUnderMouse( int mx, int my )
{
POINT pt;
pt.x = mx;
pt.y = my;
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
if ( !item )
continue;
if ( !item->GetVisible() )
continue;
RECT rc;
item->GetBounds( rc );
if ( PtInRect( &rc, pt ) )
{
return i;
}
}
return -1;
}
void CExpressionToolWorkspace::MouseToToolMouse( int& mx, int& my, char *reason )
{
POINT pt;
int oldmx = mx;
pt.x = mx;
pt.y = my;
ClientToScreen( (HWND)getHandle(), &pt );
ScreenToClient( (HWND)getParent()->getHandle(), &pt );
mx = pt.x;
my = pt.y;
}
int CExpressionToolWorkspace::handleEvent( mxEvent *event )
{
int iret = 0;
switch ( event->event )
{
case mxEvent::MouseDown:
{
SetFocus( (HWND)getParent()->getHandle() );
{
int mx = (short)event->x;
int my = (short)event->y;
MouseToToolMouse( mx, my, "CExpressionToolWorkspace mousedown" );
g_pExpressionTool->SetClickedPos( mx, my );
g_pExpressionTool->SetMouseOverPos( mx, my );
g_pExpressionTool->DrawMouseOverPos();
}
int oldFocus = m_nFocusItem;
m_nFocusItem = GetItemUnderMouse( (short)event->x, (short)event->y );
if ( oldFocus != -1 &&
oldFocus != m_nFocusItem )
{
TimelineItem *item = GetItem( oldFocus );
if ( item )
{
item->DrawSelf();
}
}
if ( m_nFocusItem != -1 )
{
TimelineItem *item = GetItem( m_nFocusItem );
if ( item )
{
RECT rc;
item->GetBounds( rc );
event->x -= rc.left;
event->y -= rc.top;
iret = item->handleEvent( event );
}
}
iret = 1;
}
break;
case mxEvent::MouseDrag:
case mxEvent::MouseMove:
{
//
bool handled = false;
if ( m_nFocusItem != -1 )
{
TimelineItem *item = GetItem( m_nFocusItem );
if ( item )
{
RECT rc;
item->GetBounds( rc );
event->x -= rc.left;
event->y -= rc.top;
iret = item->handleEvent( event );
if ( event->event == mxEvent::MouseDrag )
{
int mx, my;
item->GetLastMouse( mx, my );
mx += rc.left;
my += rc.top;
MouseToToolMouse( mx, my, "CExpressionToolWorkspace mousedrag" );
g_pExpressionTool->SetMouseOverPos( mx, my );
g_pExpressionTool->DrawMouseOverPos();
handled = true;
}
}
}
if ( !handled )
{
int mx = (short)event->x;
int my = (short)event->y;
mx += TRAY_ITEM_INSET;
MouseToToolMouse( mx, my, "CExpressionToolWorkspace mousemove" );
g_pExpressionTool->SetMouseOverPos( mx, my );
g_pExpressionTool->DrawMouseOverPos();
}
}
break;
case mxEvent::MouseUp:
{
//
{
int mx = (short)event->x;
int my = (short)event->y;
MouseToToolMouse( mx, my, "CExpressionToolWorkspace mouseup" );
g_pExpressionTool->SetMouseOverPos( mx, my );
g_pExpressionTool->DrawMouseOverPos();
}
if ( m_nFocusItem != -1 )
{
TimelineItem *item = GetItem( m_nFocusItem );
if ( item )
{
RECT rc;
item->GetBounds( rc );
event->x -= rc.left;
event->y -= rc.top;
iret = item->handleEvent( event );
}
}
}
break;
case mxEvent::Size:
{
RepositionVSlider();
LayoutItems();
iret = 1;
}
break;
case mxEvent::MouseWheeled:
// Tell parent
{
if ( event->modifiers & mxEvent::KeyShift )
{
// Zoom time in / out
if ( event->height > 0 )
{
g_pExpressionTool->SetTimeZoomScale( min( g_pExpressionTool->GetTimeZoomScale() + TIME_ZOOM_STEP, MAX_TIME_ZOOM ) );
}
else
{
g_pExpressionTool->SetTimeZoomScale( max( g_pExpressionTool->GetTimeZoomScale() - TIME_ZOOM_STEP, TIME_ZOOM_STEP ) );
}
g_pExpressionTool->RepositionHSlider();
redraw();
iret = 1;
return iret;
}
int offset = 0;
int jump = 50;
if ( event->height < 0 )
{
offset = m_pVertScrollBar->getValue();
offset += jump;
offset = min( offset, m_pVertScrollBar->getMaxValue() );
}
else
{
offset = m_pVertScrollBar->getValue();
offset -= jump;
offset = max( offset, m_pVertScrollBar->getMinValue() );
}
m_pVertScrollBar->setValue( offset );
InvalidateRect( (HWND)m_pVertScrollBar->getHandle(), NULL, TRUE );
m_nTopOffset = offset;
LayoutItems();
iret = 1;
}
break;
case mxEvent::Action:
{
iret = 1;
switch ( event->action )
{
default:
iret = 0;
break;
case IDC_EXPRESSIONTOOLVSCROLL:
{
int offset = 0;
bool processed = true;
switch ( event->modifiers )
{
case SB_THUMBTRACK:
offset = event->height;
break;
case SB_PAGEUP:
offset = m_pVertScrollBar->getValue();
offset -= 100;
offset = max( offset, m_pVertScrollBar->getMinValue() );
break;
case SB_PAGEDOWN:
offset = m_pVertScrollBar->getValue();
offset += 100;
offset = min( offset, m_pVertScrollBar->getMaxValue() );
break;
case SB_LINEDOWN:
offset = m_pVertScrollBar->getValue();
offset += 10;
offset = min( offset, m_pVertScrollBar->getMaxValue() );
break;
case SB_LINEUP:
offset = m_pVertScrollBar->getValue();
offset -= 10;
offset = max( offset, m_pVertScrollBar->getMinValue() );
break;
default:
processed = false;
break;
}
if ( processed )
{
m_pVertScrollBar->setValue( offset );
InvalidateRect( (HWND)m_pVertScrollBar->getHandle(), NULL, TRUE );
m_nTopOffset = offset;
LayoutItems();
}
}
}
}
break;
}
return iret;
}
void CExpressionToolWorkspace::HideTimelines( void )
{
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
Assert( item );
item->SetVisible( false );
}
redraw();
}
TimelineItem *CExpressionToolWorkspace::GetItem( int number )
{
if ( number < 0 || number >= GLOBAL_STUDIO_FLEX_CONTROL_COUNT )
{
return NULL;
}
return m_pItems[ number ];
}
TimelineItem *CExpressionToolWorkspace::GetClickedItem( void )
{
return GetItem( m_nFocusItem );
}
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -