You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
539 lines
16 KiB
539 lines
16 KiB
//========= 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(); |
|
} |
|
|
|
|
|
|