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.
472 lines
12 KiB
472 lines
12 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "hlfaceposer.h" |
|
#include <mxtk/mx.h> |
|
#include "expressions.h" |
|
#include "StudioModel.h" |
|
#include "filesystem.h" |
|
#include "viewersettings.h" |
|
#include "matsyswin.h" |
|
#include "checksum_crc.h" |
|
#include "expclass.h" |
|
#include "ControlPanel.h" |
|
#include "faceposer_models.h" |
|
#include "mdlviewer.h" |
|
|
|
static int g_counter = 0; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CExpression::CExpression( void ) |
|
{ |
|
name[ 0 ] = 0; |
|
index = 0; |
|
description[ 0 ] = 0; |
|
memset( setting, 0, sizeof( setting ) ); |
|
|
|
for ( int i = 0; i < MAX_FP_MODELS; i++ ) |
|
{ |
|
m_Bitmap[ i ].valid = false; |
|
} |
|
|
|
m_nUndoCurrent = 0; |
|
m_bModified = false; |
|
|
|
m_bSelected = false; |
|
|
|
m_bDirty = false; |
|
|
|
expressionclass[ 0 ] = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Copy constructor |
|
// Input : from - |
|
//----------------------------------------------------------------------------- |
|
CExpression::CExpression( const CExpression& from ) |
|
{ |
|
int i; |
|
|
|
strcpy( name, from.name ); |
|
index = from.index; |
|
strcpy( description, from.description ); |
|
|
|
for ( i = 0; i < MAX_FP_MODELS; i++ ) |
|
{ |
|
m_Bitmap[ i ] = from.m_Bitmap[ i ]; |
|
} |
|
|
|
m_bModified = from.m_bModified; |
|
|
|
for ( i = 0 ; i < from.undo.Size(); i++ ) |
|
{ |
|
CExpUndoInfo *newUndo = new CExpUndoInfo(); |
|
*newUndo = *from.undo[ i ]; |
|
undo.AddToTail( newUndo ); |
|
} |
|
|
|
m_nUndoCurrent = from.m_nUndoCurrent; |
|
|
|
m_bSelected = from.m_bSelected; |
|
|
|
m_bDirty = from.m_bDirty; |
|
|
|
strcpy( expressionclass, from.expressionclass ); |
|
|
|
memcpy( setting, from.setting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( weight, from.weight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CExpression::~CExpression( void ) |
|
{ |
|
ResetUndo(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CExpression::GetDirty( void ) |
|
{ |
|
return m_bDirty; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : dirty - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::SetDirty( bool dirty ) |
|
{ |
|
m_bDirty = dirty; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : float |
|
//----------------------------------------------------------------------------- |
|
float *CExpression::GetSettings( void ) |
|
{ |
|
return setting; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : float |
|
//----------------------------------------------------------------------------- |
|
float *CExpression::GetWeights( void ) |
|
{ |
|
return weight; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : mod - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::SetModified( bool mod ) |
|
{ |
|
m_bModified = mod; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CExpression::GetModified( void ) |
|
{ |
|
return m_bModified; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : selected - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::SetSelected( bool selected ) |
|
{ |
|
m_bSelected = selected; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CExpression::GetSelected( void ) |
|
{ |
|
return m_bSelected; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CExpression::ResetUndo( void ) |
|
{ |
|
CExpUndoInfo *u; |
|
for ( int i = 0; i < undo.Size(); i++ ) |
|
{ |
|
u = undo[ i ]; |
|
delete u; |
|
} |
|
|
|
undo.RemoveAll(); |
|
m_nUndoCurrent = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CExpression::CanRedo( void ) |
|
{ |
|
if ( !undo.Size() ) |
|
return false; |
|
|
|
if ( m_nUndoCurrent == 0 ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CExpression::CanUndo( void ) |
|
{ |
|
if ( !undo.Size() ) |
|
return false; |
|
|
|
if ( m_nUndoCurrent >= undo.Size() ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CExpression::UndoLevels( void ) |
|
{ |
|
return undo.Size(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : int |
|
//----------------------------------------------------------------------------- |
|
int CExpression::UndoCurrent( void ) |
|
{ |
|
return m_nUndoCurrent; |
|
} |
|
|
|
void ChecksumFlexControllers( bool bSpew, char const *name, CRC32_t &crc, const float *settings, const float *weights ); |
|
|
|
CRC32_t CExpression::GetBitmapCRC() |
|
{ |
|
CRC32_t crc; |
|
|
|
float *s = setting; |
|
float *w = weight; |
|
|
|
// Note, we'll use the pristine values if this has changed |
|
if ( undo.Size() >= 1 ) |
|
{ |
|
s = undo[ undo.Size() - 1 ]->setting; |
|
w = undo[ undo.Size() - 1 ]->weight; |
|
} |
|
|
|
// This walks the global controllers sorted by name and only includes values with a setting or value which is != 0.0f |
|
|
|
ChecksumFlexControllers( false, name, crc, s, w ); |
|
|
|
return crc; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CExpression::GetBitmapCheckSum() |
|
{ |
|
CRC32_t crc = GetBitmapCRC(); |
|
|
|
// Create string name out of binary data |
|
static char hex[ 9 ]; |
|
Q_binarytohex( (byte *)&crc, sizeof( crc ), hex, sizeof( hex ) ); |
|
return hex; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : const char |
|
//----------------------------------------------------------------------------- |
|
const char *CExpression::GetBitmapFilename( int modelindex ) |
|
{ |
|
static char filename[ 256 ] = { 0 }; |
|
|
|
char const *classname = "error"; |
|
CExpClass *cl = GetExpressionClass(); |
|
if ( cl ) |
|
{ |
|
classname = cl->GetBaseName(); |
|
} |
|
|
|
char modelName[512], modelNameTemp[512]; |
|
Q_strncpy( modelNameTemp, models->GetModelName( modelindex ), sizeof( modelNameTemp ) ); |
|
|
|
char const *in = modelNameTemp; |
|
char *out = modelName; |
|
|
|
while ( *in ) |
|
{ |
|
if ( V_isalnum( *in ) || |
|
*in == '_' || |
|
*in == '\\' || |
|
*in == '/' || |
|
*in == '.' || |
|
*in == ':' ) |
|
{ |
|
*out++ = *in; |
|
} |
|
in++; |
|
} |
|
*out = 0; |
|
|
|
|
|
sprintf( filename, "expressions/%s/%s/%s.bmp", modelName, classname, GetBitmapCheckSum() ); |
|
|
|
Q_FixSlashes( filename ); |
|
strlwr( filename ); |
|
|
|
CreatePath( filename ); |
|
|
|
return filename; |
|
} |
|
|
|
void CExpression::CreateNewBitmap( int modelindex ) |
|
{ |
|
MatSysWindow *pWnd = g_pMatSysWindow; |
|
if ( !pWnd ) |
|
return; |
|
|
|
StudioModel *model = models->GetStudioModel( modelindex ); |
|
if ( !model ) |
|
return; |
|
|
|
CStudioHdr *hdr = models->GetStudioHeader( modelindex ); |
|
if ( !hdr ) |
|
return; |
|
|
|
char filename[ 256 ]; |
|
V_strcpy_safe( filename, GetBitmapFilename( modelindex ) ); |
|
if ( !Q_strstr( filename, ".bmp" ) ) |
|
return; |
|
|
|
models->CreateNewBitmap( modelindex, filename, 0, 128, true, this, &m_Bitmap[ modelindex ] ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *exp - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::PushUndoInformation( void ) |
|
{ |
|
SetModified( true ); |
|
|
|
// A real change to the data wipes out the redo counters |
|
WipeRedoInformation(); |
|
|
|
CExpUndoInfo *newundo = new CExpUndoInfo; |
|
|
|
memcpy( newundo->setting, setting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memset( newundo->redosetting, 0, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( newundo->weight, weight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memset( newundo->redoweight, 0, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
|
|
newundo->counter = g_counter++; |
|
|
|
undo.AddToHead( newundo ); |
|
|
|
Assert( m_nUndoCurrent == 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *exp - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::PushRedoInformation( void ) |
|
{ |
|
Assert( undo.Size() >= 1 ); |
|
|
|
CExpUndoInfo *redo = undo[ 0 ]; |
|
memcpy( redo->redosetting, setting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( redo->redoweight, weight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *exp - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::Undo( void ) |
|
{ |
|
if ( !CanUndo() ) |
|
return; |
|
|
|
Assert( m_nUndoCurrent < undo.Size() ); |
|
|
|
CExpUndoInfo *u = undo[ m_nUndoCurrent++ ]; |
|
Assert( u ); |
|
|
|
memcpy( setting, u->setting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( weight, u->weight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *exp - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::Redo( void ) |
|
{ |
|
if ( !CanRedo() ) |
|
return; |
|
|
|
Assert( m_nUndoCurrent >= 1 ); |
|
Assert( m_nUndoCurrent <= undo.Size() ); |
|
|
|
CExpUndoInfo *u = undo[ --m_nUndoCurrent ]; |
|
Assert( u ); |
|
|
|
memcpy( setting, u->redosetting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( weight, u->redoweight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *exp - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::WipeRedoInformation( void ) |
|
{ |
|
// Wipe out all stuff newer then m_nUndoCurrent |
|
int level = 0; |
|
while ( level < m_nUndoCurrent ) |
|
{ |
|
CExpUndoInfo *u = undo[ 0 ]; |
|
undo.Remove( 0 ); |
|
Assert( u ); |
|
delete u; |
|
level++; |
|
} |
|
|
|
m_nUndoCurrent = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Revert to last saved state |
|
//----------------------------------------------------------------------------- |
|
void CExpression::Revert( void ) |
|
{ |
|
SetDirty( false ); |
|
|
|
if ( undo.Size() <= 0 ) |
|
return; |
|
|
|
// Go back to original data |
|
CExpUndoInfo *u = undo[ undo.Size() - 1 ]; |
|
Assert( u ); |
|
|
|
memcpy( setting, u->setting, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
memcpy( weight, u->weight, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ); |
|
|
|
ResetUndo(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Output : CExpClass |
|
//----------------------------------------------------------------------------- |
|
CExpClass *CExpression::GetExpressionClass( void ) |
|
{ |
|
CExpClass *cl = expressions->FindClass( expressionclass, false ); |
|
if ( !cl ) |
|
{ |
|
Assert( cl ); |
|
} |
|
return cl; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *classname - |
|
//----------------------------------------------------------------------------- |
|
void CExpression::SetExpressionClass( char const *classname ) |
|
{ |
|
strcpy( expressionclass, classname ); |
|
} |
|
|
|
|