void ControlPanel::CenterOnFace( void )
{
	if ( !models->GetActiveStudioModel() )
		return;

	StudioModel *mdl = models->GetActiveStudioModel();
	if ( !mdl )
		return;

	CStudioHdr *hdr = mdl->GetStudioHdr();
	if ( !hdr )
		return;

	setSpeed( 1.0f );

	int oldSeq = models->GetActiveStudioModel()->GetSequence();

	int seq = models->GetActiveStudioModel()->LookupSequence( "idle_suble" );
	if ( seq == -1 )
		seq = 0;

	if ( seq != oldSeq )
	{
		Con_Printf( "Centering changed model sequence # to %d\n", seq );
	}

	setSequence( seq );
	initPoseParameters( );

	mdl->m_angles.Init();
	mdl->m_origin.Init();

	Vector size;
	VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );

	float eyeheight = hdr->hull_min().z + 0.9 * size.z;

	if ( hdr->GetNumAttachments() > 0 )
	{
		for (int i = 0; i < hdr->GetNumAttachments(); i++)
		{
			const mstudioattachment_t &attachment = hdr->pAttachment( i );
			int iBone = hdr->GetAttachmentBone( i );

			if ( Q_stricmp( attachment.pszName(), "eyes" ) )
				continue;

			mstudiobone_t *bone = hdr->pBone( iBone );
			if ( !bone )
				continue;

			matrix3x4_t boneToPose;
			MatrixInvert( bone->poseToBone, boneToPose );

			matrix3x4_t attachmentPoseToLocal;
			ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );

			Vector localSpaceEyePosition;
			VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );

			// Not sure why this must be negative?
			eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
			break;
		}
	}

	KeyValues *seqKeyValues = new KeyValues("");
	if ( seqKeyValues->LoadFromBuffer( mdl->GetFileName( ), mdl->GetKeyValueText( seq ) ) )
	{
		// Do we have a build point section?
		KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
		if ( pkvAllFaceposer )
		{
			float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
			if ( flEyeheight != -9999.0f )
			{
				eyeheight = flEyeheight;
			}
		}
	}

	seqKeyValues->deleteThis();

	mdl->m_origin.x = size.z * .65f;
	mdl->m_origin.z += eyeheight;

	CUtlVector< StudioModel * > modellist;

	modellist.AddToTail( models->GetActiveStudioModel() );

	int i;
	if ( models->CountVisibleModels() > 0 )
	{
		modellist.RemoveAll();
		for ( i = 0; i < models->Count(); i++ )
		{
			if ( models->IsModelShownIn3DView( i ) )
			{
				modellist.AddToTail( models->GetStudioModel( i ) );
			}
		}
	}

	int modelcount = modellist.Count();
	int countover2 = modelcount / 2;
	int ydelta = GetModelGap();
	int yoffset = -countover2 * ydelta;
	for ( i = 0 ; i < modelcount; i++ )
	{
		if ( models->GetStudioHeader( i ) == hdr )
		{
			mdl->m_origin.y = -yoffset;
		}
		yoffset += ydelta;
	}

	g_pMatSysWindow->redraw();
}
void IFaceposerModels::CFacePoserModel::CreateNewBitmap( char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap )
{
	MatSysWindow *pWnd = g_pMatSysWindow;
	if ( !pWnd ) 
		return;

	StudioModel *model = m_pModel;
	if ( !model )
		return;

	CStudioHdr *hdr = model->GetStudioHdr();
	if ( !hdr )
		return;
	if ( sequence < 0 || sequence >= hdr->GetNumSeq() )
		return;

	mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence );

	Con_ColorPrintf( FILE_COLOR, "Creating bitmap %s for sequence '%s'\n", pchBitmapFilename, seqdesc.pszLabel() );

	model->ClearOverlaysSequences();
	int iLayer = model->GetNewAnimationLayer();
	model->SetOverlaySequence( iLayer, sequence, 1.0 );
	model->SetOverlayRate( iLayer, FindPoseCycle( model, sequence ), 0.0 );

	for (int i = 0; i < hdr->GetNumPoseParameters(); i++)
	{
		model->SetPoseParameter( i, 0.0 );
	}

	float flexValues[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ] = { 0 };

	if ( pExpression )
	{
		float *settings = pExpression->GetSettings();
		float *weights = pExpression->GetWeights();

		// Save existing settings from model
		for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
		{
			int j = hdr->pFlexcontroller( i )->localToGlobal;
			if ( j == -1 )
				continue;
			flexValues[ i ] = model->GetFlexController( i );
			// Set Value from passed in settings
			model->SetFlexController( i, settings[ j ] * weights[ j ] );
		}
	}

	model->ClearLookTargets( );

	QAngle oldrot, oldLight;
	Vector oldtrans;
	
	VectorCopy( model->m_angles, oldrot );
	VectorCopy( model->m_origin, oldtrans );
	VectorCopy( g_viewerSettings.lightrot, oldLight );

	model->m_angles.Init();
	model->m_origin.Init();
	g_viewerSettings.lightrot.Init();

	g_viewerSettings.lightrot.y = -180;

	bool bSaveGround = g_viewerSettings.showGround;
	g_viewerSettings.showGround = false;

	if ( bZoomInOnFace )
	{
		Vector size;
		VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );

		float eyeheight = hdr->hull_min().z + 0.9 * size.z;
		//	float width = ( size.x + size.y ) / 2.0f;

		model->m_origin.x = size.z * .6f;

		if ( hdr->GetNumAttachments() > 0 )
		{
			for (int i = 0; i < hdr->GetNumAttachments(); i++)
			{
				const mstudioattachment_t &attachment = hdr->pAttachment( i );
				int iBone = hdr->GetAttachmentBone( i );

				if ( Q_stricmp( attachment.pszName(), "eyes" ) )
					continue;

				mstudiobone_t *bone = hdr->pBone( iBone );
				if ( !bone )
					continue;

				matrix3x4_t boneToPose;
				MatrixInvert( bone->poseToBone, boneToPose );

				matrix3x4_t attachmentPoseToLocal;
				ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );

				Vector localSpaceEyePosition;
				VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );

				// Not sure why this must be negative?
				eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
				break;
			}
		}

		KeyValues *seqKeyValues = new KeyValues("");
		if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
		{
			// Do we have a build point section?
			KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
			if ( pkvAllFaceposer )
			{
				float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
				if ( flEyeheight != -9999.0f )
				{
					eyeheight = flEyeheight;
				}
			}
		}

		model->m_origin.z += eyeheight;
	}
	else
	{
		Vector mins, maxs;
		model->ExtractBbox(mins, maxs);
		Vector size;
		VectorSubtract( maxs, mins, size );

		float maxdim = size.x;
		if ( size.y > maxdim )
			maxdim = size.y;
		if ( size.z > maxdim )
			maxdim = size.z;

		float midpoint = mins.z + 0.5 * size.z;

		model->m_origin.x = 3 * maxdim;
		model->m_origin.z += midpoint;
	}

	pWnd->SuppressResize( true );

	RECT rcClient;
	HWND wnd = (HWND)pWnd->getHandle();

	WINDOWPLACEMENT wp;

	GetWindowPlacement( wnd, &wp );

	GetClientRect( wnd, &rcClient );

	MoveWindow( wnd, 0, 0, nSnapShotSize + 16, nSnapShotSize + 16, TRUE );

	// Snapshots are taken of the back buffer; 
	// we need to render to the back buffer but not move it to the front
	pWnd->SuppressBufferSwap( true );
	pWnd->redraw();
	pWnd->SuppressBufferSwap( false );

	// make it square, assumes w > h
	char fullpath[ 512 ];
	Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename );
	pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize );

	// Move back to original position
	SetWindowPlacement( wnd, &wp );

	pWnd->SuppressResize( false );

	VectorCopy( oldrot, model->m_angles );
	VectorCopy( oldtrans, model->m_origin );
	VectorCopy( oldLight, g_viewerSettings.lightrot );

	g_viewerSettings.showGround = bSaveGround;

	if ( pExpression )
	{
		// Save existing settings from model
		for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
		{
			int j = hdr->pFlexcontroller( i )->localToGlobal;
			if ( j == -1 )
				continue;

			model->SetFlexController( i, flexValues[ i ] );
		}
	}

	model->ClearOverlaysSequences();
	
	if ( bitmap->valid )
	{
		DeleteObject( bitmap->image );
		bitmap->image = 0;
		bitmap->valid = false;
	}

	LoadBitmapFromFile( pchBitmapFilename, *bitmap );
}