This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

View File

@@ -0,0 +1,723 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#if defined(WIN32) && !defined( _X360 )
#include <windows.h>
#endif
#include "filesystem.h"
#include "filesystem_init.h"
#include "appframework/IAppSystemGroup.h"
#include "appframework/IAppSystem.h"
#include "appframework/AppFramework.h"
#include "filesystem_helpers.h"
#include "matsys_controls/QCGenerator.h"
#include "tier1/KeyValues.h"
#include "tier2/vconfig.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/FileOpenDialog.h"
#include "vgui_controls/DirectorySelectDialog.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/MessageBox.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/Cursor.h"
#include "vgui_controls/KeyBoardEditorDialog.h"
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
using namespace vgui;
#define MAX_KEYVALUE 1024
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to the 'count' occurence of a character from the end of a string
// returns 0 of there aren't 'count' number of the character in the string
//-----------------------------------------------------------------------------
char *strrchrcount(char *string, int character, int count )
{
int j = count;
int numChars = strlen( string );
for( int i = numChars; i > 0; i-- )
{
if( string[i-1] == character )
{
j--;
}
if( j == 0 )
{
return string + i-1;
}
}
return 0;
}
class CModalPreserveMessageBox : public vgui::MessageBox
{
public:
CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
: vgui::MessageBox( title, text, parent )
{
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
}
~CModalPreserveMessageBox()
{
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
}
public:
vgui::VPANEL m_PrevAppFocusPanel;
};
void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
{
char msg[4096];
va_list marker;
va_start( marker, pMsg );
Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
va_end( marker );
vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
dlg->DoModal();
dlg->Activate();
dlg->RequestFocus();
}
//-----------------------------------------------------------------------------
// Purpose: Places all the info from the vgui controls into the QCInfo struct
//-----------------------------------------------------------------------------
void QCInfo::SyncFromControls()
{
char tempText[MAX_PATH];
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
bStaticProp = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
bMostlyOpaque = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
bDisableCollision = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
bReferenceAsPhys = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
bConcave = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
bAutomass = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "massField" );
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
fMass = atof(tempText);
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
fScale = atof(tempText);
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszCollisionPath, tempText );
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszSurfaceProperty, tempText );
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszMaterialPath, tempText );
LODs.RemoveAll();
pTargetField = pQCGenerator->FindChildByName( "LODList" );
int numLOD = ((ListPanel *)pTargetField)->GetItemCount();
for ( int i = 0; i < numLOD; i++ )
{
KeyValues *key = ((ListPanel *)pTargetField)->GetItem( i );
LODInfo newLOD;
V_strcpy_safe( newLOD.pszFilename, key->GetString( "SMD" ) );
newLOD.iLOD = key->GetInt( "LOD" );
LODs.AddToTail( newLOD );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called during intialization to setup the initial state of the VGUI controls
//-----------------------------------------------------------------------------
void QCInfo::SyncToControls()
{
char tempText[MAX_PATH];
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
((CheckButton *)pTargetField)->SetSelected( bStaticProp );
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
((CheckButton *)pTargetField)->SetSelected( bMostlyOpaque );
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
((CheckButton *)pTargetField)->SetSelected( bDisableCollision );
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
((CheckButton *)pTargetField)->SetSelected( bReferenceAsPhys );
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
((CheckButton *)pTargetField)->SetSelected( bConcave );
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
((CheckButton *)pTargetField)->SetSelected( bAutomass );
Q_snprintf( tempText, 10, "%d", (int)fMass );
pTargetField = pQCGenerator->FindChildByName( "massField" );
((TextEntry *)pTargetField)->SetText( tempText );
Q_snprintf( tempText, 10, "%d", (int)fScale );
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
((TextEntry *)pTargetField)->SetText( tempText );
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
((TextEntry *)pTargetField)->SetText( pszCollisionPath );
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
((TextEntry *)pTargetField)->SetText( pszMaterialPath );
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
int numItems = ((ComboBox *)pTargetField)->GetItemCount();
for( int i = 0; i < numItems; i++ )
{
((ComboBox *)pTargetField)->GetItemText( i, tempText, MAX_PATH );
if ( !Q_strcmp( tempText, pszSurfaceProperty ) )
{
((ComboBox *)pTargetField)->SetItemEnabled( i, true );
((ComboBox *)pTargetField)->SetText( tempText );
break;
}
}
}
CBrowseButton::CBrowseButton( vgui::Panel *pParent ) : BaseClass( pParent, "Browse Button", "...", pParent, "browse" )
{
SetParent( pParent );
pszStartingDirectory = NULL;
pszFileFilter = NULL;
pszTargetField = NULL;
}
CBrowseButton::~CBrowseButton()
{
}
void CBrowseButton::SetCharVar( char **pVar, const char *pszNewText )
{
if ( *pVar && pszNewText && !Q_strcmp( *pVar, pszNewText ) )
{
return;
}
if ( *pVar )
{
delete [] *pVar;
*pVar = NULL;
}
if ( pszNewText )
{
int len = Q_strlen( pszNewText ) + 1;
*pVar = new char[ len ];
Q_strncpy( *pVar, pszNewText, len );
}
}
void CBrowseButton::InitBrowseInfo( int x, int y, const char *pszName, const char *pszDir, const char *pszFilter, const char *pszField )
{
SetSize( 24, 24 );
SetPos( x, y );
SetName( pszName );
SetCharVar( GetStartingDirectory(), pszDir );
SetCharVar( GetFileFilter(), pszFilter );
SetCharVar( GetTargetField(), pszField );
SetActionMessage();
}
void CBrowseButton::SetActionMessage()
{
KeyValues *newActionMessage = new KeyValues( "browse", "directory", pszStartingDirectory, "filter", pszFileFilter);
newActionMessage->SetString( "targetField", pszTargetField );
SetCommand( newActionMessage );
}
const char *ParseKeyvalue( const char *pBuffer, char *key, char *value )
{
char com_token[1024];
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
{
Q_strncpy( key, com_token, MAX_KEYVALUE );
Q_strlower( key );
}
// no value on a close brace
if ( !Q_strcmp( key, "}" ) )
{
value[0] = 0;
return pBuffer;
}
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
{
Q_strncpy( value, com_token, MAX_KEYVALUE );
Q_strlower( value );
}
return pBuffer;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CQCGenerator::CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ) : BaseClass( pParent, "QCGenerator" )
{
m_QCInfo_t.Init( this );
SetMinimumSize(846, 770);
m_pLODPanel = new ListPanel(this, "LODList");
m_pLODPanel->SetSelectIndividualCells( true );
m_pLODPanel->AddColumnHeader(0, "SMD", "LOD SMD", 450, 0);
m_pLODPanel->AddColumnHeader(1, "LOD", "LOD Distance", 50, 0);
m_pLODPanel->AddActionSignalTarget( this );
m_pLODPanel->SetMouseInputEnabled( true );
LoadControlSettings( "QCGenerator.res" );
m_pCollisionBrowseButton = new CBrowseButton( this );
m_pCollisionBrowseButton->InitBrowseInfo( 808, 158, "collisionBrowseButton", pszPath, "*.smd", "collisionSMDField" );
char szTerminatedPath[1024] = "\0";
sprintf( szTerminatedPath, "%s\\", pszPath );
InitializeSMDPaths( szTerminatedPath, pszScene );
char *pszMaterialsStart = strrchrcount( szTerminatedPath, '\\', 3 ) + 1;
char *pszMaterialsEnd = strrchr( szTerminatedPath, '\\');
Q_strncpy( m_QCInfo_t.pszMaterialPath, pszMaterialsStart, pszMaterialsEnd - pszMaterialsStart + 1 );
SetParent( pParent );
char szGamePath[1024] = "\0";
char szSearchPath[1024] = "\0";
// Get the currently set game configuration
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
static const char *pSurfacePropFilename = "\\scripts\\surfaceproperties.txt";
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
FileHandle_t fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
if ( !fp )
{
//the set game configuration didn't have a surfaceproperties file; we are grabbing it from hl2
//TODO: This only works if they are in a subdirectory that is a peer to an hl2 directory
// that contains the file. It potentially needs to search the entire drive or prompt for the location
char *pszEndGamePath = Q_strrchr( szGamePath, '\\' );
pszEndGamePath[0] = 0;
V_strcat_safe( szGamePath, "\\hl2" );
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
}
int len = g_pFullFileSystem->Size( fp );
const char *szSurfacePropContents = new char[len+1];
g_pFullFileSystem->Read( (void *)szSurfacePropContents, len, fp );
char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
vgui::Panel *pSurfacePropDropDown = FindChildByName( "surfacePropertyDropDown" );
//filling up the surface property dropdown
while ( szSurfacePropContents )
{
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
((ComboBox *)pSurfacePropDropDown)->AddItem( key, NULL );
while ( szSurfacePropContents )
{
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
if (!stricmp( key, "}" ) )
{
break;
}
}
}
m_QCInfo_t.SyncToControls();
m_pLODEdit = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CQCGenerator::~CQCGenerator()
{
}
void CQCGenerator::OnCommand( const char *command )
{
if ( Q_stricmp( command, "createQC" ) == 0 )
{
m_QCInfo_t.SyncFromControls();
GenerateQCFile();
}
if ( Q_stricmp( command, "deleteSeq" ) == 0 )
{
//delete it
DeleteLOD();
}
if ( Q_stricmp( command, "editSeq" ) == 0 )
{
//edit
EditLOD();
}
BaseClass::OnCommand( command );
}
void CQCGenerator::OnKeyCodeTyped( KeyCode code )
{
switch ( code )
{
case KEY_ENTER:
EditLOD();
}
}
void CQCGenerator::OnBrowse( KeyValues *data )
{
V_strcpy_safe( m_szTargetField, data->GetString( "targetField" ) );
const char *filter = data->GetString( "filter" );
if ( Q_strlen( filter ) == 0 )
{
// BrowseDirectory( data );
}
else
{
BrowseFile( data );
}
}
/*
//This function is no longer used in the current version of the program.
void CQCGenerator::BrowseDirectory( KeyValues *data )
{
DirectorySelectDialog *pDialog = new DirectorySelectDialog( this, "Select Directory" );
pDialog->AddActionSignalTarget( this );
pDialog->DoModal();
pDialog->SetStartDirectory( data->GetString( "directory" ) );
}
*/
void CQCGenerator::BrowseFile( KeyValues *data )
{
const char *filter = data->GetString( "filter" );
FileOpenDialog *pDialog = new FileOpenDialog( this, "Select File", true );
pDialog->AddFilter( filter, filter, true );
pDialog->AddActionSignalTarget(this);
pDialog->SetStartDirectory( data->GetString( "directory" ) );
pDialog->DoModal( true );
}
void CQCGenerator::OnFileSelected( KeyValues *data )
{
if ( m_szTargetField )
{
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
((TextEntry *)pTargetField)->SetText( data->GetString( "fullpath" ) );
Repaint();
}
}
void CQCGenerator::OnDirectorySelected( KeyValues *data )
{
if ( m_szTargetField )
{
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
((TextEntry *)pTargetField)->SetText( data->GetString( "dir" ) );
Repaint();
}
}
bool CQCGenerator::GenerateQCFile()
{
//TODO: clean this up. Consider creating a datatype that includes the string to write out when the QC file is created
char *nameBegin = strrchr( m_QCInfo_t.pszSMDPath, '\\' );
char szPath[MAX_PATH];
char szName[MAX_PATH];
Q_strncpy( szPath, m_QCInfo_t.pszSMDPath, nameBegin - m_QCInfo_t.pszSMDPath + 2 );
V_strcpy_safe( szName, szPath);
V_strcat_safe( szName, m_QCInfo_t.pszSceneName);
V_strcat_safe( szName, ".qc" );
FileHandle_t pSaveFile = g_pFullFileSystem->Open( szName, "wt" );
if (!pSaveFile)
{
char szSaveError[1024] = "";
Q_snprintf( szSaveError, 1024, "Save failed: invalid file name '%s'\n\nDirectory '%s' must exist.", szName, szPath );
VGUIMessageBox( this, "QC Generator error", szSaveError );
return 0;
}
//write qc header
g_pFullFileSystem->FPrintf( pSaveFile, "//\n// .qc file version 1.0\n\n");
//write out modelname info
char szModelName[MAX_PATH];
char *modelStart = strrchrcount( szName, '\\', 2) + 1;
char *modelEnd = strrchr( szName, '.' );
Q_strncpy( szModelName, modelStart, modelEnd - modelStart + 1 );
V_strcat_safe( szModelName, ".mdl" );
g_pFullFileSystem->FPrintf( pSaveFile, "$modelname %s\n\n", szModelName );
//write out scale info
g_pFullFileSystem->FPrintf( pSaveFile, "$scale %f\n", m_QCInfo_t.fScale );
//write out body info
g_pFullFileSystem->FPrintf( pSaveFile, "$body \"Body\" \"%s\"\n", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
if ( m_QCInfo_t.bStaticProp == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$staticprop\n" );
}
if ( m_QCInfo_t.bMostlyOpaque == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$mostlyopaque\n" );
}
//write out surfaceprop info
g_pFullFileSystem->FPrintf( pSaveFile, "$surfaceprop \"%s\"\n\n", m_QCInfo_t.pszSurfaceProperty );
//write materials
g_pFullFileSystem->FPrintf( pSaveFile, "$cdmaterials %s\n\n", m_QCInfo_t.pszMaterialPath);
if ( m_QCInfo_t.bStaticProp || m_QCInfo_t.bNoAnimation )
{
g_pFullFileSystem->FPrintf( pSaveFile, "// --------- Animation sequences -------\n");
g_pFullFileSystem->FPrintf( pSaveFile, "$sequence \"idle\" \"%s\" fps 30\n\n", strrchr(m_QCInfo_t.pszSMDPath, '\\')+1);
}
//write out lod info
for( int i = 0; i < m_QCInfo_t.LODs.Count(); i++ )
{
LODInfo thisLOD = m_QCInfo_t.LODs.Element( i );
g_pFullFileSystem->FPrintf( pSaveFile, "$lod %d\n{\n\treplacemodel \"%s\" \"%s\"\n}\n\n", thisLOD.iLOD, strrchr(m_QCInfo_t.pszSMDPath, '\\')+1, thisLOD.pszFilename );
}
if ( m_QCInfo_t.bDisableCollision != true )
{
//write out collision header
g_pFullFileSystem->FPrintf( pSaveFile, "\n" );
//write out collision info
if ( m_QCInfo_t.bReferenceAsPhys == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
}
else
{
if( Q_strcmp( m_QCInfo_t.pszCollisionPath, "" ) )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszCollisionPath, '\\' ) + 1 );
}
}
g_pFullFileSystem->FPrintf( pSaveFile, " {\n\t// Mass in kilograms\n ");
if ( m_QCInfo_t.bAutomass == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$automass\n" );
}
else
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$mass %f\n", m_QCInfo_t.fMass );
}
if ( m_QCInfo_t.bConcave == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$concave\n" );
}
g_pFullFileSystem->FPrintf( pSaveFile, "}\n\n");
}
g_pFullFileSystem->Close( pSaveFile );
char szCommand[MAX_PATH];
char szGamePath[MAX_PATH];
char studiomdlPath[512];
g_pFullFileSystem->RelativePathToFullPath( "studiomdl.bat", NULL, studiomdlPath, sizeof( studiomdlPath ));
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
#ifdef WIN32
STARTUPINFO startup;
PROCESS_INFORMATION process;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
sprintf( szCommand, "%s -game %s %s", studiomdlPath, szGamePath, szName);
bool bReturn = CreateProcess( NULL, szCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startup, &process);
#else
Assert( !"Implement me, why aren't we using a thread tool abstraction?" );
bool bReturn = false;
#endif
return bReturn;
}
void CQCGenerator::InitializeSMDPaths( const char *pszPath, const char *pszScene )
{
V_strcpy_safe( m_QCInfo_t.pszSceneName, pszScene );
FileFindHandle_t *pFileHandle = new FileFindHandle_t();
g_pFullFileSystem->AddSearchPath( pszPath, "SMD_DIR" );
const char *filename = g_pFullFileSystem->FindFirst( "*.smd", pFileHandle );
bool bFoundReference = false;
bool bFoundCollision = false;
bool bFoundLOD = false;
//iterate through .smd files
const char *startName = pszScene;
int nSearchLength = Q_strlen( pszScene );
int currentLOD = 1;
while( filename )
{
if ( !strncmp( startName, filename, nSearchLength ) )
{
const char *filenameEnd = filename + nSearchLength;
if ( !strncmp( filenameEnd, "_ref", 4 ) || !strncmp( filenameEnd, ".smd", 4 ) )
{
bFoundReference = true;
//we have found the reference smd.
V_strcpy_safe( m_QCInfo_t.pszSMDPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszSMDPath, filename );
}
if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
{
bFoundCollision = true;
//we have found the collision smd.
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszCollisionPath, filename );
}
if ( !strncmp( filenameEnd, "_lod", 4) )
{
bFoundLOD = true;
//we found an LOD smd.
char lodName[255];
Q_snprintf( lodName, Q_strlen( lodName ), "lod%d", currentLOD );
//we found an LOD
KeyValues *newKv = new KeyValues( lodName, "SMD", filename, "LOD", "10" );
m_pLODPanel->AddItem( newKv, currentLOD, false, false );
currentLOD++;
}
}
filename = g_pFullFileSystem->FindNext( *pFileHandle );
}
char pszMessage[2048] = "";
char pszRefMessage[1024] = "";
char pszColMessage[1024] = "";
if (!bFoundReference )
{
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszScene );
V_strcat_safe( m_QCInfo_t.pszSMDPath, ".smd" );
Q_snprintf( pszRefMessage, 1024, "Reference SMD not found.\n\nValid default reference SMDs are %s%s_ref*.smd and %s%s.smd\nUsing default of %s. Model will not compile.\n\n", pszPath, pszScene, pszPath, pszScene, m_QCInfo_t.pszSMDPath );
}
if ( !bFoundCollision )
{
Q_snprintf( pszColMessage, 1024, "Collision SMD not found.\n\nThe valid default collision SMD is %s%s_phy*.smd.\nUsing reference SMD as default.\n", pszPath, pszScene );
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
m_QCInfo_t.bReferenceAsPhys = true;
}
if ( !bFoundReference || !bFoundCollision)
{
V_strcpy_safe( pszMessage, pszRefMessage );
V_strcat_safe( pszMessage, pszColMessage );
VGUIMessageBox( this, "Error Initializing Paths", pszMessage );
}
}
void CQCGenerator::DeleteLOD()
{
int numSelected = m_pLODPanel->GetSelectedItemsCount();
int selected;
for ( int i = numSelected-1; i >= 0; i-- )
{
selected = m_pLODPanel->GetSelectedItem( i );
m_pLODPanel->RemoveItem( selected );
}
}
void CQCGenerator::EditLOD()
{
int numSelected = m_pLODPanel->GetSelectedItemsCount();
if ( numSelected == 1 && !m_pLODPanel->IsInEditMode() )
{
if ( m_pLODEdit )
{
m_pLODEdit->MarkForDeletion();
m_pLODEdit = NULL;
}
m_pLODEdit = new vgui::TextEntry( this, "Edit" );
m_pLODEdit->SendNewLine( true );
m_nSelectedSequence = m_pLODPanel->GetSelectedItem( 0 );
m_nSelectedColumn = m_pLODPanel->GetSelectedColumn();
m_pLODPanel->EnterEditMode( m_nSelectedSequence, m_nSelectedColumn, m_pLODEdit );
}
}
void CQCGenerator::OnNewLODText()
{
KeyValues *pEditItem = m_pLODPanel->GetItem( m_nSelectedSequence );
KeyValues *pListItem = pEditItem;
wchar_t szEditText[MAX_PATH];
pEditItem = pEditItem->GetFirstValue();
const char *name = pEditItem->GetName();
for( int i = 0; i < m_nSelectedColumn; i++ )
{
pEditItem = pEditItem->GetNextValue();
name = pEditItem->GetName();
}
m_pLODEdit->GetText( szEditText, MAX_PATH );
pListItem->SetWString( name, szEditText );
m_pLODPanel->LeaveEditMode();
m_pLODPanel->InvalidateLayout();
return;
}

View File

@@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "matsys_controls/assetpicker.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Asset Picker with no preview
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CAssetPicker::CAssetPicker( vgui::Panel *pParent, const char *pAssetType,
const char *pExt, const char *pSubDir, const char *pTextType ) :
BaseClass( pParent, pAssetType, pExt, pSubDir, pTextType )
{
CreateStandardControls( this );
LoadControlSettingsAndUserConfig( "resource/assetpicker.res" );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CAssetPickerFrame::CAssetPickerFrame( vgui::Panel *pParent, const char *pTitle,
const char *pAssetType, const char *pExt, const char *pSubDir, const char *pTextType ) :
BaseClass( pParent )
{
SetAssetPicker( new CAssetPicker( this, pAssetType, pExt, pSubDir, pTextType ) );
LoadControlSettingsAndUserConfig( "resource/assetpickerframe.res" );
SetTitle( pTitle, false );
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/curveeditorpanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "tier1/KeyValues.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/MouseCode.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CCurveEditorPanel::CCurveEditorPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
m_nSelectedPoint = -1;
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( true );
m_nHighlightedPoint = -1;
}
CCurveEditorPanel::~CCurveEditorPanel()
{
}
//-----------------------------------------------------------------------------
// Converts screen location to normalized values
//-----------------------------------------------------------------------------
void CCurveEditorPanel::ScreenToValue( int x, int y, float *pIn, float *pOut )
{
int w, h;
GetSize( w, h );
*pIn = (float)x / (w-1);
*pOut = 1.0f - ((float)y / (h-1));
}
void CCurveEditorPanel::ValueToScreen( float flIn, float flOut, int *x, int *y )
{
int w, h;
GetSize( w, h );
*x = (int)(flIn * (w-1) + 0.5f);
*y = (h-1) - (int)(flOut * (h-1) + 0.5f);
}
//-----------------------------------------------------------------------------
// Handle input
//-----------------------------------------------------------------------------
void CCurveEditorPanel::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
int x, y;
input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
if ( code == MOUSE_LEFT )
{
int w, h;
GetSize( w, h );
float flIn, flOut;
ScreenToValue( x, y, &flIn, &flOut );
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
m_nSelectedPoint = FindOrAddControlPoint( flIn, flTolerance, flOut );
}
}
void CCurveEditorPanel::OnMouseReleased( vgui::MouseCode code )
{
BaseClass::OnMouseReleased( code );
if ( code == MOUSE_LEFT )
{
m_nSelectedPoint = -1;
}
}
void CCurveEditorPanel::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
float flIn, flOut;
ScreenToValue( x, y, &flIn, &flOut );
int w, h;
GetSize( w, h );
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
m_nHighlightedPoint = FindControlPoint( flIn, flTolerance );
if ( m_nSelectedPoint < 0 )
return;
m_nSelectedPoint = ModifyControlPoint( m_nSelectedPoint, flIn, flOut );
}
//-----------------------------------------------------------------------------
// Handles keypresses
//-----------------------------------------------------------------------------
void CCurveEditorPanel::OnKeyCodePressed( vgui::KeyCode code )
{
BaseClass::OnKeyCodePressed( code );
if ( m_nSelectedPoint >= 0 )
{
RemoveControlPoint( m_nSelectedPoint );
m_nSelectedPoint = -1;
}
}
//-----------------------------------------------------------------------------
// This paints the grid behind the curves
//-----------------------------------------------------------------------------
void CCurveEditorPanel::PaintBackground( void )
{
int w, h;
GetSize( w, h );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
vgui::surface()->DrawFilledRect( 0, 0, w, h );
vgui::surface()->DrawSetColor( 128, 128, 128, 255 );
vgui::surface()->DrawLine( 0, h/4, w, h/4 );
vgui::surface()->DrawLine( 0, h/2, w, h/2 );
vgui::surface()->DrawLine( 0, 3*h/4, w, 3*h/4 );
vgui::surface()->DrawLine( w/4, 0, w/4, h );
vgui::surface()->DrawLine( w/2, 0, w/2, h );
vgui::surface()->DrawLine( 3*w/4, 0, 3*w/4, h );
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawLine( 0, 0, w, 0 );
vgui::surface()->DrawLine( w, 0, w, h );
vgui::surface()->DrawLine( w, h, 0, h );
vgui::surface()->DrawLine( 0, h, 0, 0 );
}
//-----------------------------------------------------------------------------
// Sets the color curves operation to edit
//-----------------------------------------------------------------------------
void CCurveEditorPanel::Paint( void )
{
int w, h;
GetSize( w, h );
int x0 = 0, y0 = 0;
// FIXME: Add method to draw multiple lines DrawPolyLine connects the 1st and last points... bleah
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
for ( int i = 0; i < w; ++i )
{
float flIn = (float)i / (w-1);
float flOut = GetValue( flIn );
int x = i;
int y = (h-1) - (int)(flOut * (h-1) + 0.5f);
y = clamp( y, 0, h-1 );
if ( i != 0 )
{
vgui::surface()->DrawLine( x0, y0, x, y );
}
x0 = x; y0 = y;
}
// This will paint the control points
// The currently selected one will be painted red and filled.
for ( int i = ControlPointCount(); --i >= 0; )
{
float flIn, flOut;
GetControlPoint( i, &flIn, &flOut );
int cx, cy;
ValueToScreen( flIn, flOut, &cx, &cy );
if ( (i == m_nSelectedPoint) || ((m_nSelectedPoint == -1) && (i == m_nHighlightedPoint)) )
{
vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
vgui::surface()->DrawFilledRect( cx-3, cy-3, cx+3, cy+3 );
}
else
{
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawOutlinedRect( cx-3, cy-3, cx+3, cy+3 );
}
}
}

View File

@@ -0,0 +1,301 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#if defined(WIN32) && !defined( _X360 )
#include <windows.h>
#endif
#undef PropertySheet
#include "matsys_controls/gamefiletreeview.h"
#include "filesystem.h"
#include "tier1/KeyValues.h"
#include "vgui/ISurface.h"
#include "vgui/Cursor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// list of all tree view icons
//-----------------------------------------------------------------------------
enum
{
IMAGE_FOLDER = 1,
IMAGE_OPENFOLDER,
IMAGE_FILE,
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameFileTreeView::CGameFileTreeView( Panel *parent, const char *name, const char *pRootFolderName, const char *pRootDir, const char *pExtension ) : BaseClass(parent, name), m_Images( false )
{
m_RootDir = pRootDir;
m_Ext = pExtension;
m_bUseExt = ( pExtension != NULL );
m_RootFolderName = pRootFolderName;
// build our list of images
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) );
SetImageList( &m_Images, false );
}
//-----------------------------------------------------------------------------
// Purpose: Refreshes the active file list
//-----------------------------------------------------------------------------
void CGameFileTreeView::RefreshFileList()
{
RemoveAll();
SetFgColor(Color(216, 222, 211, 255));
// add the base node
KeyValues *pkv = new KeyValues( "root" );
pkv->SetString( "text", m_RootFolderName );
pkv->SetInt( "root", 1 );
pkv->SetInt( "expand", 1 );
int iRoot = AddItem( pkv, GetRootItemIndex() );
pkv->deleteThis();
ExpandItem( iRoot, true );
}
//-----------------------------------------------------------------------------
// Selects the root folder
//-----------------------------------------------------------------------------
void CGameFileTreeView::SelectRoot()
{
AddSelectedItem( GetRootItemIndex(), true );
}
//-----------------------------------------------------------------------------
// Gets the number of root directories
//-----------------------------------------------------------------------------
int CGameFileTreeView::GetRootDirectoryCount()
{
return GetNumChildren( GetRootItemIndex() );
}
//-----------------------------------------------------------------------------
// Gets the ith root directory
//-----------------------------------------------------------------------------
const char *CGameFileTreeView::GetRootDirectory( int nIndex )
{
int nItemIndex = GetChild( GetRootItemIndex(), nIndex );
KeyValues *kv = GetItemData( nItemIndex );
if ( !kv )
return NULL;
return kv->GetString( "path", NULL );
}
//-----------------------------------------------------------------------------
// Populate the root node (necessary since tree view can't have multiple roots)
//-----------------------------------------------------------------------------
void CGameFileTreeView::PopulateRootNode( int itemIndex )
{
AddDirectoriesOfNode( itemIndex, m_RootDir );
if ( m_bUseExt )
{
AddFilesOfNode( itemIndex, m_RootDir, m_Ext );
}
}
//-----------------------------------------------------------------------------
// Populate the root node with directories
//-----------------------------------------------------------------------------
bool CGameFileTreeView::DoesDirectoryHaveSubdirectories( const char *pFilePath )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
while ( pszFileName )
{
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
return true;
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
return false;
}
//-----------------------------------------------------------------------------
// Populate the root node with directories
//-----------------------------------------------------------------------------
void CGameFileTreeView::AddDirectoriesOfNode( int itemIndex, const char *pFilePath )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
while ( pszFileName )
{
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
{
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
char pFullPath[MAX_PATH];
Q_snprintf( pFullPath, sizeof(pFullPath), "%s/%s", pFilePath, pszFileName );
Q_FixSlashes( pFullPath );
Q_strlower( pFullPath );
bool bHasSubdirectories = DoesDirectoryHaveSubdirectories( pFullPath );
kv->SetString( "path", pFullPath );
kv->SetInt( "expand", bHasSubdirectories );
kv->SetInt( "dir", 1 );
kv->SetInt( "image", IMAGE_FOLDER );
int itemID = AddItem(kv, itemIndex);
kv->deleteThis();
// mark directories in orange
SetItemColorForDirectories( itemID );
}
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
}
//-----------------------------------------------------------------------------
// Populate the root node with files
//-----------------------------------------------------------------------------
void CGameFileTreeView::AddFilesOfNode( int itemIndex, const char *pFilePath, const char *pExt )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*.%s", pFilePath, pExt );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirst( pSearchString, &findHandle );
while ( pszFileName )
{
if ( !g_pFullFileSystem->FindIsDirectory( findHandle ) )
{
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
char pFullPath[MAX_PATH];
Q_snprintf( pFullPath, MAX_PATH, "%s\\%s", pFilePath, pszFileName );
kv->SetString( "path", pFullPath );
kv->SetInt( "image", IMAGE_FILE );
AddItem(kv, itemIndex);
kv->deleteThis();
}
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
}
//-----------------------------------------------------------------------------
// override to incremental request and show p4 directories
//-----------------------------------------------------------------------------
void CGameFileTreeView::GenerateChildrenOfNode(int itemIndex)
{
KeyValues *pkv = GetItemData(itemIndex);
if ( pkv->GetInt("root") )
{
PopulateRootNode( itemIndex );
return;
}
if (!pkv->GetInt("dir"))
return;
const char *pFilePath = pkv->GetString("path", "");
if (!pFilePath[0])
return;
surface()->SetCursor(dc_waitarrow);
AddDirectoriesOfNode( itemIndex, pFilePath );
if ( m_bUseExt )
{
AddFilesOfNode( itemIndex, pFilePath, m_Ext );
}
}
//-----------------------------------------------------------------------------
// setup a context menu whenever a directory is clicked on
//-----------------------------------------------------------------------------
void CGameFileTreeView::GenerateContextMenu( int itemIndex, int x, int y )
{
return;
/*
KeyValues *pkv = GetItemData(itemIndex);
const char *pFilePath = pkv->GetString("path", "");
if (!pFilePath[0])
return;
Menu *pContext = new Menu(this, "FileContext");
pContext->AddMenuItem("Cloak folder", new KeyValues("CloakFolder", "item", itemIndex), GetParent(), NULL);
// show the context menu
pContext->SetPos(x, y);
pContext->SetVisible(true);
*/
}
//-----------------------------------------------------------------------------
// Sets an item to be colored as if its a menu
//-----------------------------------------------------------------------------
void CGameFileTreeView::SetItemColorForDirectories( int itemID )
{
// mark directories in orange
SetItemFgColor( itemID, Color(224, 192, 0, 255) );
}
//-----------------------------------------------------------------------------
// setup a smaller font
//-----------------------------------------------------------------------------
void CGameFileTreeView::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFont( pScheme->GetFont("DefaultSmall") );
}

View File

@@ -0,0 +1,201 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "matsys_controls/manipulator.h"
#include "materialsystem/imaterialsystem.h"
#include "vgui/IVGui.h"
#include "vgui/IInput.h"
#include "vgui/ISystem.h"
#include "vgui/MouseCode.h"
#include "mathlib/vector.h"
#include "mathlib/vmatrix.h"
#include "mathlib/mathlib.h"
#include <float.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// local helper functions
//-----------------------------------------------------------------------------
static float UpdateTime( float &flLastTime )
{
float flTime = vgui::system()->GetFrameTime();
float dt = flTime - flLastTime;
flLastTime = flTime;
return dt;
}
//-----------------------------------------------------------------------------
// Base class for manipulators which operate on transforms
//-----------------------------------------------------------------------------
CTransformManipulator::CTransformManipulator( matrix3x4_t *pTransform ) :
m_pTransform( pTransform )
{
}
void CTransformManipulator::SetTransform( matrix3x4_t *pTransform )
{
m_pTransform = pTransform;
}
matrix3x4_t *CTransformManipulator::GetTransform( void )
{
return m_pTransform;
}
//-----------------------------------------------------------------------------
// CPotteryWheelManip - nendo-style camera manipulator
//-----------------------------------------------------------------------------
CPotteryWheelManip::CPotteryWheelManip( matrix3x4_t *pTransform ) :
CTransformManipulator( pTransform ),
m_lastx( -1 ), m_lasty( -1 ),
m_zoom( 100.0f ), m_altitude( 0.0f ), m_azimuth( 0.0f ),
m_prevZoom( 100.0f ), m_prevAltitude( 0.0f ), m_prevAzimuth( 0.0f ),
m_flLastMouseTime( 0.0f ), m_flLastTickTime( 0.0f ),
m_flSpin( 0.0f ), m_bSpin( false )
{
}
void CPotteryWheelManip::OnBeginManipulation( void )
{
m_prevZoom = m_zoom;
m_prevAltitude = m_altitude;
m_prevAzimuth = m_azimuth;
m_flLastMouseTime = m_flLastTickTime = vgui::system()->GetFrameTime();
m_flSpin = 0.0f;
m_bSpin = false;
}
// Sets the zoom level
void CPotteryWheelManip::SetZoom( float flZoom )
{
m_prevZoom = m_zoom = flZoom;
}
void CPotteryWheelManip::OnAcceptManipulation( void )
{
m_flSpin = 0.0f;
m_bSpin = false;
}
void CPotteryWheelManip::OnCancelManipulation( void )
{
m_zoom = m_prevZoom;
m_altitude = m_prevAltitude;
m_azimuth = m_prevAzimuth;
m_flSpin = 0.0f;
m_bSpin = false;
UpdateTransform();
}
void CPotteryWheelManip::OnTick( void )
{
float dt = UpdateTime( m_flLastTickTime );
if ( m_bSpin )
{
m_azimuth += dt * m_flSpin;
UpdateTransform();
}
}
void CPotteryWheelManip::OnCursorMoved( int x, int y )
{
float dt = UpdateTime( m_flLastMouseTime );
if ( m_bSpin )
{
m_lastx = x;
m_lasty = y;
return;
}
if ( input()->IsMouseDown( MOUSE_MIDDLE ) )
{
int dy = y - m_lasty;
int dx = x - m_lastx;
if ( abs( dx ) < 2 * abs( dy ) )
{
UpdateZoom( 0.2f * dy );
}
else
{
m_flSpin = (dt != 0.0f) ? 0.002f * dx / dt : 0.0f;
m_azimuth += 0.002f * dx;
}
}
else
{
m_azimuth += 0.002f * ( x - m_lastx );
m_altitude -= 0.002f * ( y - m_lasty );
m_altitude = max( (float)-M_PI/2, min( (float)M_PI/2, m_altitude ) );
}
m_lastx = x;
m_lasty = y;
UpdateTransform();
}
void CPotteryWheelManip::OnMousePressed( vgui::MouseCode code, int x, int y )
{
UpdateTime( m_flLastMouseTime );
m_lastx = x;
m_lasty = y;
m_bSpin = false;
m_flSpin = 0.0f;
}
void CPotteryWheelManip::OnMouseReleased( vgui::MouseCode code, int x, int y )
{
UpdateTime( m_flLastMouseTime );
if ( code == MOUSE_MIDDLE )
{
m_bSpin = ( fabs( m_flSpin ) > 1.0f );
}
m_lastx = x;
m_lasty = y;
}
void CPotteryWheelManip::OnMouseWheeled( int delta )
{
UpdateTime( m_flLastMouseTime );
UpdateZoom( -10.0f * delta );
UpdateTransform();
}
void CPotteryWheelManip::UpdateTransform()
{
if ( !m_pTransform )
return;
float y = m_zoom * sin( m_altitude );
float xz = m_zoom * cos( m_altitude );
float x = xz * sin( m_azimuth );
float z = xz * cos( m_azimuth );
Vector position(x, y, z);
AngleMatrix( RadianEuler( -m_altitude, m_azimuth, 0 ), position, *m_pTransform );
}
void CPotteryWheelManip::UpdateZoom( float delta )
{
m_zoom *= pow( 1.01f, delta );
}

View File

@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
// MATSYS_CONTROLS.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR "..\.."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Project "matsys_controls"
{
$Folder "Source Files"
{
$File "assetpicker.cpp"
$File "baseassetpicker.cpp"
$File "colorpickerpanel.cpp"
$File "curveeditorpanel.cpp"
$File "gamefiletreeview.cpp"
$File "manipulator.cpp"
$File "matsyscontrols.cpp"
$File "mdlpanel.cpp"
$File "mdlpicker.cpp"
$File "mdlsequencepicker.cpp"
$File "picker.cpp"
$File "potterywheelpanel.cpp"
$File "proceduraltexturepanel.cpp"
$File "QCGenerator.cpp"
$File "sequencepicker.cpp"
$File "tgapreviewpanel.cpp"
$File "vmtpicker.cpp"
$File "vmtpreviewpanel.cpp"
$File "vtfpicker.cpp"
$File "vtfpreviewpanel.cpp"
$File "vmtpanel.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\matsys_controls\assetpicker.h"
$File "$SRCDIR\public\matsys_controls\baseassetpicker.h"
$File "$SRCDIR\public\matsys_controls\colorpickerpanel.h"
$File "$SRCDIR\public\matsys_controls\gamefiletreeview.h"
$File "$SRCDIR\public\matsys_controls\manipulator.h"
$File "$SRCDIR\public\matsys_controls\matsyscontrols.h"
$File "$SRCDIR\public\matsys_controls\mdlpanel.h"
$File "$SRCDIR\public\matsys_controls\mdlpicker.h"
$File "$SRCDIR\public\matsys_controls\mdlsequencepicker.h"
$File "$SRCDIR\public\matsys_controls\picker.h"
$File "$SRCDIR\public\matsys_controls\potterywheelpanel.h"
$File "$SRCDIR\public\matsys_controls\proceduraltexturepanel.h"
$File "$SRCDIR\public\matsys_controls\QCGenerator.h"
$File "$SRCDIR\public\matsys_controls\sequencepicker.h"
$File "$SRCDIR\public\matsys_controls\tgapreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vmtpicker.h"
$File "$SRCDIR\public\matsys_controls\vmtpreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vtfpicker.h"
$File "$SRCDIR\public\matsys_controls\vtfpreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vmtpanel.h"
}
$Folder "Link Libraries"
{
$Lib bitmap [$WIN32]
}
}

View File

@@ -0,0 +1,100 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "matsys_controls/matsyscontrols.h"
#include <materialsystem/imaterialsystem.h>
#include <materialsystem/imaterialsystemhardwareconfig.h>
#include <datacache/imdlcache.h>
#include <VGuiMatSurface/IMatSystemSurface.h>
#include <istudiorender.h>
#include "vgui_controls/Controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
namespace vgui
{
IMaterialSystem *g_pMaterialSystem = NULL;
IMaterialSystem *MaterialSystem()
{
return g_pMaterialSystem;
}
IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig = NULL;
IMaterialSystemHardwareConfig *MaterialSystemHardwareConfig()
{
return g_pMaterialSystemHardwareConfig;
}
IMDLCache *g_pMDLCache = NULL;
IMDLCache *MDLCache()
{
return g_pMDLCache;
}
IMatSystemSurface *g_pMatSystemSurface = NULL;
IMatSystemSurface *MatSystemSurface()
{
return g_pMatSystemSurface;
}
IStudioRender *g_pStudioRender = NULL;
IStudioRender *StudioRender()
{
return g_pStudioRender;
}
//-----------------------------------------------------------------------------
// Purpose: finds a particular interface in the factory set
//-----------------------------------------------------------------------------
static void *InitializeInterface( char const *interfaceName, CreateInterfaceFn *factoryList, int numFactories )
{
void *retval;
for ( int i = 0; i < numFactories; i++ )
{
CreateInterfaceFn factory = factoryList[ i ];
if ( !factory )
continue;
retval = factory( interfaceName, NULL );
if ( retval )
return retval;
}
// No provider for requested interface!!!
// Assert( !"No provider for requested interface!!!" );
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Initializes the controls
//-----------------------------------------------------------------------------
bool VGui_InitMatSysInterfacesList( const char *moduleName, CreateInterfaceFn *factoryList, int numFactories )
{
if ( !vgui::VGui_InitInterfacesList( moduleName, factoryList, numFactories ) )
return false;
g_pMaterialSystem = (IMaterialSystem *)InitializeInterface( MATERIAL_SYSTEM_INTERFACE_VERSION, factoryList, numFactories );
g_pMatSystemSurface = (IMatSystemSurface *)InitializeInterface( MAT_SYSTEM_SURFACE_INTERFACE_VERSION, factoryList, numFactories );
g_pMDLCache = (IMDLCache *)InitializeInterface( MDLCACHE_INTERFACE_VERSION, factoryList, numFactories );
g_pStudioRender = (IStudioRender *)InitializeInterface( STUDIO_RENDER_INTERFACE_VERSION, factoryList, numFactories );
g_pMaterialSystemHardwareConfig = (IMaterialSystemHardwareConfig *)InitializeInterface( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, factoryList, numFactories );
// MDL cache + studiorender are optional
return ( g_pMaterialSystem && g_pMatSystemSurface && g_pMaterialSystemHardwareConfig );
}
} // namespace vgui

View File

@@ -0,0 +1,902 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "matsys_controls/mdlpanel.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "materialsystem/imesh.h"
#include "vgui/IVGui.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/Frame.h"
#include "tier1/convar.h"
#include "tier0/dbg.h"
#include "tier1/fmtstr.h"
#include "istudiorender.h"
#include "matsys_controls/matsyscontrols.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "bone_setup.h"
#include "vphysics_interface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( CMDLPanel );
static const int THUMBNAIL_SAFE_ZONE_SIZE = 512;
static const int THUMBNAIL_SAFE_ZONE_HEIGHT = 92;
static const float THUMBNAIL_SAFE_ZONE_HEIGHT_SCALE = (float)THUMBNAIL_SAFE_ZONE_HEIGHT / THUMBNAIL_SAFE_ZONE_SIZE;
//-----------------------------------------------------------------------------
// Purpose: Keeps a global clock to autoplay sequences to run from
// Also deals with speedScale changes
//-----------------------------------------------------------------------------
float GetAutoPlayTime( void )
{
static int g_prevTicks;
static float g_time;
int ticks = Plat_MSTime();
// limit delta so that float time doesn't overflow
if (g_prevTicks == 0)
{
g_prevTicks = ticks;
}
g_time += ( ticks - g_prevTicks ) / 1000.0f;
g_prevTicks = ticks;
return g_time;
}
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CMDLPanel::CMDLPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
SetVisible( true );
// Used to poll input
vgui::ivgui()->AddTickSignal( GetVPanel() );
// Deal with the default cubemap
ITexture *pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap", NULL, true );
m_DefaultEnvCubemap.Init( pCubemapTexture );
pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap.hdr", NULL, true );
m_DefaultHDREnvCubemap.Init( pCubemapTexture );
SetIdentityMatrix( m_RootMDL.m_MDLToWorld );
m_bDrawCollisionModel = false;
m_bWireFrame = false;
m_bGroundGrid = false;
m_bLockView = false;
m_bLookAtCamera = true;
m_bThumbnailSafeZone = false;
m_nNumSequenceLayers = 0;
ResetAnimationEventState( &m_EventState );
}
CMDLPanel::~CMDLPanel()
{
m_aMergeMDLs.Purge();
m_DefaultEnvCubemap.Shutdown( );
m_DefaultHDREnvCubemap.Shutdown();
}
//-----------------------------------------------------------------------------
// Scheme settings
//-----------------------------------------------------------------------------
void CMDLPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
SetBackgroundColor( GetBgColor() );
SetBorder( pScheme->GetBorder( "MenuBorder") );
}
//-----------------------------------------------------------------------------
// Rendering options
//-----------------------------------------------------------------------------
void CMDLPanel::SetCollsionModel( bool bVisible )
{
m_bDrawCollisionModel = bVisible;
}
void CMDLPanel::SetGroundGrid( bool bVisible )
{
m_bGroundGrid = bVisible;
}
void CMDLPanel::SetWireFrame( bool bVisible )
{
m_bWireFrame = bVisible;
}
void CMDLPanel::SetLockView( bool bLocked )
{
m_bLockView = bLocked;
}
void CMDLPanel::SetLookAtCamera( bool bLookAtCamera )
{
m_bLookAtCamera = bLookAtCamera;
}
void CMDLPanel::SetIgnoreDoubleClick( bool bState )
{
m_bIgnoreDoubleClick = bState;
}
void CMDLPanel::SetThumbnailSafeZone( bool bVisible )
{
m_bThumbnailSafeZone = bVisible;
}
//-----------------------------------------------------------------------------
// Stores the clip
//-----------------------------------------------------------------------------
void CMDLPanel::SetMDL( MDLHandle_t handle, void *pProxyData )
{
m_RootMDL.m_MDL.SetMDL( handle );
m_RootMDL.m_MDL.m_pProxyData = pProxyData;
Vector vecMins, vecMaxs;
GetMDLBoundingBox( &vecMins, &vecMaxs, handle, m_RootMDL.m_MDL.m_nSequence );
m_RootMDL.m_MDL.m_bWorldSpaceViewTarget = false;
m_RootMDL.m_MDL.m_vecViewTarget.Init( 100.0f, 0.0f, vecMaxs.z );
m_RootMDL.m_flCycleStartTime = 0.f;
// Set the pose parameters to the default for the mdl
SetPoseParameters( NULL, 0 );
// Clear any sequence layers
SetSequenceLayers( NULL, 0 );
ResetAnimationEventState( &m_EventState );
}
//-----------------------------------------------------------------------------
// An MDL was selected
//-----------------------------------------------------------------------------
void CMDLPanel::SetMDL( const char *pMDLName, void *pProxyData )
{
MDLHandle_t hMDLFindResult = vgui::MDLCache()->FindMDL( pMDLName );
MDLHandle_t hMDL = pMDLName ? hMDLFindResult : MDLHANDLE_INVALID;
if ( vgui::MDLCache()->IsErrorModel( hMDL ) )
{
hMDL = MDLHANDLE_INVALID;
}
SetMDL( hMDL, pProxyData );
// FindMDL takes a reference and the the CMDL will also hold a reference for as long as it sticks around. Release the FindMDL reference.
int nRef = vgui::MDLCache()->Release( hMDLFindResult );
(void)nRef; // Avoid unreferenced variable warning
AssertMsg( hMDL == MDLHANDLE_INVALID || nRef > 0, "CMDLPanel::SetMDL referenced a model that has a zero ref count." );
}
//-----------------------------------------------------------------------------
// Purpose: Returns a model bounding box.
//-----------------------------------------------------------------------------
bool CMDLPanel::GetBoundingBox( Vector &vecBoundsMin, Vector &vecBoundsMax )
{
// Check to see if we have a valid model to look at.
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
return false;
GetMDLBoundingBox( &vecBoundsMin, &vecBoundsMax, m_RootMDL.m_MDL.GetMDL(), m_RootMDL.m_MDL.m_nSequence );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Returns a more accurate bounding sphere
//-----------------------------------------------------------------------------
bool CMDLPanel::GetBoundingSphere( Vector &vecCenter, float &flRadius )
{
// Check to see if we have a valid model to look at.
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
return false;
Vector vecEngineCenter;
GetMDLBoundingSphere( &vecEngineCenter, &flRadius, m_RootMDL.m_MDL.GetMDL(), m_RootMDL.m_MDL.m_nSequence );
VectorTransform( vecEngineCenter, m_RootMDL.m_MDLToWorld, vecCenter );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos )
{
SetIdentityMatrix( m_RootMDL.m_MDLToWorld );
AngleMatrix( angRot, vecPos, m_RootMDL.m_MDLToWorld );
}
//-----------------------------------------------------------------------------
// Sets the camera to look at the model
//-----------------------------------------------------------------------------
void CMDLPanel::LookAtMDL()
{
// Check to see if we have a valid model to look at.
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
return;
if ( m_bLockView )
return;
float flRadius;
Vector vecCenter;
GetBoundingSphere( vecCenter, flRadius );
LookAt( vecCenter, flRadius );
}
//-----------------------------------------------------------------------------
// FIXME: This should be moved into studiorender
//-----------------------------------------------------------------------------
static ConVar r_showenvcubemap( "r_showenvcubemap", "0", FCVAR_CHEAT );
static ConVar r_eyegloss ( "r_eyegloss", "1", FCVAR_ARCHIVE ); // wet eyes
static ConVar r_eyemove ( "r_eyemove", "1", FCVAR_ARCHIVE ); // look around
static ConVar r_eyeshift_x ( "r_eyeshift_x", "0", FCVAR_ARCHIVE ); // eye X position
static ConVar r_eyeshift_y ( "r_eyeshift_y", "0", FCVAR_ARCHIVE ); // eye Y position
static ConVar r_eyeshift_z ( "r_eyeshift_z", "0", FCVAR_ARCHIVE ); // eye Z position
static ConVar r_eyesize ( "r_eyesize", "0", FCVAR_ARCHIVE ); // adjustment to iris textures
static ConVar mat_softwareskin( "mat_softwareskin", "0", FCVAR_CHEAT );
static ConVar r_nohw ( "r_nohw", "0", FCVAR_CHEAT );
static ConVar r_nosw ( "r_nosw", "0", FCVAR_CHEAT );
static ConVar r_teeth ( "r_teeth", "1" );
static ConVar r_drawentities ( "r_drawentities", "1", FCVAR_CHEAT );
static ConVar r_flex ( "r_flex", "1" );
static ConVar r_eyes ( "r_eyes", "1" );
static ConVar r_skin ( "r_skin","0", FCVAR_CHEAT );
static ConVar r_maxmodeldecal ( "r_maxmodeldecal", "50" );
static ConVar r_modelwireframedecal ( "r_modelwireframedecal", "0", FCVAR_CHEAT );
static ConVar mat_normals ( "mat_normals", "0", FCVAR_CHEAT );
static ConVar r_eyeglintlodpixels ( "r_eyeglintlodpixels", "0", FCVAR_CHEAT );
static ConVar r_rootlod ( "r_rootlod", "0" );
static StudioRenderConfig_t s_StudioRenderConfig;
void CMDLPanel::UpdateStudioRenderConfig( void )
{
memset( &s_StudioRenderConfig, 0, sizeof(s_StudioRenderConfig) );
s_StudioRenderConfig.bEyeMove = !!r_eyemove.GetInt();
s_StudioRenderConfig.fEyeShiftX = r_eyeshift_x.GetFloat();
s_StudioRenderConfig.fEyeShiftY = r_eyeshift_y.GetFloat();
s_StudioRenderConfig.fEyeShiftZ = r_eyeshift_z.GetFloat();
s_StudioRenderConfig.fEyeSize = r_eyesize.GetFloat();
if( mat_softwareskin.GetInt() || m_bWireFrame )
{
s_StudioRenderConfig.bSoftwareSkin = true;
}
else
{
s_StudioRenderConfig.bSoftwareSkin = false;
}
s_StudioRenderConfig.bNoHardware = !!r_nohw.GetInt();
s_StudioRenderConfig.bNoSoftware = !!r_nosw.GetInt();
s_StudioRenderConfig.bTeeth = !!r_teeth.GetInt();
s_StudioRenderConfig.drawEntities = r_drawentities.GetInt();
s_StudioRenderConfig.bFlex = !!r_flex.GetInt();
s_StudioRenderConfig.bEyes = !!r_eyes.GetInt();
s_StudioRenderConfig.bWireframe = m_bWireFrame;
s_StudioRenderConfig.bDrawNormals = mat_normals.GetBool();
s_StudioRenderConfig.skin = r_skin.GetInt();
s_StudioRenderConfig.maxDecalsPerModel = r_maxmodeldecal.GetInt();
s_StudioRenderConfig.bWireframeDecals = r_modelwireframedecal.GetInt() != 0;
s_StudioRenderConfig.fullbright = false;
s_StudioRenderConfig.bSoftwareLighting = false;
s_StudioRenderConfig.bShowEnvCubemapOnly = r_showenvcubemap.GetInt() ? true : false;
s_StudioRenderConfig.fEyeGlintPixelWidthLODThreshold = r_eyeglintlodpixels.GetFloat();
StudioRender()->UpdateConfig( s_StudioRenderConfig );
}
void CMDLPanel::DrawCollisionModel()
{
vcollide_t *pCollide = MDLCache()->GetVCollide( m_RootMDL.m_MDL.GetMDL() );
if ( !pCollide || pCollide->solidCount <= 0 )
return;
static color32 color = {255,0,0,0};
IVPhysicsKeyParser *pParser = g_pPhysicsCollision->VPhysicsKeyParserCreate( pCollide->pKeyValues );
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
m_RootMDL.m_MDL.SetUpBones( m_RootMDL.m_MDLToWorld, MAXSTUDIOBONES, pBoneToWorld );
// PERFORMANCE: Just parse the script each frame. It's fast enough for tools. If you need
// this to go faster then cache off the bone index mapping in an array like HLMV does
while ( !pParser->Finished() )
{
const char *pBlock = pParser->GetCurrentBlockName();
if ( !stricmp( pBlock, "solid" ) )
{
solid_t solid;
pParser->ParseSolid( &solid, NULL );
int boneIndex = Studio_BoneIndexByName( &studioHdr, solid.name );
Vector *outVerts;
int vertCount = g_pPhysicsCollision->CreateDebugMesh( pCollide->solids[solid.index], &outVerts );
if ( vertCount )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
// NOTE: assumes these have been set up already by the model render code
// So this is a little bit of a back door to a cache of the bones
// this code wouldn't work unless you draw the model this frame before calling
// this routine. CMDLPanel always does this, but it's worth noting.
// A better solution would be to move the ragdoll visulization into the CDmeMdl
// and either draw it there or make it queryable and query/draw here.
matrix3x4_t xform;
SetIdentityMatrix( xform );
if ( boneIndex >= 0 )
{
MatrixCopy( pBoneToWorld[ boneIndex ], xform );
}
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_Wireframe );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, vertCount/3 );
for ( int j = 0; j < vertCount; j++ )
{
Vector out;
VectorTransform( outVerts[j].Base(), xform, out.Base() );
meshBuilder.Position3fv( out.Base() );
meshBuilder.Color4ub( color.r, color.g, color.b, color.a );
meshBuilder.TexCoord2f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
}
meshBuilder.End();
pMesh->Draw();
}
g_pPhysicsCollision->DestroyDebugMesh( vertCount, outVerts );
}
else
{
pParser->SkipBlock();
}
}
g_pPhysicsCollision->VPhysicsKeyParserDestroy( pParser );
}
void CMDLPanel::SetupRenderState( int nDisplayWidth, int nDisplayHeight )
{
int iWidth = nDisplayWidth;
int iHeight = nDisplayHeight;
if ( m_bThumbnailSafeZone )
{
iWidth = THUMBNAIL_SAFE_ZONE_SIZE;
iHeight = THUMBNAIL_SAFE_ZONE_SIZE;
}
BaseClass::SetupRenderState( iWidth, iHeight );
}
//-----------------------------------------------------------------------------
// paint it!
//-----------------------------------------------------------------------------
void CMDLPanel::OnPaint3D()
{
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
return;
// FIXME: Move this call into DrawModel in StudioRender
StudioRenderConfig_t oldStudioRenderConfig;
StudioRender()->GetCurrentConfig( oldStudioRenderConfig );
UpdateStudioRenderConfig();
CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() );
if ( vgui::MaterialSystemHardwareConfig()->GetHDRType() == HDR_TYPE_NONE )
{
ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( false ) : m_DefaultEnvCubemap;
pRenderContext->BindLocalCubemap( pMyCube );
}
else
{
ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( true ) : m_DefaultHDREnvCubemap;
pRenderContext->BindLocalCubemap( pMyCube );
}
PrePaint3D( pRenderContext );
if ( m_bGroundGrid )
{
DrawGrid();
}
if ( m_bLookAtCamera )
{
matrix3x4_t worldToCamera;
ComputeCameraTransform( &worldToCamera );
Vector vecPosition;
MatrixGetColumn( worldToCamera, 3, vecPosition );
m_RootMDL.m_MDL.m_bWorldSpaceViewTarget = true;
m_RootMDL.m_MDL.m_vecViewTarget = vecPosition;
}
// Draw the MDL
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
SetupFlexWeights();
matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( studioHdr.numbones() );
m_RootMDL.m_MDL.SetUpBones( m_RootMDL.m_MDLToWorld, studioHdr.numbones(), pBoneToWorld, m_PoseParameters, m_SequenceLayers, m_nNumSequenceLayers );
g_pStudioRender->UnlockBoneMatrices();
IMaterial* pOverrideMaterial = GetOverrideMaterial( m_RootMDL.m_MDL.GetMDL() );
if ( pOverrideMaterial != NULL )
g_pStudioRender->ForcedMaterialOverride( pOverrideMaterial );
m_RootMDL.m_MDL.Draw( m_RootMDL.m_MDLToWorld, pBoneToWorld );
if ( pOverrideMaterial != NULL )
g_pStudioRender->ForcedMaterialOverride( NULL );
pOverrideMaterial = NULL;
// Draw the merge MDLs.
matrix3x4_t matMergeBoneToWorld[MAXSTUDIOBONES];
int nMergeCount = m_aMergeMDLs.Count();
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
{
if ( m_aMergeMDLs[iMerge].m_bDisabled )
continue;
// Get the merge studio header.
studiohdr_t *pStudioHdr = g_pMDLCache->GetStudioHdr( m_aMergeMDLs[iMerge].m_MDL.GetMDL() );
matrix3x4_t *pMergeBoneToWorld = &matMergeBoneToWorld[0];
// If we have a valid mesh, bonemerge it. If we have an invalid mesh we can't bonemerge because
// it'll crash trying to pull data from the missing header.
if ( pStudioHdr != NULL )
{
CStudioHdr mergeHdr( pStudioHdr, g_pMDLCache );
m_aMergeMDLs[iMerge].m_MDL.SetupBonesWithBoneMerge( &mergeHdr, pMergeBoneToWorld, &studioHdr, pBoneToWorld, m_RootMDL.m_MDLToWorld );
pOverrideMaterial = GetOverrideMaterial( m_aMergeMDLs[iMerge].m_MDL.GetMDL() );
if ( pOverrideMaterial != NULL )
g_pStudioRender->ForcedMaterialOverride( pOverrideMaterial );
m_aMergeMDLs[iMerge].m_MDL.Draw( m_aMergeMDLs[iMerge].m_MDLToWorld, pMergeBoneToWorld );
if ( pOverrideMaterial != NULL )
g_pStudioRender->ForcedMaterialOverride( NULL );
// Notify of model render
RenderingMergedModel( pRenderContext, &mergeHdr, m_aMergeMDLs[iMerge].m_MDL.GetMDL(), pMergeBoneToWorld );
}
}
RenderingRootModel( pRenderContext, &studioHdr, m_RootMDL.m_MDL.GetMDL(), pBoneToWorld );
PostPaint3D( pRenderContext );
if ( m_bDrawCollisionModel )
{
DrawCollisionModel();
}
pRenderContext->Flush();
StudioRender()->UpdateConfig( oldStudioRenderConfig );
}
//-----------------------------------------------------------------------------
// Sets the current LOD
//-----------------------------------------------------------------------------
void CMDLPanel::SetLOD( int nLOD )
{
m_RootMDL.m_MDL.m_nLOD = nLOD;
int nMergeCount = m_aMergeMDLs.Count();
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
{
m_aMergeMDLs[iMerge].m_MDL.m_nLOD = nLOD;
}
}
//-----------------------------------------------------------------------------
// Sets the current sequence
//-----------------------------------------------------------------------------
void CMDLPanel::SetSequence( int nSequence, bool bResetSequence )
{
m_RootMDL.m_MDL.m_nSequence = nSequence;
if ( bResetSequence )
{
m_RootMDL.m_flCycleStartTime = GetAutoPlayTime();
}
}
//-----------------------------------------------------------------------------
// Set the current pose parameters. If NULL the pose parameters will be reset
// to the default values.
//-----------------------------------------------------------------------------
void CMDLPanel::SetPoseParameters( const float *pPoseParameters, int nCount )
{
if ( pPoseParameters )
{
int nParameters = MIN( MAXSTUDIOPOSEPARAM, nCount );
for ( int iParam = 0; iParam < nParameters; ++iParam )
{
m_PoseParameters[ iParam ] = pPoseParameters[ iParam ];
}
}
else if ( m_RootMDL.m_MDL.GetMDL() != MDLHANDLE_INVALID )
{
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
Studio_CalcDefaultPoseParameters( &studioHdr, m_PoseParameters, MAXSTUDIOPOSEPARAM );
}
}
//-----------------------------------------------------------------------------
// Set a pose parameter by name
//-----------------------------------------------------------------------------
bool CMDLPanel::SetPoseParameterByName( const char *pszName, float fValue )
{
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
int nPoseCount = studioHdr.GetNumPoseParameters();
for ( int i = 0; i < nPoseCount; ++i )
{
const mstudioposeparamdesc_t &Pose = studioHdr.pPoseParameter( i );
if ( V_strcasecmp( pszName, Pose.pszName() ) == 0 )
{
m_PoseParameters[ i ] = fValue;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Set the overlay sequence layers
//-----------------------------------------------------------------------------
void CMDLPanel::SetSequenceLayers( const MDLSquenceLayer_t *pSequenceLayers, int nCount )
{
if ( pSequenceLayers )
{
m_nNumSequenceLayers = MIN( MAX_SEQUENCE_LAYERS, nCount );
for ( int iLayer = 0; iLayer < m_nNumSequenceLayers; ++iLayer )
{
m_SequenceLayers[ iLayer ] = pSequenceLayers[ iLayer ];
ResetAnimationEventState( &m_SequenceLayerEventState[ iLayer ] );
}
}
else
{
m_nNumSequenceLayers = 0;
V_memset( m_SequenceLayers, 0, sizeof( m_SequenceLayers ) );
}
}
//-----------------------------------------------------------------------------
// Set the current skin
//-----------------------------------------------------------------------------
void CMDLPanel::SetSkin( int nSkin )
{
m_RootMDL.m_MDL.m_nSkin = nSkin;
}
//-----------------------------------------------------------------------------
// called when we're ticked...
//-----------------------------------------------------------------------------
void CMDLPanel::OnTick()
{
BaseClass::OnTick();
if ( m_RootMDL.m_MDL.GetMDL() != MDLHANDLE_INVALID )
{
m_RootMDL.m_MDL.m_flTime = ( GetAutoPlayTime() - m_RootMDL.m_flCycleStartTime );
DoAnimationEvents();
}
}
void CMDLPanel::Paint()
{
BaseClass::Paint();
if ( m_bThumbnailSafeZone )
{
int iWidth, iHeight;
GetSize( iWidth, iHeight );
CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() );
IMaterial *safezone = materials->FindMaterial( "vgui/thumbnails_safezone", TEXTURE_GROUP_VGUI, true );
if ( safezone )
{
safezone->IncrementReferenceCount();
}
int screenposx = 0;
int screenposy = 0;
LocalToScreen( screenposx, screenposy );
int iScaledHeight = THUMBNAIL_SAFE_ZONE_HEIGHT_SCALE * iHeight;
int iRemappedHeight = RemapVal( iScaledHeight, 0, THUMBNAIL_SAFE_ZONE_HEIGHT, 0, iScaledHeight );
pRenderContext->DrawScreenSpaceRectangle( safezone, screenposx, screenposy, iWidth, iRemappedHeight,
0, 0,
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_HEIGHT,
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_SIZE );
screenposx = 0;
screenposy = iHeight - iRemappedHeight;
LocalToScreen( screenposx, screenposy );
pRenderContext->DrawScreenSpaceRectangle( safezone, screenposx, screenposy, iWidth, iRemappedHeight,
0, 0,
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_HEIGHT,
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_SIZE );
if ( safezone )
{
safezone->DecrementReferenceCount();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::DoAnimationEvents()
{
CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
// If we don't have any sequences, don't do anything
if ( studioHdr.GetNumSeq() < 1 )
{
Assert( studioHdr.GetNumSeq() >= 1 );
return;
}
DoAnimationEvents( &studioHdr, m_RootMDL.m_MDL.m_nSequence, m_RootMDL.m_MDL.m_flTime, false, &m_EventState );
for ( int i = 0; i < m_nNumSequenceLayers; ++i )
{
float flTime = m_RootMDL.m_MDL.m_flTime - m_SequenceLayers[ i ].m_flCycleBeganAt;
//Plat_DebugString( CFmtStr("Animation: time = %f, started = %f, delta = %f\n",m_RootMDL.m_MDL.m_flTime,m_SequenceLayers[ i ].m_flCycleBeganAt,flTime ) );
DoAnimationEvents( &studioHdr, m_SequenceLayers[ i ].m_nSequenceIndex, flTime, m_SequenceLayers[ i ].m_bNoLoop, &m_SequenceLayerEventState[ i ] );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::DoAnimationEvents( CStudioHdr *pStudioHdr, int nSeqNum, float flTime, bool bNoLoop, MDLAnimEventState_t *pEventState )
{
if ( nSeqNum < 0 || nSeqNum >= pStudioHdr->GetNumSeq() )
{
return;
}
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( nSeqNum );
if ( seqdesc.numevents == 0 )
{
return;
}
mstudioevent_t *pevent = seqdesc.pEvent( 0 );
int nFrameCount = Studio_MaxFrame( pStudioHdr, nSeqNum, m_PoseParameters );
if ( nFrameCount == 0 )
{
nFrameCount = 1;
}
float flEventCycle = ( flTime * m_RootMDL.m_MDL.m_flPlaybackRate ) / nFrameCount;
//Plat_DebugString( CFmtStr("Event cycle: %f, playback rate: %f, frame count: %d\n", flEventCycle, m_RootMDL.m_MDL.m_flPlaybackRate, nFrameCount ) );
if ( bNoLoop )
{
flEventCycle = MIN(flEventCycle, 1.0f);
}
else
{
flEventCycle -= (int)(flEventCycle);
}
if ( pEventState->m_nEventSequence != nSeqNum )
{
pEventState->m_nEventSequence = nSeqNum;
flEventCycle = 0.0f;
pEventState->m_flPrevEventCycle = -0.01f; // back up to get 0'th frame animations
}
if ( flEventCycle == pEventState->m_flPrevEventCycle )
{
return;
}
// check for looping
BOOL bLooped = (flEventCycle < pEventState->m_flPrevEventCycle);
// This makes sure events that occur at the end of a sequence occur are
// sent before events that occur at the beginning of a sequence.
if (bLooped)
{
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
if ( pevent[i].cycle <= pEventState->m_flPrevEventCycle )
continue;
FireEvent( pevent[ i ].pszEventName(), pevent[ i ].pszOptions() );
}
// Necessary to get the next loop working
pEventState->m_flPrevEventCycle = -0.01f;
}
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
if ( (pevent[i].cycle > pEventState->m_flPrevEventCycle && pevent[i].cycle <= flEventCycle) )
{
FireEvent( pevent[ i ].pszEventName(), pevent[ i ].pszOptions() );
}
}
pEventState->m_flPrevEventCycle = flEventCycle;
}
void CMDLPanel::FireEvent( const char *pszEventName, const char *pszEventOptions )
{
KeyValues* pKVEvent = new KeyValues( "AnimEvent" );
pKVEvent->SetString( "name", pszEventName );
pKVEvent->SetString( "options", pszEventOptions );
PostActionSignal( pKVEvent );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::ResetAnimationEventState( MDLAnimEventState_t *pEventState )
{
pEventState->m_nEventSequence = -1;
pEventState->m_flPrevEventCycle = -0.01f;
}
//-----------------------------------------------------------------------------
// input
//-----------------------------------------------------------------------------
void CMDLPanel::OnMouseDoublePressed( vgui::MouseCode code )
{
if ( m_bIgnoreDoubleClick )
return;
float flRadius;
Vector vecCenter;
GetBoundingSphere( vecCenter, flRadius );
LookAt( vecCenter, flRadius );
BaseClass::OnMouseDoublePressed( code );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::SetMergeMDL( MDLHandle_t handle, void *pProxyData, int nSkin /*= -1 */ )
{
// Verify that we have a root model to merge to.
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
return;
int iIndex = m_aMergeMDLs.AddToTail();
if ( !m_aMergeMDLs.IsValidIndex( iIndex ) )
return;
m_aMergeMDLs[iIndex].m_MDL.SetMDL( handle );
if ( nSkin != -1 )
{
m_aMergeMDLs[iIndex].m_MDL.m_nSkin = nSkin;
}
m_aMergeMDLs[iIndex].m_MDL.m_nLOD = m_RootMDL.m_MDL.m_nLOD;
m_aMergeMDLs[iIndex].m_MDL.m_pProxyData = pProxyData;
SetIdentityMatrix( m_aMergeMDLs[iIndex].m_MDLToWorld );
m_aMergeMDLs[iIndex].m_bDisabled = false;
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
MDLHandle_t CMDLPanel::SetMergeMDL( const char *pMDLName, void *pProxyData, int nSkin /*= -1 */ )
{
MDLHandle_t hMDLFindResult = vgui::MDLCache()->FindMDL( pMDLName );
MDLHandle_t hMDL = pMDLName ? hMDLFindResult : MDLHANDLE_INVALID;
if ( vgui::MDLCache()->IsErrorModel( hMDL ) )
{
hMDL = MDLHANDLE_INVALID;
}
SetMergeMDL( hMDL, pProxyData, nSkin );
// FindMDL takes a reference and the the CMDL will also hold a reference for as long as it sticks around. Release the FindMDL reference.
int nRef = vgui::MDLCache()->Release( hMDLFindResult );
(void)nRef; // Avoid unreferenced variable warning
AssertMsg( hMDL == MDLHANDLE_INVALID || nRef > 0, "CMDLPanel::SetMergeMDL referenced a model that has a zero ref count." );
return hMDL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CMDLPanel::GetMergeMDLIndex( void *pProxyData )
{
int nMergeCount = m_aMergeMDLs.Count();
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
{
if ( m_aMergeMDLs[iMerge].m_MDL.m_pProxyData == pProxyData )
return iMerge;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CMDLPanel::GetMergeMDLIndex( MDLHandle_t handle )
{
int nMergeCount = m_aMergeMDLs.Count();
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
{
if ( m_aMergeMDLs[iMerge].m_MDL.GetMDL() == handle )
return iMerge;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMDL *CMDLPanel::GetMergeMDL( MDLHandle_t handle )
{
int nMergeCount = m_aMergeMDLs.Count();
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
{
if ( m_aMergeMDLs[iMerge].m_MDL.GetMDL() == handle )
return (&m_aMergeMDLs[iMerge].m_MDL);
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMDLPanel::ClearMergeMDLs( void )
{
m_aMergeMDLs.Purge();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,539 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "matsys_controls/mdlsequencepicker.h"
#include "tier1/KeyValues.h"
#include "tier1/utldict.h"
#include "datacache/imdlcache.h"
#include "filesystem.h"
#include "studio.h"
#include "vgui/IVGui.h"
#include "vgui/Cursor.h"
#include "vgui/ISurface.h"
#include "vgui_controls/Splitter.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/PropertySheet.h"
#include "vgui_controls/PropertyPage.h"
#include "vgui_controls/ToolWindow.h"
#include "vgui_controls/Button.h"
#include "matsys_controls/gamefiletreeview.h"
#include "matsys_controls/matsyscontrols.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// MDL Sequence Picker
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CMDLSequencePicker::CMDLSequencePicker( vgui::Panel *pParent ) : BaseClass(pParent, "MDLSequencePicker"), m_Images(false)
{
vgui::ivgui()->AddTickSignal( GetVPanel() );
m_hSelectedMDL = MDLHANDLE_INVALID;
// Horizontal splitter for mdls
m_pMDLSplitter = new Splitter( this, "MDLSplitter", SPLITTER_MODE_VERTICAL, 1 );
vgui::Panel *pSplitterLeftSide = m_pMDLSplitter->GetChild( 0 );
vgui::Panel *pSplitterRightSide = m_pMDLSplitter->GetChild( 1 );
// filter selection
m_pFilterList = new ComboBox( pSplitterLeftSide, "FilterList", 16, true );
m_pFilterList->AddActionSignalTarget( this );
// file browser tree controls
m_pFileTree = new CGameFileTreeView( pSplitterLeftSide, "FileTree", "All .MDLs", "models", "mdl" );
// build our list of images
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) );
m_pFileTree->SetImageList( &m_Images, false );
m_pFileTree->AddActionSignalTarget( this );
// property sheet - revisions, changes, etc.
m_pSequenceSplitter = new Splitter( pSplitterRightSide, "SequenceSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
vgui::Panel *pSplitterTopSide = m_pSequenceSplitter->GetChild( 0 );
vgui::Panel *pSplitterBottomSide = m_pSequenceSplitter->GetChild( 1 );
// MDL preview
m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
SetSkipChildDuringPainting( m_pMDLPreview );
m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
m_pViewsSheet->AddActionSignalTarget( this );
// sequences
m_pSequencesPage = new PropertyPage( m_pViewsSheet, "SequencesPage" );
m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
m_pSequencesList = new ListPanel( m_pSequencesPage, "SequencesList" );
m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
m_pSequencesList->AddActionSignalTarget( this );
m_pSequencesList->SetSelectIndividualCells( true );
m_pSequencesList->SetEmptyListText("No .MDL file currently selected.");
m_pSequencesList->SetDragEnabled( true );
m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
// Activities
m_pActivitiesPage = new PropertyPage( m_pViewsSheet, "ActivitiesPage" );
m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
m_pActivitiesList = new ListPanel( m_pActivitiesPage, "ActivitiesList" );
m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
m_pActivitiesList->AddActionSignalTarget( this );
m_pActivitiesList->SetSelectIndividualCells( true );
m_pActivitiesList->SetEmptyListText( "No .MDL file currently selected." );
m_pActivitiesList->SetDragEnabled( true );
m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
// Load layout settings; has to happen before pinning occurs in code
LoadControlSettingsAndUserConfig( "resource/mdlsequencepicker.res" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CMDLSequencePicker::~CMDLSequencePicker()
{
}
//-----------------------------------------------------------------------------
// Purpose: This is a bit of a hack to make sure that the ToolWindow containing this picker punches
// a hold for the rendering viewport, too
// Input : -
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnTick()
{
BaseClass::OnTick();
if ( GetParent() )
{
ToolWindow *tw = dynamic_cast< ToolWindow * >( GetParent()->GetParent() );
if ( tw )
{
tw->SetSkipChildDuringPainting( IsVisible() ? m_pMDLPreview : NULL );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: stops app on close
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnClose()
{
BaseClass::OnClose();
}
//-----------------------------------------------------------------------------
// Purpose: called to open
//-----------------------------------------------------------------------------
void CMDLSequencePicker::Activate()
{
RefreshFileList();
RefreshActivitiesAndSequencesList();
}
//-----------------------------------------------------------------------------
// Performs layout
//-----------------------------------------------------------------------------
void CMDLSequencePicker::PerformLayout()
{
// NOTE: This call should cause auto-resize to occur
// which should fix up the width of the panels
BaseClass::PerformLayout();
int w, h;
GetSize( w, h );
// Layout the mdl splitter
m_pMDLSplitter->SetBounds( 0, 0, w, h );
}
//-----------------------------------------------------------------------------
// Purpose: Refreshes the active file list
//-----------------------------------------------------------------------------
void CMDLSequencePicker::RefreshFileList()
{
m_pFileTree->RefreshFileList();
}
//-----------------------------------------------------------------------------
// Purpose: rebuilds the list of activities
//-----------------------------------------------------------------------------
void CMDLSequencePicker::RefreshActivitiesAndSequencesList()
{
m_pActivitiesList->RemoveAll();
m_pSequencesList->RemoveAll();
m_pMDLPreview->SetSequence( 0 );
if ( m_hSelectedMDL == MDLHANDLE_INVALID )
{
m_pActivitiesList->SetEmptyListText("No .MDL file currently selected");
m_pSequencesList->SetEmptyListText("No .MDL file currently selected");
return;
}
m_pActivitiesList->SetEmptyListText(".MDL file contains no activities");
m_pSequencesList->SetEmptyListText(".MDL file contains no sequences");
studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
for (int j = 0; j < hdr->GetNumSeq(); j++)
{
if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
{
const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
if ( pActivityName && pActivityName[0] )
{
// Multiple sequences can have the same activity name; only add unique activity names
if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
{
KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
pDrag->SetString( "texttype", "activityName" );
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
m_pActivitiesList->SetItemDragData( nItemID, pDrag );
activityNames.Insert( pActivityName, j );
}
}
const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
if ( pSequenceName && pSequenceName[0] )
{
KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
pkv->SetInt( "seqindex", j );
int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
pDrag->SetString( "texttype", "sequenceName" );
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
m_pSequencesList->SetItemDragData( nItemID, pDrag );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: refreshes dialog on text changing
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnTextChanged( vgui::Panel *pPanel, const char *pText )
{
// m_pFileTree->SetFilter( pText );
RefreshFileList();
}
/*
//-----------------------------------------------------------------------------
// Purpose: Selects an sequence based on an activity
//-----------------------------------------------------------------------------
int SelectWeightedSequence( studiohdr_t *pstudiohdr, int activity, int curSequence )
{
if (! pstudiohdr)
return 0;
VerifySequenceIndex( pstudiohdr );
int weighttotal = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
int weight = 0;
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
{
int curActivity = GetSequenceActivity( pstudiohdr, i, &weight );
if (curActivity == activity)
{
if ( curSequence == i && weight < 0 )
{
seq = i;
break;
}
weighttotal += iabs(weight);
int randomValue;
if ( IsInPrediction() )
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i );
else
randomValue = RandomInt( 0, weighttotal - 1 );
if (!weighttotal || randomValue < iabs(weight))
seq = i;
}
}
return seq;
}
*/
//-----------------------------------------------------------------------------
// Plays the selected activity
//-----------------------------------------------------------------------------
void CMDLSequencePicker::PlaySelectedActivity( )
{
int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
if ( nIndex < 0 )
return;
KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
const char *pActivityName = pkv->GetString( "activity", NULL );
if ( !pActivityName )
return;
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
{
// FIXME: Add weighted sequence selection logic?
m_pMDLPreview->SetSequence( i );
break;
}
}
}
//-----------------------------------------------------------------------------
// Plays the selected sequence
//-----------------------------------------------------------------------------
void CMDLSequencePicker::PlaySelectedSequence( )
{
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
if ( nIndex < 0 )
return;
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
const char *pSequenceName = pkv->GetString( "sequence", NULL );
if ( !pSequenceName )
return;
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
{
m_pMDLPreview->SetSequence( i );
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when a page is shown
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnPageChanged( )
{
if ( m_pViewsSheet->GetActivePage() == m_pSequencesPage )
{
PlaySelectedSequence();
return;
}
if ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage )
{
PlaySelectedActivity();
return;
}
}
//-----------------------------------------------------------------------------
// Purpose: refreshes dialog on text changing
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnItemSelected( KeyValues *kv )
{
Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
if ( pPanel == m_pSequencesList )
{
PlaySelectedSequence();
return;
}
if ( pPanel == m_pActivitiesList )
{
PlaySelectedActivity();
return;
}
}
//-----------------------------------------------------------------------------
// An MDL was selected
//-----------------------------------------------------------------------------
void CMDLSequencePicker::SelectMDL( const char *pMDLName )
{
m_hSelectedMDL = pMDLName ? vgui::MDLCache()->FindMDL( pMDLName ) : MDLHANDLE_INVALID;
if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL ) )
{
m_hSelectedMDL = MDLHANDLE_INVALID;
}
m_pMDLPreview->SetMDL( m_hSelectedMDL );
m_pMDLPreview->LookAtMDL();
RefreshActivitiesAndSequencesList();
}
//-----------------------------------------------------------------------------
// Purpose: updates revision view on a file being selected
//-----------------------------------------------------------------------------
void CMDLSequencePicker::OnFileSelected()
{
// update list
int iItem = m_pFileTree->GetFirstSelectedItem();
if ( iItem < 0 )
return;
// Don't bother to change if a directory was selected
KeyValues *pkv = m_pFileTree->GetItemData(iItem);
if ( pkv->GetInt("dir") || pkv->GetInt("root") )
return;
surface()->SetCursor(dc_waitarrow);
const char *pFullPathName = pkv->GetString( "path" );
char pRelativePathName[MAX_PATH];
g_pFullFileSystem->FullPathToRelativePath( pFullPathName, pRelativePathName, sizeof(pRelativePathName) );
// FIXME: Check that we're not actually opening the wrong file!!
SelectMDL( pRelativePathName );
}
char const *CMDLSequencePicker::GetModelName()
{
if ( MDLHANDLE_INVALID == m_hSelectedMDL )
{
return "";
}
return vgui::MDLCache()->GetModelName( m_hSelectedMDL );
}
char const *CMDLSequencePicker::GetSequenceName()
{
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
if ( nIndex < 0 )
return "";
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
const char *pSequenceName = pkv->GetString( "sequence", NULL );
if ( !pSequenceName )
return "";
return pSequenceName;
}
int CMDLSequencePicker::GetSequenceNumber()
{
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
if ( nIndex < 0 )
return -1;
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
return pkv->GetInt( "seqindex", -1 );
}
//-----------------------------------------------------------------------------
// Sequence picker frame
//-----------------------------------------------------------------------------
CMDLSequencePickerFrame::CMDLSequencePickerFrame( vgui::Panel *parent, char const *title ) :
BaseClass( parent, "MDLSequencePickerFrame" )
{
m_pMDLSequencePicker = new CMDLSequencePicker( this );
SetTitle( title, true );
SetSizeable( false );
SetCloseButtonVisible( false );
SetMoveable( true );
SetMinimumSize( 640, 480 );
Activate();
m_pMDLSequencePicker->Activate();
m_pOK = new Button( this, "OK", "#vgui_ok", this );
m_pOK->SetCommand( new KeyValues( "OnOK" ) );
m_pCancel= new Button( this, "Cancel", "#vgui_cancel", this );
m_pOK->SetCommand( new KeyValues( "OnCancel" ) );
m_pOK->SetEnabled( false );
vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
}
CMDLSequencePickerFrame::~CMDLSequencePickerFrame()
{
}
void CMDLSequencePickerFrame::OnTick()
{
BaseClass::OnTick();
bool bHasModel = m_pMDLSequencePicker->GetModelName()[ 0 ] != 0 ? true : false;
bool bHasSequence = m_pMDLSequencePicker->GetSequenceNumber() != -1 ? true : false;
m_pOK->SetEnabled( bHasModel && bHasSequence );
}
void CMDLSequencePickerFrame::PerformLayout()
{
BaseClass::PerformLayout();
int x, y, w, h;
GetClientArea( x, y, w, h );
h -= 24;
m_pMDLSequencePicker->SetBounds( x, y, w, h );
h += 5;
int bw = 120;
int bwwithGap = 2 * bw + 10;
x = ( w - bwwithGap ) / 2;
m_pOK->SetBounds( x, y + h, bw, 16 );
x += bw + 10;
m_pCancel->SetBounds( x, y + h, bw, 16 );
}
void CMDLSequencePickerFrame::OnCancel()
{
KeyValues *pActionKeys = new KeyValues( "AssetSelected" );
pActionKeys->SetString( "ModelName", m_pMDLSequencePicker->GetModelName() );
pActionKeys->SetString( "SequenceName", m_pMDLSequencePicker->GetSequenceName() );
pActionKeys->SetInt( "SequenceNumber", m_pMDLSequencePicker->GetSequenceNumber() );
PostActionSignal( pActionKeys );
CloseModal();
}
void CMDLSequencePickerFrame::OnOK()
{
CloseModal();
}

View File

@@ -0,0 +1,318 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "filesystem.h"
#include "matsys_controls/picker.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/Button.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Base asset Picker
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sort by asset name
//-----------------------------------------------------------------------------
static int __cdecl PickerBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("choice");
const char *string2 = item2.kv->GetString("choice");
return stricmp( string1, string2 );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CPicker::CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ) :
BaseClass( pParent, "Picker" )
{
m_pPickerType = pColumnHeader;
m_pPickerTextType = pTextType;
// FIXME: Make this an image browser
m_pPickerBrowser = new vgui::ListPanel( this, "Browser" );
m_pPickerBrowser->AddColumnHeader( 0, "choice", m_pPickerType, 52, 0 );
m_pPickerBrowser->SetSelectIndividualCells( true );
m_pPickerBrowser->SetEmptyListText( "Nothing to pick" );
m_pPickerBrowser->SetDragEnabled( true );
m_pPickerBrowser->AddActionSignalTarget( this );
m_pPickerBrowser->SetSortFunc( 0, PickerBrowserSortFunc );
m_pPickerBrowser->SetSortColumn( 0 );
// filter selection
m_pFilterList = new TextEntry( this, "FilterList" );
m_pFilterList->AddActionSignalTarget( this );
m_pFilterList->RequestFocus();
LoadControlSettingsAndUserConfig( "resource/picker.res" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPicker::~CPicker()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPicker::OnKeyCodePressed( KeyCode code )
{
if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
{
KeyValues *pMsg = new KeyValues("KeyCodePressed", "code", code);
vgui::ipanel()->SendMessage( m_pPickerBrowser->GetVPanel(), pMsg, GetVPanel());
pMsg->deleteThis();
}
else
{
BaseClass::OnKeyCodePressed( code );
}
}
//-----------------------------------------------------------------------------
// Purpose: refreshes the asset list
//-----------------------------------------------------------------------------
void CPicker::SetStringList( const PickerList_t &list )
{
m_Type = list.m_Type;
m_pPickerBrowser->RemoveAll();
int nCount = list.Count();
for ( int i = 0; i < nCount; ++i )
{
const char *pPickerName = list[i].m_pChoiceString;
KeyValues *kv = new KeyValues( "node", "choice", pPickerName );
if ( m_Type == PICKER_CHOICE_STRING )
{
kv->SetString( "value", list[i].m_pChoiceValue );
}
else
{
kv->SetPtr( "value", list[i].m_pChoiceValuePtr );
}
int nItemID = m_pPickerBrowser->AddItem( kv, 0, false, false );
if ( m_Type == PICKER_CHOICE_STRING )
{
KeyValues *pDrag = new KeyValues( "drag", "text", list[i].m_pChoiceValue );
if ( m_pPickerTextType )
{
pDrag->SetString( "texttype", m_pPickerTextType );
}
m_pPickerBrowser->SetItemDragData( nItemID, pDrag );
}
}
RefreshChoiceList();
}
//-----------------------------------------------------------------------------
// Purpose: refreshes the choice list
//-----------------------------------------------------------------------------
void CPicker::RefreshChoiceList( )
{
// Check the filter matches
int nMatchingCount = 0;
int nTotalCount = 0;
for ( int nItemID = m_pPickerBrowser->FirstItem(); nItemID != m_pPickerBrowser->InvalidItemID(); nItemID = m_pPickerBrowser->NextItem( nItemID ) )
{
KeyValues *kv = m_pPickerBrowser->GetItem( nItemID );
const char *pPickerName = kv->GetString( "choice" );
bool bVisible = !m_Filter.Length() || Q_stristr( pPickerName, m_Filter.Get() );
m_pPickerBrowser->SetItemVisible( nItemID, bVisible );
if ( bVisible )
{
++nMatchingCount;
}
++nTotalCount;
}
char pColumnTitle[512];
Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
m_pPickerType, nMatchingCount, nTotalCount );
m_pPickerBrowser->SetColumnHeaderText( 0, pColumnTitle );
m_pPickerBrowser->SortList();
if ( ( m_pPickerBrowser->GetSelectedItemsCount() == 0 ) && ( m_pPickerBrowser->GetItemCount() > 0 ) )
{
int nItemID = m_pPickerBrowser->GetItemIDFromRow( 0 );
m_pPickerBrowser->SetSelectedCell( nItemID, 0 );
}
}
//-----------------------------------------------------------------------------
// Purpose: refreshes dialog on text changing
//-----------------------------------------------------------------------------
void CPicker::OnTextChanged( )
{
int nLength = m_pFilterList->GetTextLength();
m_Filter.SetLength( nLength );
if ( nLength > 0 )
{
m_pFilterList->GetText( m_Filter.GetForModify(), nLength+1 );
}
RefreshChoiceList();
}
//-----------------------------------------------------------------------------
// Returns the selected string
//-----------------------------------------------------------------------------
PickerChoiceType_t CPicker::GetSelectionType() const
{
return m_Type;
}
const char *CPicker::GetSelectedString( ) const
{
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
return NULL;
if ( m_Type != PICKER_CHOICE_STRING )
return NULL;
int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
return pItemKeyValues->GetString( "value" );
}
void *CPicker::GetSelectedPtr( ) const
{
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
return NULL;
if ( m_Type != PICKER_CHOICE_PTR )
return NULL;
int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
return pItemKeyValues->GetPtr( "value" );
}
//-----------------------------------------------------------------------------
// Returns the index of the selected string
//-----------------------------------------------------------------------------
int CPicker::GetSelectedIndex()
{
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
return -1;
return m_pPickerBrowser->GetSelectedItem( 0 );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CPickerFrame::CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pPickerType, const char *pTextType ) :
BaseClass( pParent, "PickerFrame" )
{
m_pContextKeyValues = NULL;
SetDeleteSelfOnClose( true );
m_pPicker = new CPicker( this, pPickerType, pTextType );
m_pPicker->AddActionSignalTarget( this );
m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
SetBlockDragChaining( true );
LoadControlSettingsAndUserConfig( "resource/pickerframe.res" );
SetTitle( pTitle, false );
}
CPickerFrame::~CPickerFrame()
{
CleanUpMessage();
}
//-----------------------------------------------------------------------------
// Deletes the message
//-----------------------------------------------------------------------------
void CPickerFrame::CleanUpMessage()
{
if ( m_pContextKeyValues )
{
m_pContextKeyValues->deleteThis();
m_pContextKeyValues = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Activate the dialog
//-----------------------------------------------------------------------------
void CPickerFrame::DoModal( const PickerList_t &list, KeyValues *pContextKeyValues )
{
CleanUpMessage();
m_pContextKeyValues = pContextKeyValues;
m_pPicker->SetStringList( list );
BaseClass::DoModal();
}
//-----------------------------------------------------------------------------
// On command
//-----------------------------------------------------------------------------
void CPickerFrame::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "Open" ) )
{
KeyValues *pActionKeys = new KeyValues( "Picked" );
pActionKeys->SetInt( "choiceIndex", m_pPicker->GetSelectedIndex( ) );
if ( m_pPicker->GetSelectionType() == PICKER_CHOICE_STRING )
{
const char *pPickerName = m_pPicker->GetSelectedString( );
pActionKeys->SetString( "choice", pPickerName );
}
else
{
void *pPickerPtr = m_pPicker->GetSelectedPtr( );
pActionKeys->SetPtr( "choice", pPickerPtr );
}
if ( m_pContextKeyValues )
{
pActionKeys->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
PostActionSignal( pActionKeys );
CloseModal();
return;
}
if ( !Q_stricmp( pCommand, "Cancel" ) )
{
CloseModal();
return;
}
BaseClass::OnCommand( pCommand );
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/proceduraltexturepanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/itexture.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "tier1/KeyValues.h"
#include "pixelwriter.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
CProceduralTexturePanel::CProceduralTexturePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
m_pImageBuffer = NULL;
m_bMaintainProportions = false;
m_bUsePaintRect = false;
m_PaintRect.x = m_PaintRect.y = 0;
m_PaintRect.width = m_PaintRect.height = 0;
}
CProceduralTexturePanel::~CProceduralTexturePanel()
{
CleanUp();
}
//-----------------------------------------------------------------------------
// initialization, shutdown
//-----------------------------------------------------------------------------
bool CProceduralTexturePanel::Init( int nWidth, int nHeight, bool bAllocateImageBuffer )
{
m_nWidth = nWidth;
m_nHeight = nHeight;
if ( bAllocateImageBuffer )
{
m_pImageBuffer = new BGRA8888_t[nWidth * nHeight];
}
m_TextureSubRect.x = m_TextureSubRect.y = 0;
m_TextureSubRect.width = nWidth;
m_TextureSubRect.height = nHeight;
char pTemp[512];
Q_snprintf( pTemp, 512, "__%s", GetName() );
ITexture *pTex = MaterialSystem()->CreateProceduralTexture( pTemp, TEXTURE_GROUP_VGUI,
m_nWidth, m_nHeight, IMAGE_FORMAT_BGRX8888,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_NOMIP |
TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
pTex->SetTextureRegenerator( this );
m_ProceduralTexture.Init( pTex );
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
pVMTKeyValues->SetString( "$basetexture", pTemp );
pVMTKeyValues->SetInt( "$nocull", 1 );
pVMTKeyValues->SetInt( "$nodebug", 1 );
m_ProceduralMaterial.Init( MaterialSystem()->CreateMaterial( pTemp, pVMTKeyValues ));
m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_ProceduralMaterial );
return true;
}
void CProceduralTexturePanel::Shutdown()
{
CleanUp();
}
//-----------------------------------------------------------------------------
// Maintain proportions when drawing
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::MaintainProportions( bool bEnable )
{
m_bMaintainProportions = bEnable;
}
//-----------------------------------------------------------------------------
// Returns the image buffer + dimensions
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::CleanUp()
{
if ( (ITexture*)m_ProceduralTexture )
{
m_ProceduralTexture->SetTextureRegenerator( NULL );
}
m_ProceduralTexture.Shutdown();
m_ProceduralMaterial.Shutdown();
if ( m_pImageBuffer )
{
delete[] m_pImageBuffer;
m_pImageBuffer = NULL;
}
}
//-----------------------------------------------------------------------------
// Default implementation of regenerate texture bits
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
{
Assert( m_pImageBuffer );
Assert( pVTFTexture->FrameCount() == 1 );
Assert( pVTFTexture->FaceCount() == 1 );
Assert( !pTexture->IsMipmapped() );
int nWidth, nHeight, nDepth;
pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
Assert( nDepth == 1 );
Assert( nWidth == m_nWidth && nHeight == m_nHeight );
CPixelWriter pixelWriter;
pixelWriter.SetPixelMemory( pVTFTexture->Format(),
pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
for ( int y = 0; y < nHeight; ++y )
{
pixelWriter.Seek( 0, y );
BGRA8888_t *pTexel = &m_pImageBuffer[y * m_nWidth];
for ( int x = 0; x < nWidth; ++x, ++pTexel )
{
pixelWriter.WritePixel( pTexel->r, pTexel->g, pTexel->b, pTexel->a );
}
}
}
//-----------------------------------------------------------------------------
// Returns the image buffer + dimensions
//-----------------------------------------------------------------------------
BGRA8888_t *CProceduralTexturePanel::GetImageBuffer()
{
Assert( m_pImageBuffer );
return m_pImageBuffer;
}
int CProceduralTexturePanel::GetImageWidth() const
{
return m_nWidth;
}
int CProceduralTexturePanel::GetImageHeight() const
{
return m_nHeight;
}
//-----------------------------------------------------------------------------
// Sets the paint rect
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::SetPaintRect( const Rect_t *pPaintRect )
{
m_bUsePaintRect = ( pPaintRect != NULL );
if ( m_bUsePaintRect )
{
m_PaintRect = *pPaintRect;
}
}
//-----------------------------------------------------------------------------
// Sets the draw rect
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::SetTextureSubRect( const Rect_t &subRect )
{
m_TextureSubRect = subRect;
}
//-----------------------------------------------------------------------------
// Redownloads the procedural texture
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::DownloadTexture()
{
m_ProceduralTexture->Download();
}
//-----------------------------------------------------------------------------
// Paints the texture
//-----------------------------------------------------------------------------
void CProceduralTexturePanel::Paint( void )
{
vgui::surface()->DrawSetTexture( m_nTextureID );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
int x = 0;
int y = 0;
int w, h;
GetSize( w, h );
if ( m_bUsePaintRect )
{
x = m_PaintRect.x;
y = m_PaintRect.y;
w = m_PaintRect.width;
h = m_PaintRect.height;
}
if ( m_bMaintainProportions )
{
if ( m_TextureSubRect.width > m_TextureSubRect.height )
{
h = w * m_TextureSubRect.height / m_TextureSubRect.width;
}
else
{
w = h * m_TextureSubRect.width / m_TextureSubRect.height;
}
}
// Rotated version of the bitmap!
// Rotate about the center of the bitmap
vgui::Vertex_t verts[4];
verts[0].m_Position.Init( x, y );
verts[0].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
verts[1].m_Position.Init( w+x, y );
verts[1].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
verts[2].m_Position.Init( w+x, h+y );
verts[2].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
verts[3].m_Position.Init( x, h+y );
verts[3].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
vgui::surface()->DrawTexturedPolygon( 4, verts );
}

View File

@@ -0,0 +1,485 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "matsys_controls/sequencepicker.h"
#include "tier1/utldict.h"
#include "tier1/KeyValues.h"
#include "studio.h"
#include "vgui/IInput.h"
#include "vgui/ISurface.h"
#include "vgui_controls/Splitter.h"
#include "vgui_controls/PropertyPage.h"
#include "vgui_controls/PropertySheet.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/Button.h"
#include "matsys_controls/matsyscontrols.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Sequence Picker
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Sort by sequence name
//-----------------------------------------------------------------------------
static int __cdecl SequenceSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("sequence");
const char *string2 = item2.kv->GetString("sequence");
return stricmp( string1, string2 );
}
static int __cdecl ActivitySortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("activity");
const char *string2 = item2.kv->GetString("activity");
return stricmp( string1, string2 );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSequencePicker::CSequencePicker( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePicker" )
{
m_hSelectedMDL = MDLHANDLE_INVALID;
// property sheet - revisions, changes, etc.
m_pPreviewSplitter = new Splitter( this, "PreviewSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
vgui::Panel *pSplitterTopSide = m_pPreviewSplitter->GetChild( 0 );
vgui::Panel *pSplitterBottomSide = m_pPreviewSplitter->GetChild( 1 );
// MDL preview
m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
SetSkipChildDuringPainting( m_pMDLPreview );
m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
m_pViewsSheet->AddActionSignalTarget( this );
// sequences
m_pSequencesPage = NULL;
m_pSequencesList = NULL;
if ( nFlags & PICK_SEQUENCES )
{
m_pSequencesPage = new PropertyPage( m_pViewsSheet, "SequencesPage" );
m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
m_pSequencesList = new ListPanel( m_pSequencesPage, "SequencesList" );
m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
m_pSequencesList->AddActionSignalTarget( this );
m_pSequencesList->SetSelectIndividualCells( true );
m_pSequencesList->SetEmptyListText(".MDL file contains no activities");
m_pSequencesList->SetDragEnabled( true );
m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
m_pSequencesList->SetSortFunc( 0, SequenceSortFunc );
m_pSequencesList->SetSortColumn( 0 );
}
// Activities
m_pActivitiesPage = NULL;
m_pActivitiesList = NULL;
if ( nFlags & PICK_ACTIVITIES )
{
m_pActivitiesPage = new PropertyPage( m_pViewsSheet, "ActivitiesPage" );
m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
m_pActivitiesList = new ListPanel( m_pActivitiesPage, "ActivitiesList" );
m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
m_pActivitiesList->AddActionSignalTarget( this );
m_pActivitiesList->SetSelectIndividualCells( true );
m_pActivitiesList->SetEmptyListText( ".MDL file contains no activities" );
m_pActivitiesList->SetDragEnabled( true );
m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
m_pActivitiesList->SetSortFunc( 0, ActivitySortFunc );
m_pActivitiesList->SetSortColumn( 0 );
}
// Load layout settings; has to happen before pinning occurs in code
LoadControlSettingsAndUserConfig( "resource/sequencepicker.res" );
SETUP_PANEL( this );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CSequencePicker::~CSequencePicker()
{
}
//-----------------------------------------------------------------------------
// Performs layout
//-----------------------------------------------------------------------------
void CSequencePicker::PerformLayout()
{
// NOTE: This call should cause auto-resize to occur
// which should fix up the width of the panels
BaseClass::PerformLayout();
int w, h;
GetSize( w, h );
// Layout the mdl splitter
m_pPreviewSplitter->SetBounds( 0, 0, w, h );
}
//-----------------------------------------------------------------------------
// Purpose: rebuilds the list of activities + sequences
//-----------------------------------------------------------------------------
void CSequencePicker::RefreshActivitiesAndSequencesList()
{
if ( m_pActivitiesList )
{
m_pActivitiesList->RemoveAll();
}
if ( m_pSequencesList )
{
m_pSequencesList->RemoveAll();
}
m_pMDLPreview->SetSequence( 0 );
if ( m_hSelectedMDL == MDLHANDLE_INVALID )
return;
studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
for (int j = 0; j < hdr->GetNumSeq(); j++)
{
if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
{
const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
if ( m_pActivitiesList && pActivityName && pActivityName[0] )
{
// Multiple sequences can have the same activity name; only add unique activity names
if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
{
KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
pDrag->SetString( "texttype", "activityName" );
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
m_pActivitiesList->SetItemDragData( nItemID, pDrag );
activityNames.Insert( pActivityName, j );
}
}
const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
if ( m_pSequencesList && pSequenceName && pSequenceName[0] )
{
KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
pDrag->SetString( "texttype", "sequenceName" );
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
m_pSequencesList->SetItemDragData( nItemID, pDrag );
}
}
}
if ( m_pSequencesList )
{
m_pSequencesList->SortList();
}
if ( m_pActivitiesList )
{
m_pActivitiesList->SortList();
}
}
/*
//-----------------------------------------------------------------------------
// Purpose: Selects an sequence based on an activity
//-----------------------------------------------------------------------------
int SelectWeightedSequence( studiohdr_t *pstudiohdr, int activity, int curSequence )
{
if (! pstudiohdr)
return 0;
VerifySequenceIndex( pstudiohdr );
int weighttotal = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
int weight = 0;
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
{
int curActivity = GetSequenceActivity( pstudiohdr, i, &weight );
if (curActivity == activity)
{
if ( curSequence == i && weight < 0 )
{
seq = i;
break;
}
weighttotal += iabs(weight);
int randomValue;
if ( IsInPrediction() )
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i );
else
randomValue = RandomInt( 0, weighttotal - 1 );
if (!weighttotal || randomValue < iabs(weight))
seq = i;
}
}
return seq;
}
*/
//-----------------------------------------------------------------------------
// Gets the selected activity/sequence
//-----------------------------------------------------------------------------
CSequencePicker::PickType_t CSequencePicker::GetSelectedSequenceType( )
{
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
return PICK_SEQUENCES;
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
return PICK_ACTIVITIES;
return PICK_NONE;
}
const char *CSequencePicker::GetSelectedSequenceName( )
{
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
{
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
if ( nIndex >= 0 )
{
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
return pkv->GetString( "sequence", NULL );
}
return NULL;
}
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
{
int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
if ( nIndex >= 0 )
{
KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
return pkv->GetString( "activity", NULL );
}
return NULL;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Plays the selected activity
//-----------------------------------------------------------------------------
void CSequencePicker::PlayActivity( const char *pActivityName )
{
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
{
// FIXME: Add weighted sequence selection logic?
m_pMDLPreview->SetSequence( i );
break;
}
}
}
//-----------------------------------------------------------------------------
// Plays the selected sequence
//-----------------------------------------------------------------------------
void CSequencePicker::PlaySequence( const char *pSequenceName )
{
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
{
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
{
m_pMDLPreview->SetSequence( i );
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called when a page is shown
//-----------------------------------------------------------------------------
void CSequencePicker::OnPageChanged( )
{
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
{
const char *pSequenceName = GetSelectedSequenceName();
if ( pSequenceName )
{
PlaySequence( pSequenceName );
PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
}
return;
}
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
{
const char *pActivityName = GetSelectedSequenceName();
if ( pActivityName )
{
PlayActivity( pActivityName );
PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
}
return;
}
}
//-----------------------------------------------------------------------------
// Purpose: refreshes dialog on text changing
//-----------------------------------------------------------------------------
void CSequencePicker::OnItemSelected( KeyValues *kv )
{
Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
if ( m_pSequencesList && (pPanel == m_pSequencesList ) )
{
const char *pSequenceName = GetSelectedSequenceName();
if ( pSequenceName )
{
PlaySequence( pSequenceName );
PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
}
return;
}
if ( m_pActivitiesList && ( pPanel == m_pActivitiesList ) )
{
const char *pActivityName = GetSelectedSequenceName();
if ( pActivityName )
{
PlayActivity( pActivityName );
PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
}
return;
}
}
//-----------------------------------------------------------------------------
// Sets the MDL to select sequences in
//-----------------------------------------------------------------------------
void CSequencePicker::SetMDL( const char *pMDLName )
{
m_hSelectedMDL = pMDLName ? vgui::MDLCache()->FindMDL( pMDLName ) : MDLHANDLE_INVALID;
if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL ) )
{
m_hSelectedMDL = MDLHANDLE_INVALID;
}
m_pMDLPreview->SetMDL( m_hSelectedMDL );
m_pMDLPreview->LookAtMDL();
RefreshActivitiesAndSequencesList();
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CSequencePickerFrame::CSequencePickerFrame( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePickerFrame" )
{
SetDeleteSelfOnClose( true );
m_pPicker = new CSequencePicker( this, nFlags );
m_pPicker->AddActionSignalTarget( this );
m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
SetBlockDragChaining( true );
LoadControlSettingsAndUserConfig( "resource/sequencepickerframe.res" );
m_pOpenButton->SetEnabled( false );
}
//-----------------------------------------------------------------------------
// Purpose: Activate the dialog
//-----------------------------------------------------------------------------
void CSequencePickerFrame::DoModal( const char *pMDLName )
{
m_pPicker->SetMDL( pMDLName );
BaseClass::DoModal();
}
//-----------------------------------------------------------------------------
// On mdl preview changed
//-----------------------------------------------------------------------------
void CSequencePickerFrame::OnSequencePreviewChanged( KeyValues *pKeyValues )
{
const char *pSequence = pKeyValues->GetString( "sequence", NULL );
const char *pActivity = pKeyValues->GetString( "activity", NULL );
m_pOpenButton->SetEnabled( pSequence || pActivity );
}
//-----------------------------------------------------------------------------
// On command
//-----------------------------------------------------------------------------
void CSequencePickerFrame::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "Open" ) )
{
CSequencePicker::PickType_t type = m_pPicker->GetSelectedSequenceType( );
if (( type == CSequencePicker::PICK_SEQUENCES ) || ( type == CSequencePicker::PICK_ACTIVITIES ))
{
const char *pSequenceName = m_pPicker->GetSelectedSequenceName();
if ( pSequenceName )
{
if ( type == CSequencePicker::PICK_SEQUENCES )
{
PostActionSignal( new KeyValues("SequenceSelected", "sequence", pSequenceName ) );
}
else
{
PostActionSignal( new KeyValues("SequenceSelected", "activity", pSequenceName ) );
}
CloseModal();
return;
}
}
return;
}
if ( !Q_stricmp( pCommand, "Cancel" ) )
{
CloseModal();
return;
}
BaseClass::OnCommand( pCommand );
}

View File

@@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/tgapreviewpanel.h"
#include "bitmap/tgaloader.h"
#include "tier1/utlbuffer.h"
#include "filesystem.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// TGA Preview panel
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
CTGAPreviewPanel::CTGAPreviewPanel( vgui::Panel *pParent, const char *pName ) :
BaseClass( pParent, pName )
{
}
//-----------------------------------------------------------------------------
// Sets the current TGA
//-----------------------------------------------------------------------------
void CTGAPreviewPanel::SetTGA( const char *pFullPath )
{
int nWidth, nHeight;
ImageFormat format;
float flGamma;
CUtlBuffer buf;
if ( !g_pFullFileSystem->ReadFile( pFullPath, NULL, buf ) )
{
Warning( "Can't open TGA file: %s\n", pFullPath );
return;
}
TGALoader::GetInfo( buf, &nWidth, &nHeight, &format, &flGamma );
Shutdown();
Init( nWidth, nHeight, true );
m_TGAName = pFullPath;
buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
if ( !TGALoader::Load( (unsigned char*)GetImageBuffer(), buf,
nWidth, nHeight, IMAGE_FORMAT_BGRA8888, flGamma, false ) )
{
Shutdown();
}
else
{
DownloadTexture();
}
}
//-----------------------------------------------------------------------------
// Gets the current TGA
//-----------------------------------------------------------------------------
const char *CTGAPreviewPanel::GetTGA() const
{
return m_TGAName;
}

View File

@@ -0,0 +1,458 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "matsys_controls/vmtpanel.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/itexture.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "vgui_controls/ScrollBar.h"
#include "matsys_controls/matsyscontrols.h"
#include "vgui/IVGui.h"
#include "vgui_controls/ToolWindow.h"
#include "tier2/renderutils.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------------
enum
{
SCROLLBAR_SIZE=18, // the width of a scrollbar
WINDOW_BORDER_WIDTH=2 // the width of the window's border
};
#define SPHERE_RADIUS 10.0f
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CVMTPanel::CVMTPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
m_bUseActualSize = true;
m_pMaterial = NULL;
m_pHorizontalBar = new ScrollBar( this, "HorizScrollBar", false );
m_pHorizontalBar->AddActionSignalTarget(this);
m_pHorizontalBar->SetVisible(false);
m_pVerticalBar = new ScrollBar( this, "VertScrollBar", true );
m_pVerticalBar->AddActionSignalTarget(this);
m_pVerticalBar->SetVisible(false);
LookAt( SPHERE_RADIUS );
m_pLightmapTexture.Init( "//platform/materials/debug/defaultlightmap", "editor" );
m_DefaultEnvCubemap.Init( "editor/cubemap", "editor", true );
}
CVMTPanel::~CVMTPanel()
{
m_pLightmapTexture.Shutdown();
m_DefaultEnvCubemap.Shutdown();
if (m_pMaterial)
{
m_pMaterial->DecrementReferenceCount();
}
}
//-----------------------------------------------------------------------------
// Scheme
//-----------------------------------------------------------------------------
void CVMTPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
SetBorder( pScheme->GetBorder( "MenuBorder") );
}
//-----------------------------------------------------------------------------
// Set the material to draw
//-----------------------------------------------------------------------------
void CVMTPanel::SetMaterial( IMaterial *pMaterial )
{
if (pMaterial)
{
pMaterial->IncrementReferenceCount();
}
if (m_pMaterial)
{
m_pMaterial->DecrementReferenceCount();
}
m_pMaterial = pMaterial;
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Set rendering mode (stretch to full screen, or use actual size)
//-----------------------------------------------------------------------------
void CVMTPanel::RenderUsingActualSize( bool bEnable )
{
m_bUseActualSize = bEnable;
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: relayouts out the panel after any internal changes
//-----------------------------------------------------------------------------
void CVMTPanel::PerformLayout()
{
BaseClass::PerformLayout();
return;
// Get the current size, see if it's big enough to view the entire thing
int iWidth, iHeight;
GetSize( iWidth, iHeight );
// In the case of stretching, just stretch to the size and blow off
// the scrollbars. Same holds true if there's no material
if (!m_bUseActualSize || !m_pMaterial)
{
m_iViewableWidth = iWidth;
m_iViewableHeight = iHeight;
m_pHorizontalBar->SetVisible(false);
m_pVerticalBar->SetVisible(false);
return;
}
// Check the size of the material...
int iMaterialWidth = m_pMaterial->GetMappingWidth();
int iMaterialHeight = m_pMaterial->GetMappingHeight();
// Check if the scroll bars are visible
bool bHorizScrollVisible = (iMaterialWidth > iWidth);
bool bVertScrollVisible = (iMaterialHeight > iHeight);
m_pHorizontalBar->SetVisible(bHorizScrollVisible);
m_pVerticalBar->SetVisible(bVertScrollVisible);
// Shrink the bars if both are visible
m_iViewableWidth = bVertScrollVisible ? iWidth - SCROLLBAR_SIZE - WINDOW_BORDER_WIDTH : iWidth;
m_iViewableHeight = bHorizScrollVisible ? iHeight - SCROLLBAR_SIZE - WINDOW_BORDER_WIDTH : iHeight;
// Set the position of the horizontal bar...
if (bHorizScrollVisible)
{
m_pHorizontalBar->SetPos(0, iHeight - SCROLLBAR_SIZE);
m_pHorizontalBar->SetSize( m_iViewableWidth, SCROLLBAR_SIZE );
m_pHorizontalBar->SetRangeWindow( m_iViewableWidth );
m_pHorizontalBar->SetRange( 0, iMaterialWidth );
// FIXME: Change scroll amount based on how much is not visible?
m_pHorizontalBar->SetButtonPressedScrollValue( 5 );
}
// Set the position of the vertical bar...
if (bVertScrollVisible)
{
m_pVerticalBar->SetPos(iWidth - SCROLLBAR_SIZE, 0);
m_pVerticalBar->SetSize(SCROLLBAR_SIZE, m_iViewableHeight);
m_pVerticalBar->SetRangeWindow( m_iViewableHeight );
m_pVerticalBar->SetRange( 0, iMaterialHeight);
m_pVerticalBar->SetButtonPressedScrollValue( 5 );
}
}
//-----------------------------------------------------------------------------
// paint it stretched to the window size
//-----------------------------------------------------------------------------
void CVMTPanel::DrawStretchedToPanel( CMeshBuilder &meshBuilder )
{
// Draw a polygon the size of the panel
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( 0, 0, 0 );
meshBuilder.TexCoord2f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( 0, m_iViewableHeight, 0 );
meshBuilder.TexCoord2f( 0, 0, 1 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( m_iViewableWidth, m_iViewableHeight, 0 );
meshBuilder.TexCoord2f( 0, 1, 1 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( m_iViewableWidth, 0, 0 );
meshBuilder.TexCoord2f( 0, 0, 1 );
meshBuilder.AdvanceVertex();
}
//-----------------------------------------------------------------------------
// paint it actual size
//-----------------------------------------------------------------------------
void CVMTPanel::DrawActualSize( CMeshBuilder &meshBuilder )
{
// Check the size of the material...
int iMaterialWidth = m_pMaterial->GetMappingWidth();
int iMaterialHeight = m_pMaterial->GetMappingHeight();
Vector2D ul;
Vector2D lr;
Vector2D tul;
Vector2D tlr;
if (m_iViewableWidth >= iMaterialWidth)
{
// Center the material if we've got enough horizontal space
ul.x = (m_iViewableWidth - iMaterialWidth) * 0.5f;
lr.x = ul.x + iMaterialWidth;
tul.x = 0.0f; tlr.x = 1.0f;
}
else
{
// Use the scrollbars here...
int val = m_pHorizontalBar->GetValue();
tul.x = (float)val / (float)iMaterialWidth;
tlr.x = tul.x + (float)m_iViewableWidth / (float)iMaterialWidth;
ul.x = 0;
lr.x = m_iViewableWidth;
}
if (m_iViewableHeight >= iMaterialHeight)
{
// Center the material if we've got enough vertical space
ul.y = (m_iViewableHeight - iMaterialHeight) * 0.5f;
lr.y = ul.y + iMaterialHeight;
tul.y = 0.0f; tlr.y = 1.0f;
}
else
{
// Use the scrollbars here...
int val = m_pVerticalBar->GetValue();
tul.y = (float)val / (float)iMaterialHeight;
tlr.y = tul.y + (float)m_iViewableHeight / (float)iMaterialHeight;
ul.y = 0;
lr.y = m_iViewableHeight;
}
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( ul.x, ul.y, 0 );
meshBuilder.TexCoord2f( 0, tul.x, tul.y );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( lr.x, ul.y, 0 );
meshBuilder.TexCoord2f( 0, tlr.x, tul.y );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( lr.x, lr.y, 0 );
meshBuilder.TexCoord2f( 0, tlr.x, tlr.y );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.Position3f( ul.x, lr.y, 0 );
meshBuilder.TexCoord2f( 0, tul.x, tlr.y );
meshBuilder.AdvanceVertex();
}
//-----------------------------------------------------------------------------
// Draw it on a sphere
//-----------------------------------------------------------------------------
void CVMTPanel::RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi )
{
int nVertices = nTheta * nPhi;
int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
CMatRenderContextPtr pRenderContext( MaterialSystem() );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->Bind( m_pMaterial );
pRenderContext->BindLightmapTexture( m_pLightmapTexture );
pRenderContext->BindLocalCubemap( m_DefaultEnvCubemap );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nVertices, nIndices );
bool bIsUsingLightmap = m_pMaterial->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP );
bool bIsUsingBumpedLightmap = m_pMaterial->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS );
int nLightmapWidth = m_pLightmapTexture->GetActualWidth();
float flHalfLuxel = 0.5f / nLightmapWidth;
//
// Build the index buffer.
//
int i, j;
for ( i = 0; i < nPhi; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
float u = j / ( float )(nTheta - 1);
float v = i / ( float )(nPhi - 1);
float theta = ( j != nTheta-1 ) ? 2.0f * M_PI * u : 0.0f;
float phi = M_PI * v;
Vector vecPos;
vecPos.x = flRadius * sin(phi) * cos(theta);
vecPos.y = flRadius * sin(phi) * sin(theta);
vecPos.z = flRadius * cos(phi);
Vector vecNormal = vecPos;
VectorNormalize( vecNormal );
Vector4D vecTangentS;
Vector vecTangentT;
vecTangentS.Init( -vecPos.y, vecPos.x, 0.0f, 1.0f );
if ( VectorNormalize( vecTangentS.AsVector3D() ) == 0.0f )
{
vecTangentS.Init( 1.0f, 0.0f, 0.0f, 1.0f );
}
CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
unsigned char red = (int)( u * 255.0f );
unsigned char green = (int)( v * 255.0f );
unsigned char blue = (int)( v * 255.0f );
unsigned char alpha = (int)( v * 255.0f );
vecPos += vCenter;
float u1, u2, v1, v2;
u1 = u2 = u;
v1 = v2 = v;
if ( bIsUsingLightmap )
{
u1 = RemapVal( u1, 0.0f, 1.0f, flHalfLuxel, 0.25 - flHalfLuxel );
if ( bIsUsingBumpedLightmap )
{
u2 = 0.25f;
v2 = 0.0f;
}
}
meshBuilder.Position3fv( vecPos.Base() );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( red, green, blue, alpha );
meshBuilder.TexCoord2f( 0, u, v );
meshBuilder.TexCoord2f( 1, u1, v1 );
meshBuilder.TexCoord2f( 2, u2, v2 );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
}
}
//
// Emit the triangle strips.
//
int idx = 0;
for ( i = 0; i < nPhi - 1; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
idx = nTheta * i + j;
meshBuilder.FastIndex( idx );
meshBuilder.FastIndex( idx + nTheta );
}
//
// Emit a degenerate triangle to skip to the next row without
// a connecting triangle.
//
if ( i < nPhi - 2 )
{
meshBuilder.FastIndex( idx + 1 );
meshBuilder.FastIndex( idx + 1 + nTheta );
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Power of two FB texture
//-----------------------------------------------------------------------------
static CTextureReference s_pPowerOfTwoFrameBufferTexture;
static ITexture *GetPowerOfTwoFrameBufferTexture( void )
{
if( !s_pPowerOfTwoFrameBufferTexture )
{
s_pPowerOfTwoFrameBufferTexture.Init( materials->FindTexture( "_rt_PowerOfTwoFB", TEXTURE_GROUP_RENDER_TARGET ) );
}
return s_pPowerOfTwoFrameBufferTexture;
}
//-----------------------------------------------------------------------------
// paint it!
//-----------------------------------------------------------------------------
void CVMTPanel::OnPaint3D()
{
if (!m_pMaterial)
return;
// Deal with refraction
CMatRenderContextPtr pRenderContext( MaterialSystem() );
if ( m_pMaterial->NeedsPowerOfTwoFrameBufferTexture() )
{
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture();
if ( pTexture && !pTexture->IsError() )
{
pRenderContext->CopyRenderTargetToTexture( pTexture );
pRenderContext->SetFrameBufferCopyTexture( pTexture );
}
}
// Draw a background (translucent objects will appear that way)
// FIXME: Draw the outline of this panel?
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
RenderSphere( vec3_origin, SPHERE_RADIUS, 20, 20 );
/*
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->LoadIdentity();
pRenderContext->Ortho( 0, 0, m_iViewableWidth, m_iViewableHeight, 0, 1 );
pRenderContext->Bind( m_pMaterial );
IMesh *pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
if (!m_bUseActualSize)
{
DrawStretchedToPanel( meshBuilder );
}
else
{
DrawActualSize( meshBuilder );
}
meshBuilder.End();
pMesh->Draw();
*/
}

View File

@@ -0,0 +1,78 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "filesystem.h"
#include "matsys_controls/vmtpicker.h"
#include "matsys_controls/vmtpreviewpanel.h"
#include "vgui_controls/Splitter.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Asset Picker with no preview
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CVMTPicker::CVMTPicker( vgui::Panel *pParent, bool bAllowMultiselect ) :
BaseClass( pParent, "VMT Files", "vmt", "materials", "vmtName" )
{
// Horizontal splitter for preview
m_pPreviewSplitter = new Splitter( this, "PreviewSplitter", SPLITTER_MODE_VERTICAL, 1 );
vgui::Panel *pSplitterLeftSide = m_pPreviewSplitter->GetChild( 0 );
vgui::Panel *pSplitterRightSide = m_pPreviewSplitter->GetChild( 1 );
m_p2D3DSplitter = new Splitter( pSplitterRightSide, "2D3DSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
vgui::Panel *pSplitterTopSide = m_p2D3DSplitter->GetChild( 0 );
vgui::Panel *pSplitterBottomSide = m_p2D3DSplitter->GetChild( 1 );
// VMT preview
m_pVMTPreview2D = new CVMTPreviewPanel( pSplitterTopSide, "VMTPreview2D" );
m_pVMTPreview3D = new CVMTPreviewPanel( pSplitterBottomSide, "VMTPreview3D" );
m_pVMTPreview3D->DrawIn3DMode( true );
// Standard browser controls
CreateStandardControls( pSplitterLeftSide, bAllowMultiselect );
LoadControlSettingsAndUserConfig( "resource/vmtpicker.res" );
}
CVMTPicker::~CVMTPicker()
{
}
//-----------------------------------------------------------------------------
// Derived classes have this called when the previewed asset changes
//-----------------------------------------------------------------------------
void CVMTPicker::OnSelectedAssetPicked( const char *pAssetName )
{
m_pVMTPreview2D->SetVMT( pAssetName );
m_pVMTPreview3D->SetVMT( pAssetName );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CVMTPickerFrame::CVMTPickerFrame( vgui::Panel *pParent, const char *pTitle, bool bAllowMultiselect ) :
BaseClass( pParent )
{
SetAssetPicker( new CVMTPicker( this, bAllowMultiselect ) );
LoadControlSettingsAndUserConfig( "resource/vmtpickerframe.res" );
SetTitle( pTitle, false );
}

View File

@@ -0,0 +1,625 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/vmtpreviewpanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imesh.h"
#include "tier1/KeyValues.h"
using namespace vgui;
#define FOV 90.0f
#define ZNEAR 0.1f
#define ZFAR 2000.0f
#define ROTATION_SPEED 40.0f // degrees/sec
#define VIEW_DISTANCE 12.0f
//-----------------------------------------------------------------------------
//
// VMT Preview panel
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
CVMTPreviewPanel::CVMTPreviewPanel( vgui::Panel *pParent, const char *pName ) :
BaseClass( pParent, pName )
{
SetVMT( "//platform/materials/vgui/vtfnotloaded" );
m_pLightmapTexture.Init( "//platform/materials/debug/defaultlightmap", "editor" );
m_DefaultEnvCubemap.Init( "editor/cubemap", "editor", true );
m_LightDirection.Init( 0.0f, 1.0f, -1.0f );
m_LightColor.SetColor( 255, 255, 255, 255 );
m_flLightIntensity = 2.0f;
m_bDrawIn3DMode = false;
// Reset the camera direction
m_vecCameraDirection.Init( 1.0f, 0.0f, 0.0f );
m_flLastRotationTime = Plat_FloatTime();
}
//-----------------------------------------------------------------------------
// Sets the current VMT
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::SetVMT( const char *pMaterialName )
{
m_Material.Init( pMaterialName, "editor material" );
m_VMTName = pMaterialName;
}
//-----------------------------------------------------------------------------
// Gets the current VMT
//-----------------------------------------------------------------------------
const char *CVMTPreviewPanel::GetVMT() const
{
return m_VMTName;
}
//-----------------------------------------------------------------------------
// View it in 3D or 2D mode
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::DrawIn3DMode( bool b3DMode )
{
m_bDrawIn3DMode = b3DMode;
}
//-----------------------------------------------------------------------------
// Sets up lighting state
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::SetupLightingState()
{
LightDesc_t desc;
memset( &desc, 0, sizeof(desc) );
desc.m_Type = MATERIAL_LIGHT_DIRECTIONAL;
desc.m_Color[0] = m_LightColor.r();
desc.m_Color[1] = m_LightColor.g();
desc.m_Color[2] = m_LightColor.b();
desc.m_Color *= m_flLightIntensity / 255.0f;
desc.m_Attenuation0 = 1.0f;
desc.m_Attenuation1 = 0.0f;
desc.m_Attenuation2 = 0.0f;
desc.m_Flags = LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0;
desc.m_Direction = m_LightDirection;
VectorNormalize( desc.m_Direction );
desc.m_Theta = 0.0f;
desc.m_Phi = 0.0f;
desc.m_Falloff = 1.0f;
CMatRenderContextPtr pRenderContext( MaterialSystem() );
pRenderContext->SetLight( 0, desc );
}
//-----------------------------------------------------------------------------
// Draw a sphere
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi )
{
int nVertices = nTheta * nPhi;
int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
CMatRenderContextPtr pRenderContext( MaterialSystem() );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nVertices, nIndices );
bool bIsUsingLightmap = m_Material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP );
bool bIsUsingBumpedLightmap = m_Material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS );
int nLightmapWidth = m_pLightmapTexture->GetActualWidth();
float flHalfLuxel = 0.5f / nLightmapWidth;
//
// Build the index buffer.
//
int i, j;
for ( i = 0; i < nPhi; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
float u = j / ( float )(nTheta - 1);
float v = i / ( float )(nPhi - 1);
float theta = ( j != nTheta-1 ) ? 2.0f * M_PI * u : 0.0f;
float phi = M_PI * v;
Vector vecPos;
vecPos.x = flRadius * sin(phi) * cos(theta);
vecPos.y = flRadius * sin(phi) * sin(theta);
vecPos.z = flRadius * cos(phi);
Vector vecNormal = vecPos;
VectorNormalize( vecNormal );
Vector4D vecTangentS;
Vector vecTangentT;
vecTangentS.Init( vecPos.z, -vecPos.x, 0.0f, 1.0f );
if ( VectorNormalize( vecTangentS.AsVector3D() ) == 0.0f )
{
vecTangentS.Init( 1.0f, 0.0f, 0.0f, 1.0f );
}
CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
unsigned char red = (int)( u * 255.0f );
unsigned char green = (int)( v * 255.0f );
unsigned char blue = (int)( v * 255.0f );
unsigned char alpha = (int)( v * 255.0f );
vecPos += vCenter;
float u1, u2, v1, v2;
u1 = u2 = u;
v1 = v2 = v;
if ( bIsUsingLightmap )
{
u1 = RemapVal( u1, 0.0f, 1.0f, flHalfLuxel, 0.25 - flHalfLuxel );
if ( bIsUsingBumpedLightmap )
{
u2 = 0.25f;
v2 = 0.0f;
}
}
meshBuilder.Position3fv( vecPos.Base() );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( red, green, blue, alpha );
meshBuilder.TexCoord2f( 0, 2.0f * u, v );
meshBuilder.TexCoord2f( 1, u1, v1 );
meshBuilder.TexCoord2f( 2, u2, v2 );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
}
}
//
// Emit the triangle strips.
//
int idx = 0;
for ( i = 0; i < nPhi - 1; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
idx = nTheta * i + j;
meshBuilder.FastIndex( idx );
meshBuilder.FastIndex( idx + nTheta );
}
//
// Emit a degenerate triangle to skip to the next row without
// a connecting triangle.
//
if ( i < nPhi - 2 )
{
meshBuilder.FastIndex( idx + 1 );
meshBuilder.FastIndex( idx + 1 + nTheta );
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draw sprite-card based materials
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::RenderSpriteCard( const Vector &vCenter, float flRadius )
{
CMatRenderContextPtr pRenderContext( MaterialSystem() );
IMesh *pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
// Draw a polygon the size of the panel
meshBuilder.Position3fv( vCenter.Base() );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.TexCoord4f( 0, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 1, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 2, 0.0f, 0.0f, flRadius, 0.0f );
meshBuilder.TexCoord2f( 3, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vCenter.Base() );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.TexCoord4f( 0, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 1, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 2, 0.0f, 0.0f, flRadius, 0.0f );
meshBuilder.TexCoord2f( 3, 0, 1 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vCenter.Base() );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.TexCoord4f( 0, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 1, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 2, 0.0f, 0.0f, flRadius, 0.0f );
meshBuilder.TexCoord2f( 3, 1, 1 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( vCenter.Base() );
meshBuilder.Color4ub( 255, 255, 255, 255 );
meshBuilder.TexCoord4f( 0, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 1, 0.0f, 0.0f, 1.0f, 1.0f );
meshBuilder.TexCoord4f( 2, 0.0f, 0.0f, flRadius, 0.0f );
meshBuilder.TexCoord2f( 3, 1, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Paints a regular texture
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::DrawRectangle( void )
{
// Get the aspect ratio of the material
int tw = m_Material->GetMappingWidth();
int th = m_Material->GetMappingHeight();
if ( tw <= 0 || th <= 0 )
return;
int w, h;
GetSize( w, h );
if ( w == 0 || h == 0 )
return;
SetupOrthoMatrix( w, h );
SetupLightingState();
CMatRenderContextPtr pRenderContext( MaterialSystem() );
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->LoadIdentity();
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 4, 4 );
bool bIsUsingLightmap = m_Material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP );
bool bIsUsingBumpedLightmap = m_Material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS );
int nLightmapWidth = m_pLightmapTexture->GetActualWidth();
float flHalfLuxel = 0.5f / nLightmapWidth;
Vector2D halfTexel( 0.5f / tw, 0.5f / th );
Vector vecNormal( 0.0f, 0.0f, 1.0f );
Vector4D vecTangentS( 1.0f, 0.0f, 0.0f, 1.0f );
Vector vecTangentT;
CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
float screenaspect = (float)tw / (float)th;
float aspect = (float)w / (float)h;
float ratio = screenaspect / aspect;
// Screen is wider, need bars at top and bottom
int x2, y2;
int x, y;
x = y = 0;
int nXBorder = w > 15 ? 5 : w / 3;
int nYBorder = h > 15 ? 5 : h / 3;
w -= 2 * nXBorder;
h -= 2 * nYBorder;
if ( ratio > 1.0f )
{
int usetall = (float)w / screenaspect;
y = ( h - usetall ) / 2;
h = usetall;
}
// Screen is narrower, need bars at left/right
else
{
int usewide = (float)h * screenaspect;
x = ( w - usewide ) / 2;
w = usewide;
}
x += nXBorder;
y += nYBorder;
x2 = x+w; y2 = y+h;
float u = halfTexel.x;
float v = halfTexel.y;
float u1_l, u1_r, v1_t, v1_b;
float u2_l, u2_r, v2_t, v2_b;
u1_l = u2_l = u;
u1_r = u2_r = 1.0f - u;
v1_t = v2_t = v;
v1_b = v2_b = 1.0f - v;
if ( bIsUsingLightmap )
{
u1_l = v1_t = flHalfLuxel;
u1_r = v1_b = 0.25 - flHalfLuxel;
if ( bIsUsingBumpedLightmap )
{
u2_l = u2_r = 0.25f;
v2_t = v2_b = 0.0f;
}
}
meshBuilder.Position3f( x, y2, 0.0f );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( 255, 0, 0, 255 );
meshBuilder.TexCoord2f( 0, u, v );
meshBuilder.TexCoord2f( 1, u1_l, v1_t );
meshBuilder.TexCoord2f( 2, u2_l, v2_t );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x, y, 0.0f );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( 255, 255, 255, 64 );
meshBuilder.TexCoord2f( 0, u, 1.0f - v );
meshBuilder.TexCoord2f( 1, u1_l, v1_b );
meshBuilder.TexCoord2f( 2, u2_l, v2_b );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x2, y2, 0.0f );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( 0, 0, 255, 255 );
meshBuilder.TexCoord2f( 0, 1.0f - u, v );
meshBuilder.TexCoord2f( 1, u1_r, v1_t );
meshBuilder.TexCoord2f( 2, u2_r, v2_t );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x2, y, 0.0f );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( 0, 255, 0, 64 );
meshBuilder.TexCoord2f( 0, 1.0f - u, 1.0f - v );
meshBuilder.TexCoord2f( 1, u1_r, v1_b );
meshBuilder.TexCoord2f( 2, u2_r, v2_b );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
meshBuilder.FastIndex( 0 );
meshBuilder.FastIndex( 1 );
meshBuilder.FastIndex( 2 );
meshBuilder.FastIndex( 3 );
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Paints a cubemap texture
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::DrawSphere( void )
{
float flNewTime = Plat_FloatTime();
// Circle the camera around the origin
VMatrix rot;
MatrixBuildRotateZ( rot, ROTATION_SPEED * (flNewTime - m_flLastRotationTime ) );
Vector vecTemp;
Vector3DMultiply( rot, m_vecCameraDirection, vecTemp );
m_vecCameraDirection = vecTemp;
m_flLastRotationTime = flNewTime;
int w, h;
GetSize( w, h );
SetupProjectionMatrix( w, h );
SetupLightingState();
LookAt( vec3_origin, VIEW_DISTANCE );
// Draw a sphere at the origin
if ( !m_Material->IsSpriteCard() )
{
RenderSphere( vec3_origin, 10.0f, 20, 20 );
}
else
{
RenderSpriteCard( vec3_origin, 10.0f );
}
}
//-----------------------------------------------------------------------------
// Sets the camera to look at the the thing we're spinning around
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::LookAt( const Vector &vecLookAt, float flRadius )
{
// Compute the distance to the camera for the object based on its
// radius and fov.
// since tan( fov/2 ) = f/d
// cos( fov/2 ) = r / r' where r = sphere radius, r' = perp distance from sphere center to max extent of camera
// d/f = r'/d' where d' is distance of camera to sphere
// d' = r' / tan( fov/2 ) * r' = r / ( cos (fov/2) * tan( fov/2 ) ) = r / sin( fov/2 )
float flFOVx = FOV;
// Compute fov/2 in radians
flFOVx *= M_PI / 360.0f;
// Compute an effective fov based on the aspect ratio
// if the height is smaller than the width
int w, h;
GetSize( w, h );
if ( h < w )
{
flFOVx = atan( h * tan( flFOVx ) / w );
}
float flDistance = flRadius / sin( flFOVx );
Vector vecMDLOrigin = vecLookAt;
Vector vecCameraOrigin;
VectorMA( vecMDLOrigin, -flDistance, m_vecCameraDirection, vecCameraOrigin );
CMatRenderContextPtr pRenderContext( MaterialSystem() );
QAngle angles;
VectorAngles( m_vecCameraDirection, angles );
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->LoadIdentity();
// convert from a right handed system to a left handed system
// since dx for wants it that way.
// pRenderContext->Scale( 1.0f, 1.0f, -1.0f );
pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
pRenderContext->Rotate( 90, 0, 0, 1 ); // put Z going up
pRenderContext->Rotate( -angles[2], 1, 0, 0 );
pRenderContext->Rotate( -angles[0], 0, 1, 0 );
pRenderContext->Rotate( -angles[1], 0, 0, 1 );
pRenderContext->Translate( -vecCameraOrigin[0], -vecCameraOrigin[1], -vecCameraOrigin[2] );
}
//-----------------------------------------------------------------------------
// Set up a projection matrix for a 90 degree fov
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::SetupProjectionMatrix( int nWidth, int nHeight )
{
VMatrix proj;
float flFOV = FOV;
float flZNear = ZNEAR;
float flZFar = ZFAR;
float flApsectRatio = (nHeight != 0.0f) ? (float)nWidth / (float)nHeight : 100.0f;
float halfWidth = tan( flFOV * M_PI / 360.0 );
float halfHeight = halfWidth / flApsectRatio;
memset( proj.Base(), 0, sizeof( proj ) );
proj[0][0] = 1.0f / halfWidth;
proj[1][1] = 1.0f / halfHeight;
proj[2][2] = flZFar / ( flZNear - flZFar );
proj[3][2] = -1.0f;
proj[2][3] = flZNear * flZFar / ( flZNear - flZFar );
CMatRenderContextPtr pRenderContext( MaterialSystem() );
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->LoadMatrix( proj );
}
//-----------------------------------------------------------------------------
// Set up a orthographic projection matrix
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::SetupOrthoMatrix( int nWidth, int nHeight )
{
CMatRenderContextPtr pRenderContext( MaterialSystem() );
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->LoadIdentity();
pRenderContext->Ortho( 0, 0, nWidth, nHeight, -1.0f, 1.0f );
}
//-----------------------------------------------------------------------------
// Power of two FB texture
//-----------------------------------------------------------------------------
static CTextureReference s_pPowerOfTwoFrameBufferTexture;
static ITexture *GetPowerOfTwoFrameBufferTexture( void )
{
if( !s_pPowerOfTwoFrameBufferTexture )
{
s_pPowerOfTwoFrameBufferTexture.Init( vgui::MaterialSystem()->FindTexture( "_rt_PowerOfTwoFB", TEXTURE_GROUP_RENDER_TARGET ) );
}
return s_pPowerOfTwoFrameBufferTexture;
}
//-----------------------------------------------------------------------------
// Paints the texture
//-----------------------------------------------------------------------------
void CVMTPreviewPanel::Paint( void )
{
CMatRenderContextPtr pRenderContext( MaterialSystem() );
int w, h;
GetSize( w, h );
vgui::MatSystemSurface()->Begin3DPaint( 0, 0, w, h );
// Deal with refraction
if ( m_Material->NeedsPowerOfTwoFrameBufferTexture() )
{
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture();
if ( pTexture && !pTexture->IsError() )
{
pRenderContext->CopyRenderTargetToTexture( pTexture );
pRenderContext->SetFrameBufferCopyTexture( pTexture );
}
}
pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
pRenderContext->ClearBuffers( true, true );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->Bind( m_Material );
pRenderContext->BindLightmapTexture( m_pLightmapTexture );
pRenderContext->BindLocalCubemap( m_DefaultEnvCubemap );
if ( m_bDrawIn3DMode || m_Material->IsSpriteCard() )
{
DrawSphere();
}
else
{
DrawRectangle();
}
vgui::MatSystemSurface()->End3DPaint( );
}

View File

@@ -0,0 +1,71 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "filesystem.h"
#include "matsys_controls/vtfpicker.h"
#include "matsys_controls/vtfpreviewpanel.h"
#include "vgui_controls/Splitter.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Asset Picker with no preview
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CVTFPicker::CVTFPicker( vgui::Panel *pParent ) :
BaseClass( pParent, "VTF Files", "vtf", "materials", "vtfName" )
{
// Horizontal splitter for preview
m_pPreviewSplitter = new Splitter( this, "PreviewSplitter", SPLITTER_MODE_VERTICAL, 1 );
vgui::Panel *pSplitterLeftSide = m_pPreviewSplitter->GetChild( 0 );
vgui::Panel *pSplitterRightSide = m_pPreviewSplitter->GetChild( 1 );
// VTF preview
m_pVTFPreview = new CVTFPreviewPanel( pSplitterRightSide, "VTFPreview" );
// Standard browser controls
CreateStandardControls( pSplitterLeftSide );
LoadControlSettingsAndUserConfig( "resource/vtfpicker.res" );
}
CVTFPicker::~CVTFPicker()
{
}
//-----------------------------------------------------------------------------
// Derived classes have this called when the previewed asset changes
//-----------------------------------------------------------------------------
void CVTFPicker::OnSelectedAssetPicked( const char *pAssetName )
{
m_pVTFPreview->SetVTF( pAssetName );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CVTFPickerFrame::CVTFPickerFrame( vgui::Panel *pParent, const char *pTitle ) :
BaseClass( pParent )
{
SetAssetPicker( new CVTFPicker( this ) );
LoadControlSettingsAndUserConfig( "resource/vtfpickerframe.res" );
SetTitle( pTitle, false );
}

View File

@@ -0,0 +1,398 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/vtfpreviewpanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imesh.h"
#include "tier1/KeyValues.h"
using namespace vgui;
#define FOV 90.0f
#define ZNEAR 0.1f
#define ZFAR 2000.0f
#define ROTATION_SPEED 120.0f // degrees/sec
//-----------------------------------------------------------------------------
//
// VTF Preview panel
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
CVTFPreviewPanel::CVTFPreviewPanel( vgui::Panel *pParent, const char *pName ) :
BaseClass( pParent, pName )
{
SetVTF( "//platform/materials/vgui/vtfnotloaded", true );
m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
}
CVTFPreviewPanel::~CVTFPreviewPanel()
{
if ( vgui::surface() && m_nTextureID != -1 )
{
vgui::surface()->DestroyTextureID( m_nTextureID );
m_nTextureID = -1;
}
}
//-----------------------------------------------------------------------------
// Sets the current VTF
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::SetVTF( const char *pFullPath, bool bLoadImmediately )
{
m_PreviewTexture.Init( pFullPath, "editor texture" );
m_VTFName = pFullPath;
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
if ( m_PreviewTexture->IsCubeMap() )
{
pVMTKeyValues->SetString( "$envmap", pFullPath );
}
else if ( m_PreviewTexture->IsNormalMap() )
{
pVMTKeyValues->SetString( "$bumpmap", pFullPath );
}
else
{
pVMTKeyValues->SetString( "$basetexture", pFullPath );
}
pVMTKeyValues->SetInt( "$nocull", 1 );
pVMTKeyValues->SetInt( "$nodebug", 1 );
m_PreviewMaterial.Init( MaterialSystem()->CreateMaterial( pFullPath, pVMTKeyValues ));
MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_PreviewMaterial );
// Reset the camera direction
m_vecCameraDirection.Init( 1.0f, 0.0f, 0.0f );
m_flLastRotationTime = Plat_FloatTime();
}
//-----------------------------------------------------------------------------
// Gets the current VTF
//-----------------------------------------------------------------------------
const char *CVTFPreviewPanel::GetVTF() const
{
return m_VTFName;
}
//-----------------------------------------------------------------------------
// Draw a sphere
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi )
{
CMatRenderContextPtr pRenderContext( MaterialSystem() );
int nVertices = nTheta * nPhi;
int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->Bind( m_PreviewMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nVertices, nIndices );
//
// Build the index buffer.
//
int i, j;
for ( i = 0; i < nPhi; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
float u = j / ( float )(nTheta - 1);
float v = i / ( float )(nPhi - 1);
float theta = ( j != nTheta-1 ) ? 2.0f * M_PI * u : 0.0f;
float phi = M_PI * v;
Vector vecPos;
vecPos.x = flRadius * sin(phi) * cos(theta);
vecPos.y = flRadius * cos(phi);
vecPos.z = -flRadius * sin(phi) * sin(theta);
Vector vecNormal = vecPos;
VectorNormalize( vecNormal );
Vector4D vecTangentS;
Vector vecTangentT;
vecTangentS.Init( vecPos.z, -vecPos.x, 0.0f, 1.0f );
if ( VectorNormalize( vecTangentS.AsVector3D() ) == 0.0f )
{
vecTangentS.Init( 1.0f, 0.0f, 0.0f, 1.0f );
}
CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
unsigned char red = (int)( u * 255.0f );
unsigned char green = (int)( v * 255.0f );
unsigned char blue = (int)( v * 255.0f );
unsigned char alpha = (int)( v * 255.0f );
vecPos += vCenter;
float u1, u2, v1, v2;
u1 = u2 = u;
v1 = v2 = v;
meshBuilder.Position3fv( vecPos.Base() );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.Color4ub( red, green, blue, alpha );
meshBuilder.TexCoord2f( 0, u, v );
meshBuilder.TexCoord2f( 1, u1, v1 );
meshBuilder.TexCoord2f( 2, u2, v2 );
meshBuilder.TangentS3fv( vecTangentS.Base() );
meshBuilder.TangentT3fv( vecTangentT.Base() );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.UserData( vecTangentS.Base() );
meshBuilder.AdvanceVertex();
}
}
//
// Emit the triangle strips.
//
int idx = 0;
for ( i = 0; i < nPhi - 1; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
idx = nTheta * i + j;
meshBuilder.FastIndex( idx );
meshBuilder.FastIndex( idx + nTheta );
}
//
// Emit a degenerate triangle to skip to the next row without
// a connecting triangle.
//
if ( i < nPhi - 2 )
{
meshBuilder.FastIndex( idx + 1 );
meshBuilder.FastIndex( idx + 1 + nTheta );
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Paints a regular texture
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::PaintStandardTexture( void )
{
int x, y, w, h;
x = y = 0;
GetSize( w, h );
vgui::surface()->DrawSetTexture( m_nTextureID );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
// Get the aspect ratio of the texture
int tw = m_PreviewTexture->GetActualWidth();
int th = m_PreviewTexture->GetActualHeight();
if ( th > 0 && h > 0 )
{
float screenaspect = (float)tw / (float)th;
float aspect = (float)w / (float)h;
float ratio = screenaspect / aspect;
// Screen is wider, need bars at top and bottom
if ( ratio > 1.0f )
{
int usetall = (float)w / screenaspect;
y = ( h - usetall ) / 2;
h = usetall;
}
// Screen is narrower, need bars at left/right
else
{
int usewide = (float)h * screenaspect;
x = ( w - usewide ) / 2;
w = usewide;
}
}
vgui::surface()->DrawTexturedRect( x, y, x+w, y+h );
}
//-----------------------------------------------------------------------------
// Paints a normalmap texture
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::PaintNormalMapTexture( void )
{
}
//-----------------------------------------------------------------------------
// Paints a volume texture
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::PaintVolumeTexture( void )
{
}
//-----------------------------------------------------------------------------
// Paints a cubemap texture
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::PaintCubeTexture( void )
{
float flNewTime = Plat_FloatTime();
// Circle the camera around the origin
VMatrix rot;
MatrixBuildRotateZ( rot, ROTATION_SPEED * (flNewTime - m_flLastRotationTime ) );
Vector vecTemp;
Vector3DMultiply( rot, m_vecCameraDirection, vecTemp );
m_vecCameraDirection = vecTemp;
m_flLastRotationTime = flNewTime;
LookAt( vec3_origin, 12.0f );
// Draw a sphere at the origin
RenderSphere( vec3_origin, 10.0f, 20, 20 );
}
//-----------------------------------------------------------------------------
// Sets the camera to look at the the thing we're spinning around
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::LookAt( const Vector &vecLookAt, float flRadius )
{
// Compute the distance to the camera for the object based on its
// radius and fov.
// since tan( fov/2 ) = f/d
// cos( fov/2 ) = r / r' where r = sphere radius, r' = perp distance from sphere center to max extent of camera
// d/f = r'/d' where d' is distance of camera to sphere
// d' = r' / tan( fov/2 ) * r' = r / ( cos (fov/2) * tan( fov/2 ) ) = r / sin( fov/2 )
float flFOVx = FOV;
// Compute fov/2 in radians
flFOVx *= M_PI / 360.0f;
// Compute an effective fov based on the aspect ratio
// if the height is smaller than the width
int w, h;
GetSize( w, h );
if ( h < w )
{
flFOVx = atan( h * tan( flFOVx ) / w );
}
float flDistance = flRadius / sin( flFOVx );
Vector vecMDLOrigin = vecLookAt;
Vector vecCameraOrigin;
VectorMA( vecMDLOrigin, -flDistance, m_vecCameraDirection, vecCameraOrigin );
CMatRenderContextPtr pRenderContext( MaterialSystem() );
QAngle angles;
VectorAngles( m_vecCameraDirection, angles );
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->LoadIdentity();
// convert from a right handed system to a left handed system
// since dx for wants it that way.
// pRenderContext->Scale( 1.0f, 1.0f, -1.0f );
pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
pRenderContext->Rotate( 90, 0, 0, 1 ); // put Z going up
pRenderContext->Rotate( -angles[2], 1, 0, 0 );
pRenderContext->Rotate( -angles[0], 0, 1, 0 );
pRenderContext->Rotate( -angles[1], 0, 0, 1 );
pRenderContext->Translate( -vecCameraOrigin[0], -vecCameraOrigin[1], -vecCameraOrigin[2] );
}
//-----------------------------------------------------------------------------
// Set up a projection matrix for a 90 degree fov
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::SetupProjectionMatrix( int nWidth, int nHeight )
{
CMatRenderContextPtr pRenderContext( MaterialSystem() );
VMatrix proj;
float flFOV = FOV;
float flZNear = ZNEAR;
float flZFar = ZFAR;
float flApsectRatio = (nHeight != 0.0f) ? (float)nWidth / (float)nHeight : 100.0f;
#if 1
float halfWidth = tan( flFOV * M_PI / 360.0 );
float halfHeight = halfWidth / flApsectRatio;
#else
float halfHeight = tan( flFOV * M_PI / 360.0 );
float halfWidth = flApsectRatio * halfHeight;
#endif
memset( proj.Base(), 0, sizeof( proj ) );
proj[0][0] = 1.0f / halfWidth;
proj[1][1] = 1.0f / halfHeight;
proj[2][2] = flZFar / ( flZNear - flZFar );
proj[3][2] = -1.0f;
proj[2][3] = flZNear * flZFar / ( flZNear - flZFar );
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->LoadMatrix( proj );
}
//-----------------------------------------------------------------------------
// Paints the texture
//-----------------------------------------------------------------------------
void CVTFPreviewPanel::Paint( void )
{
if ( !m_PreviewTexture->IsCubeMap() && /*!m_PreviewTexture->IsNormalMap() &&*/ !m_PreviewTexture->IsVolumeTexture() )
{
PaintStandardTexture();
return;
}
CMatRenderContextPtr pRenderContext( MaterialSystem() );
int w, h;
GetSize( w, h );
vgui::MatSystemSurface()->Begin3DPaint( 0, 0, w, h );
pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
pRenderContext->ClearBuffers( true, true );
SetupProjectionMatrix( w, h );
if ( m_PreviewTexture->IsCubeMap() )
{
PaintCubeTexture();
}
else if ( m_PreviewTexture->IsNormalMap() )
{
PaintNormalMapTexture();
}
else if ( m_PreviewTexture->IsVolumeTexture() )
{
PaintVolumeTexture();
}
vgui::MatSystemSurface()->End3DPaint( );
}