Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

746 lines
17 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "hlfaceposer.h"
#include "faceposertoolwindow.h"
#include "utlvector.h"
#include "tier1/strtools.h"
#include "MDLViewer.h"
#include "choreowidgetdrawhelper.h"
#include "StudioModel.h"
#include "faceposer_models.h"
extern MDLViewer *g_MDLViewer;
static CUtlVector< IFacePoserToolWindow * > g_Tools;
IFacePoserToolWindow *IFacePoserToolWindow::s_pActiveTool = NULL;
bool IFacePoserToolWindow::s_bToolsCanDraw;
static CUtlVector< IFacePoserToolWindow * > s_NeedRedraw;
IFacePoserToolWindow::IFacePoserToolWindow( char const *toolname, char const *displaynameroot )
{
m_bAutoProcess = false;
m_bUseForMainWindowTitle = false;
SetToolName( toolname );
m_szPrefix[0]=0;
m_szSuffix[0]=0;
SetDisplayNameRoot( displaynameroot );
g_Tools.AddToTail( this );
m_nToolFrameCount = 0;
}
mxWindow *IFacePoserToolWindow::GetMxWindow( void )
{
return dynamic_cast< mxWindow * >( this );
}
IFacePoserToolWindow *IFacePoserToolWindow::GetActiveTool( void )
{
if ( s_pActiveTool )
return s_pActiveTool;
if ( GetToolCount() > 0 )
return GetTool( 0 );
return NULL;
}
void IFacePoserToolWindow::SetActiveTool( IFacePoserToolWindow *tool )
{
if ( tool != s_pActiveTool && s_pActiveTool )
{
InvalidateRect( (HWND)s_pActiveTool->GetMxWindow()->getHandle(), NULL, TRUE );
InvalidateRect( (HWND)tool->GetMxWindow()->getHandle(), NULL, TRUE );
}
s_pActiveTool = tool;
}
void IFacePoserToolWindow::Think( float dt )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetToolName( char const *name )
{
Q_strncpy( m_szToolName, name, sizeof( m_szToolName ) );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
char const *IFacePoserToolWindow::GetToolName( void ) const
{
return m_szToolName;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetDisplayNameRoot( char const *name )
{
Q_snprintf( m_szDisplayRoot, sizeof( m_szDisplayRoot ), "%s", name );
ComputeNewTitle();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
char const *IFacePoserToolWindow::GetDisplayNameRoot( void ) const
{
return m_szDisplayRoot;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *suffix -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetSuffix( char const *suffix )
{
Q_snprintf( m_szSuffix, sizeof( m_szSuffix ), "%s", suffix );
ComputeNewTitle();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *prefix -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetPrefix( char const *prefix )
{
Q_snprintf( m_szPrefix, sizeof( m_szPrefix ), "%s", prefix );
ComputeNewTitle();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
char const *IFacePoserToolWindow::GetWindowTitle( void ) const
{
return m_szWindowTitle;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : use -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetUseForMainWindowTitle( bool use )
{
m_bUseForMainWindowTitle = use;
if ( use )
{
g_MDLViewer->setLabel( m_szWindowTitle );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::ComputeNewTitle( void )
{
Q_snprintf( m_szWindowTitle, sizeof( m_szWindowTitle ), "%s%s%s", m_szPrefix, m_szDisplayRoot, m_szSuffix );
if ( GetMxWindow() )
{
GetMxWindow()->setLabel( m_szWindowTitle );
}
if ( !m_bUseForMainWindowTitle )
return;
g_MDLViewer->setLabel( m_szWindowTitle );
}
IFacePoserToolWindow::~IFacePoserToolWindow( void )
{
g_Tools.FindAndRemove( this );
}
struct ToolTranslate
{
char const *toolname;
float xfrac;
float yfrac;
float wfrac;
float hfrac;
bool locked;
};
static ToolTranslate s_ToolTranslate[]=
{
{ "3D View", 0.0, 0.0, 0.4, 0.5, false },
{ "ControlPanel", 0.4, 0.0, 0.2, 0.25, false },
{ "FlexPanel", 0.6, 0.0, 0.4, 0.25, false },
{ "RampTool", 0.4, 0.25, 0.6, 0.25, false },
{ "CChoreoView", 0.0, 0.5, 1.0, 0.45, false },
// { "Status Window", 0.0, 0.85, 1.0, 0.15, false },
};
static bool TranslateToolPos( char const *toolname, int workspacew, int workspaceh, int& x, int& y, int &w, int &h, bool& locked )
{
int c = ARRAYSIZE( s_ToolTranslate );
for ( int i = 0; i < c; ++i )
{
ToolTranslate& tt = s_ToolTranslate[ i ];
if ( !Q_stricmp( toolname, tt.toolname ) )
{
x = (int)((float)workspacew * tt.xfrac + 0.5f );
y = (int)((float)workspaceh * tt.yfrac + 0.5f );
w = (int)((float)workspacew * tt.wfrac + 0.5f );
h = (int)((float)workspaceh * tt.hfrac + 0.5f );
locked = tt.locked;
return true;
}
}
return false;
}
static int s_nToolCount = 0;
void IFacePoserToolWindow::LoadPosition( void )
{
bool visible;
bool locked;
bool zoomed;
int x, y, w, h;
FacePoser_LoadWindowPositions( GetToolName(), visible, x, y, w, h, locked, zoomed );
if ( w == 0 || h == 0 )
{
int idx = g_Tools.Find( this );
Assert( idx != g_Tools.InvalidIndex() );
if ( idx == 0 )
{
s_nToolCount = 0;
}
zoomed = false;
locked = false;
visible = true;
// Just do a simple tiling
w = g_MDLViewer->w2() * 0.5;
h = g_MDLViewer->h2() * 0.5;
x = g_MDLViewer->w2() * 0.25f + s_nToolCount * 20;
y = s_nToolCount * 20;
bool translated = TranslateToolPos
(
GetToolName(),
g_MDLViewer->w2(),
g_MDLViewer->h2(),
x,
y,
w,
h,
locked
);
if ( !translated )
{
++s_nToolCount;
visible = false;
}
}
GetMxWindow()->setBounds( x, y, w, h );
if ( locked ^ IsLocked() )
{
ToggleLockedState();
}
GetMxWindow()->setVisible( visible );
}
void IFacePoserToolWindow::SavePosition( void )
{
bool visible;
int xpos, ypos, width, height;
visible = GetMxWindow()->isVisible();
xpos = GetMxWindow()->x();
ypos = GetMxWindow()->y();
width = GetMxWindow()->w();
height = GetMxWindow()->h();
// xpos and ypos are screen space
POINT pt;
pt.x = xpos;
pt.y = ypos;
// Convert from screen space to relative to client area of parent window so
// the setBounds == MoveWindow call will offset to the same location
if ( GetMxWindow()->getParent() )
{
ScreenToClient( (HWND)GetMxWindow()->getParent()->getHandle(), &pt );
xpos = (short)pt.x;
ypos = (short)pt.y;
}
FacePoser_SaveWindowPositions( GetToolName(), visible, xpos, ypos, width, height, IsLocked(), false );
}
int IFacePoserToolWindow::GetToolCount( void )
{
return g_Tools.Count();
}
IFacePoserToolWindow *IFacePoserToolWindow::GetTool( int index )
{
return g_Tools[ index ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::InitTools( void )
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
FacePoser_MakeToolWindow( tool->GetMxWindow(), true );
tool->GetMxWindow()->setLabel( tool->GetWindowTitle() );
}
}
void IFacePoserToolWindow::ShutdownTools( void )
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
tool->Shutdown();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : dt -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::ToolThink( float dt )
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
tool->Think( dt );
}
// Don't self animate, all animation driven by thinking of various tools now
if ( !ShouldAutoProcess() )
{
c = models->Count();
for ( i = 0; i < c; i++ )
{
StudioModel *m = models->GetStudioModel( i );
if ( m )
{
m->AdvanceFrame ( dt );
}
}
}
}
bool IFacePoserToolWindow::IsLocked( void )
{
mxWindow *w = GetMxWindow();
if ( !w )
return false;
return !FacePoser_HasWindowStyle( w, WS_SYSMENU );
}
void IFacePoserToolWindow::ToggleLockedState( void )
{
mxWindow *w = GetMxWindow();
if ( !w )
return;
bool visible = w->isVisible();
bool islocked = IsLocked();
if ( islocked )
{
FacePoser_MakeToolWindow( w, true );
}
else
{
FacePoser_RemoveWindowStyle( w, WS_OVERLAPPEDWINDOW );
FacePoser_AddWindowExStyle( w, WS_EX_OVERLAPPEDWINDOW );
}
w->setVisible( false );
// If visible, force it to redraw, etc.
if ( visible )
{
w->setVisible( true );
}
}
#define LOCK_INSET 2
#define LOCK_SIZE 8
void IFacePoserToolWindow:: GetLockRect( RECT& rc )
{
mxWindow *w = GetMxWindow();
Assert( w );
if ( !w )
return;
GetCloseRect( rc );
OffsetRect( &rc, - ( LOCK_SIZE + 2 * LOCK_INSET ), 0 );
}
void IFacePoserToolWindow::GetCloseRect( RECT& rc )
{
mxWindow *w = GetMxWindow();
Assert( w );
if ( !w )
return;
rc.right = w->w2() - LOCK_INSET;
rc.left = rc.right - LOCK_SIZE;
rc.top = LOCK_INSET;
rc.bottom = rc.top + LOCK_SIZE;
}
bool IFacePoserToolWindow::HandleToolEvent( mxEvent *event )
{
bool handled = false;
switch ( event->event )
{
default:
break;
case mxEvent::Close:
{
g_MDLViewer->UpdateWindowMenu();
handled = true;
}
break;
case mxEvent::ParentNotify:
{
mxWindow *w = GetMxWindow();
if ( w )
{
HWND wnd = (HWND)w->getHandle();
SetFocus( wnd );
SetWindowPos( wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
SetActiveTool( this );
}
handled = true;
}
break;
case mxEvent::PosChanged:
{
SetActiveTool( this );
mxWindow *w = GetMxWindow();
if ( w )
{
SetFocus( (HWND)w->getHandle() );
}
handled = true;
}
break;
case mxEvent::MouseDown:
case mxEvent::MouseUp:
{
bool isup = event->event == mxEvent::MouseUp;
mxWindow *w = GetMxWindow();
if ( !isup && w )
{
SetFocus( (HWND)w->getHandle() );
SetWindowPos( (HWND)w->getHandle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
SetActiveTool( this );
}
if ( w && IsLocked() )
{
RECT captionRect;
captionRect.left = 0;
captionRect.right = w->w2();
captionRect.top = 0;
captionRect.bottom = GetCaptionHeight();
POINT pt;
pt.x = (short)event->x;
pt.y = (short)event->y;
if ( PtInRect( &captionRect, pt ) )
{
handled = !isup;
// Right button anywhere
if ( event->buttons & mxEvent::MouseRightButton )
{
if ( isup )
{
ToggleLockedState();
}
}
// Left button on lock icon
RECT lockRect, closeRect;
GetLockRect( lockRect );
GetCloseRect( closeRect );
if ( PtInRect( &lockRect, pt ) )
{
if ( isup )
{
ToggleLockedState();
}
}
if ( PtInRect( &closeRect, pt ) )
{
if ( isup )
{
w->setVisible( !w->isVisible() );
g_MDLViewer->UpdateWindowMenu();
}
}
}
}
}
break;
case mxEvent::NCMouseUp:
{
if ( event->buttons & mxEvent::MouseRightButton )
{
ToggleLockedState();
handled = true;
}
}
break;
case mxEvent::NCMouseDown:
case mxEvent::Focus:
{
SetActiveTool( this );
// don't mark handled = true, do this passively
}
break;
}
return handled;
}
void IFacePoserToolWindow::HandleToolRedraw( CChoreoWidgetDrawHelper& helper )
{
if ( !IsLocked() )
return;
mxWindow *w = GetMxWindow();
if ( !w )
return;
++m_nToolFrameCount;
RECT lockRect, closeRect;
GetLockRect( lockRect );
GetCloseRect( closeRect );
RECT captionRect;
helper.GetClientRect( captionRect );
RECT rcClient = captionRect;
captionRect.bottom = captionRect.top + LOCK_SIZE + 2 * LOCK_INSET;
COLORREF textColor = GetSysColor( COLOR_MENUTEXT ); //GetSysColor( COLOR_INACTIVECAPTIONTEXT );
if ( IsActiveTool() )
{
helper.DrawFilledRect( GetSysColor( COLOR_ACTIVECAPTION ), captionRect );
}
else
{
helper.DrawFilledRect( GetSysColor( COLOR_INACTIVECAPTION ), captionRect );
}
captionRect.top += 1;
InflateRect( &captionRect, -LOCK_INSET, 0 );
helper.DrawColoredText( "Small Fonts", 9, FW_NORMAL, textColor, captionRect,
GetWindowTitle() );
//RECT rcFrame = captionRect;
//rcFrame.left = rcFrame.right - 50;
//rcFrame.right = rcFrame.left + 30;
// helper.DrawColoredText( "Small Fonts", 9, FW_NORMAL, textColor, rcFrame, va( "%i", m_nToolFrameCount ) );
lockRect.bottom++;
OffsetRect( &lockRect, 1, 1 );
helper.DrawColoredTextCharset( "Marlett", 8, FW_NORMAL, SYMBOL_CHARSET, textColor, lockRect, "v" );
closeRect.bottom++;
helper.DrawOutlinedRect( textColor, PS_SOLID, 1, closeRect );
OffsetRect( &closeRect, 1, 1 );
helper.DrawColoredTextCharset( "Marlett", 8, FW_NORMAL, SYMBOL_CHARSET, textColor, closeRect, "r" );
rcClient.top += captionRect.bottom;
helper.StartClipping( rcClient );
}
int IFacePoserToolWindow::GetCaptionHeight( void )
{
if ( !IsLocked() )
return 0;
return LOCK_SIZE + 2 * LOCK_INSET;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : autoprocess -
//-----------------------------------------------------------------------------
void IFacePoserToolWindow::SetAutoProcess( bool autoprocess )
{
m_bAutoProcess = autoprocess;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool IFacePoserToolWindow::GetAutoProcess( void ) const
{
return m_bAutoProcess;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool IFacePoserToolWindow::IsActiveTool( void )
{
if ( this == s_pActiveTool )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool IFacePoserToolWindow::IsAnyToolScrubbing( void )
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
if ( tool->IsScrubbing() )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool IFacePoserToolWindow::IsAnyToolProcessing( void )
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
if ( tool->IsProcessing() )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool IFacePoserToolWindow::ShouldAutoProcess( void )
{
IFacePoserToolWindow *tool = GetActiveTool();
if ( !tool )
return false;
return tool->GetAutoProcess();
}
void IFacePoserToolWindow::EnableToolRedraw( bool enabled )
{
MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
s_bToolsCanDraw = enabled;
if ( s_bToolsCanDraw )
{
int c = s_NeedRedraw.Count();
int i;
for ( i = 0; i < c; i++ )
{
IFacePoserToolWindow *tool = s_NeedRedraw[ i ];
tool->GetMxWindow()->redraw();
}
s_NeedRedraw.Purge();
}
}
bool IFacePoserToolWindow::ToolCanDraw()
{
if ( !s_bToolsCanDraw )
{
if ( s_NeedRedraw.Find( this ) == s_NeedRedraw.InvalidIndex() )
{
s_NeedRedraw.AddToTail( this );
}
return false;
}
return true;
}
void IFacePoserToolWindow::OnModelChanged()
{
}
void IFacePoserToolWindow::ModelChanged()
{
int c = GetToolCount();
int i;
for ( i = 0; i < c ; i++ )
{
IFacePoserToolWindow *tool = GetTool( i );
tool->OnModelChanged();
}
}