summaryrefslogtreecommitdiff
path: root/vgui2/dme_controls/soundpicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vgui2/dme_controls/soundpicker.cpp')
-rw-r--r--vgui2/dme_controls/soundpicker.cpp602
1 files changed, 602 insertions, 0 deletions
diff --git a/vgui2/dme_controls/soundpicker.cpp b/vgui2/dme_controls/soundpicker.cpp
new file mode 100644
index 0000000..19dc478
--- /dev/null
+++ b/vgui2/dme_controls/soundpicker.cpp
@@ -0,0 +1,602 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include <windows.h>
+#undef PropertySheet
+
+#include "filesystem.h"
+#include "dme_controls/soundpicker.h"
+#include "tier1/KeyValues.h"
+#include "vgui_controls/ListPanel.h"
+#include "vgui_controls/Button.h"
+#include "vgui_controls/PropertySheet.h"
+#include "vgui_controls/PropertyPage.h"
+#include "dme_controls/filtercombobox.h"
+#include "vgui/ISurface.h"
+#include "vgui/iinput.h"
+#include "dme_controls/dmecontrols.h"
+#include "soundemittersystem/isoundemittersystembase.h"
+#include "mathlib/mathlib.h"
+
+// FIXME: Move sound code out of the engine + into a library!
+#include "toolframework/ienginetool.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+using namespace vgui;
+
+
+//-----------------------------------------------------------------------------
+//
+// Sound Picker
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Sort by sound name
+//-----------------------------------------------------------------------------
+static int __cdecl GameSoundSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ bool bRoot1 = item1.kv->GetInt("root") != 0;
+ bool bRoot2 = item2.kv->GetInt("root") != 0;
+ if ( bRoot1 != bRoot2 )
+ return bRoot1 ? -1 : 1;
+ const char *string1 = item1.kv->GetString("gamesound");
+ const char *string2 = item2.kv->GetString("gamesound");
+ return Q_stricmp( string1, string2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CSoundPicker::CSoundPicker( vgui::Panel *pParent, int nFlags ) :
+ BaseClass( pParent, "Sound Files", "wav", "sound", "wavName" )
+{
+ m_nSoundSuppressionCount = 0;
+ m_nPlayingSound = 0;
+
+ // Connection problem if this failed
+ Assert( SoundEmitterSystem() );
+
+ m_pViewsSheet = new vgui::PropertySheet( this, "ViewsSheet" );
+ m_pViewsSheet->AddActionSignalTarget( this );
+
+ // game sounds
+ m_pGameSoundPage = NULL;
+ m_pGameSoundList = NULL;
+ if ( nFlags & PICK_GAMESOUNDS )
+ {
+ m_pGameSoundPage = new PropertyPage( m_pViewsSheet, "GameSoundPage" );
+ m_pGameSoundList = new ListPanel( m_pGameSoundPage, "GameSoundsList" );
+ m_pGameSoundList->AddColumnHeader( 0, "GameSound", "Game Sound", 52, 0 );
+ m_pGameSoundList->AddActionSignalTarget( this );
+ m_pGameSoundList->SetSelectIndividualCells( true );
+ m_pGameSoundList->SetEmptyListText("No game sounds");
+ m_pGameSoundList->SetDragEnabled( true );
+ m_pGameSoundList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
+ m_pGameSoundList->SetSortFunc( 0, GameSoundSortFunc );
+ m_pGameSoundList->SetSortColumn( 0 );
+ m_pGameSoundList->SetMultiselectEnabled( ( nFlags & ALLOW_MULTISELECT ) != 0 );
+
+ // filter selection
+ m_pGameSoundFilter = new TextEntry( m_pGameSoundPage, "GameSoundFilter" );
+ m_pGameSoundFilter->AddActionSignalTarget( this );
+
+ m_pGameSoundPage->LoadControlSettings( "resource/soundpickergamesoundpage.res" );
+
+ m_pViewsSheet->AddPage( m_pGameSoundPage, "Game Sounds" );
+ }
+
+ // wav files
+ m_pWavPage = NULL;
+ if ( nFlags & PICK_WAVFILES )
+ {
+ m_pWavPage = new PropertyPage( m_pViewsSheet, "WavPage" );
+ bool bAllowMultiselect = ( nFlags & ALLOW_MULTISELECT ) != 0;
+ CreateStandardControls( m_pWavPage, bAllowMultiselect );
+ AddExtension( "mp3" );
+
+ m_pWavPage->LoadControlSettings( "resource/soundpickerwavpage.res" );
+ m_pViewsSheet->AddPage( m_pWavPage, "WAVs" );
+ }
+
+ LoadControlSettings( "resource/soundpicker.res" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CSoundPicker::~CSoundPicker()
+{
+ StopSoundPreview();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: called to open
+//-----------------------------------------------------------------------------
+void CSoundPicker::Activate()
+{
+ BaseClass::Activate();
+ if ( m_pGameSoundPage )
+ {
+ BuildGameSoundList();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the current sound choice
+//-----------------------------------------------------------------------------
+void CSoundPicker::SetSelectedSound( PickType_t type, const char *pSoundName )
+{
+ if ( type == PICK_NONE || !pSoundName )
+ return;
+
+ if ( m_pGameSoundPage && ( type == PICK_GAMESOUNDS ) )
+ {
+ m_pViewsSheet->SetActivePage( m_pGameSoundPage );
+ m_pGameSoundFilter->SetText( pSoundName );
+ }
+
+ if ( m_pWavPage && ( type == PICK_WAVFILES ) )
+ {
+ m_pViewsSheet->SetActivePage( m_pWavPage );
+ SetInitialSelection( pSoundName );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnKeyCodePressed( KeyCode code )
+{
+ if ( m_pGameSoundPage && ( m_pViewsSheet->GetActivePage() == m_pGameSoundPage ) )
+ {
+ if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
+ {
+ KeyValues *pMsg = new KeyValues( "KeyCodePressed", "code", code );
+ vgui::ipanel()->SendMessage( m_pGameSoundList->GetVPanel(), pMsg, GetVPanel() );
+ pMsg->deleteThis();
+ return;
+ }
+ }
+
+ BaseClass::OnKeyCodePressed( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: builds the gamesound list
+//-----------------------------------------------------------------------------
+bool CSoundPicker::IsGameSoundVisible( int hGameSound )
+{
+ const char *pSoundName = SoundEmitterSystem()->GetSoundName( hGameSound );
+ return ( !m_GameSoundFilter.Length() || Q_stristr( pSoundName, m_GameSoundFilter.Get() ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Updates the column header in the chooser
+//-----------------------------------------------------------------------------
+void CSoundPicker::UpdateGameSoundColumnHeader( int nMatchCount, int nTotalCount )
+{
+ char pColumnTitle[512];
+ Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
+ "Game Sound", nMatchCount, nTotalCount );
+ m_pGameSoundList->SetColumnHeaderText( 0, pColumnTitle );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: builds the gamesound list
+//-----------------------------------------------------------------------------
+void CSoundPicker::BuildGameSoundList()
+{
+ if ( !m_pGameSoundList )
+ return;
+
+ m_pGameSoundList->RemoveAll();
+
+ int nTotalCount = 0;
+ int i = SoundEmitterSystem()->First();
+ while ( i != SoundEmitterSystem()->InvalidIndex() )
+ {
+ const char *pSoundName = SoundEmitterSystem()->GetSoundName( i );
+
+ bool bInRoot = !strchr( pSoundName, '\\' ) && !strchr( pSoundName, '/' );
+ KeyValues *kv = new KeyValues( "node", "gamesound", pSoundName );
+ kv->SetInt( "gameSoundHandle", i );
+ kv->SetInt( "root", bInRoot );
+
+ int nItemID = m_pGameSoundList->AddItem( kv, 0, false, false );
+ m_pGameSoundList->SetItemVisible( nItemID, IsGameSoundVisible( i ) );
+ KeyValues *pDrag = new KeyValues( "drag", "text", pSoundName );
+ pDrag->SetString( "texttype", "gamesoundName" );
+ m_pGameSoundList->SetItemDragData( nItemID, pDrag );
+ ++nTotalCount;
+
+ i = SoundEmitterSystem()->Next( i );
+ }
+
+ m_pGameSoundList->SortList();
+ if ( m_pGameSoundList->GetItemCount() > 0 )
+ {
+ int nItemID = m_pGameSoundList->GetItemIDFromRow( 0 );
+
+ // This prevents the refreshing of the sound list from playing the sound
+ ++m_nSoundSuppressionCount;
+ m_pGameSoundList->SetSelectedCell( nItemID, 0 );
+ }
+
+ UpdateGameSoundColumnHeader( nTotalCount, nTotalCount );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: refreshes the gamesound list
+//-----------------------------------------------------------------------------
+void CSoundPicker::RefreshGameSoundList()
+{
+ if ( !m_pGameSoundList )
+ return;
+
+ // Check the filter matches
+ int nMatchingGameSounds = 0;
+ int nTotalCount = 0;
+ for ( int nItemID = m_pGameSoundList->FirstItem(); nItemID != m_pGameSoundList->InvalidItemID(); nItemID = m_pGameSoundList->NextItem( nItemID ) )
+ {
+ KeyValues *kv = m_pGameSoundList->GetItem( nItemID );
+ int hGameSound = kv->GetInt( "gameSoundHandle", SoundEmitterSystem()->InvalidIndex() );
+ if ( hGameSound == SoundEmitterSystem()->InvalidIndex() )
+ continue;
+ bool bIsVisible = IsGameSoundVisible( hGameSound );
+ m_pGameSoundList->SetItemVisible( nItemID, bIsVisible );
+ if ( bIsVisible )
+ {
+ ++nMatchingGameSounds;
+ }
+ ++nTotalCount;
+ }
+
+ UpdateGameSoundColumnHeader( nMatchingGameSounds, nTotalCount );
+
+ if ( ( m_pGameSoundList->GetSelectedItemsCount() == 0 ) && ( m_pGameSoundList->GetItemCount() > 0 ) )
+ {
+ int nItemID = m_pGameSoundList->GetItemIDFromRow( 0 );
+ // This prevents the refreshing of the sound list from playing the sound
+ ++m_nSoundSuppressionCount;
+ m_pGameSoundList->SetSelectedCell( nItemID, 0 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Update filter when text changes
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnGameSoundFilterTextChanged( )
+{
+ int nLength = m_pGameSoundFilter->GetTextLength();
+ m_GameSoundFilter.SetLength( nLength );
+ if ( nLength > 0 )
+ {
+ m_pGameSoundFilter->GetText( m_GameSoundFilter.GetForModify(), nLength+1 );
+ }
+ RefreshGameSoundList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: refreshes dialog on filter changing
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnTextChanged( KeyValues *pKeyValues )
+{
+ vgui::Panel *pSource = (vgui::Panel*)pKeyValues->GetPtr( "panel" );
+ if ( pSource == m_pGameSoundFilter )
+ {
+ OnGameSoundFilterTextChanged();
+ return;
+ }
+
+ BaseClass::OnTextChanged( pKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when a page is shown
+//-----------------------------------------------------------------------------
+void CSoundPicker::RequestGameSoundFilterFocus( )
+{
+ m_pGameSoundFilter->SelectAllOnFirstFocus( true );
+ m_pGameSoundFilter->RequestFocus();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when a page is shown
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnPageChanged( )
+{
+ StopSoundPreview();
+ if ( m_pGameSoundPage && ( m_pViewsSheet->GetActivePage() == m_pGameSoundPage ) )
+ {
+ RequestGameSoundFilterFocus();
+ }
+ if ( m_pWavPage && ( m_pViewsSheet->GetActivePage() == m_pWavPage ) )
+ {
+ RequestFilterFocus();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Stop sound preview
+//-----------------------------------------------------------------------------
+void CSoundPicker::StopSoundPreview( )
+{
+ if ( m_nPlayingSound != 0 )
+ {
+ EngineTool()->StopSoundByGuid( m_nPlayingSound );
+ m_nPlayingSound = 0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Plays a gamesound
+//-----------------------------------------------------------------------------
+void CSoundPicker::PlayGameSound( const char *pSoundName )
+{
+ StopSoundPreview();
+
+ CSoundParameters params;
+ if ( SoundEmitterSystem()->GetParametersForSound( pSoundName, params, GENDER_NONE ) )
+ {
+ m_nPlayingSound = EngineTool()->StartSound( 0, true, -1, CHAN_STATIC, params.soundname,
+ params.volume, params.soundlevel, vec3_origin, vec3_origin, 0,
+ params.pitch, false, params.delay_msec / 1000.0f );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Plays a wav file
+//-----------------------------------------------------------------------------
+void CSoundPicker::PlayWavSound( const char *pSoundName )
+{
+ StopSoundPreview();
+ m_nPlayingSound = EngineTool()->StartSound( 0, true, -1, CHAN_STATIC, pSoundName,
+ VOL_NORM, SNDLVL_NONE, vec3_origin, vec3_origin, 0, PITCH_NORM, false, 0 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Don't play a sound when the next selection is a default selection
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnNextSelectionIsDefault()
+{
+ ++m_nSoundSuppressionCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Derived classes have this called when the previewed asset changes
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnSelectedAssetPicked( const char *pAssetName )
+{
+ bool bPlaySounds = true;
+ if ( m_nSoundSuppressionCount > 0 )
+ {
+ --m_nSoundSuppressionCount;
+ bPlaySounds = false;
+ }
+
+ if ( pAssetName && bPlaySounds )
+ {
+ PlayWavSound( pAssetName );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: refreshes dialog on text changing
+//-----------------------------------------------------------------------------
+void CSoundPicker::OnItemSelected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( m_pGameSoundList && (pPanel == m_pGameSoundList ) )
+ {
+ bool bPlaySounds = true;
+ if ( m_nSoundSuppressionCount > 0 )
+ {
+ --m_nSoundSuppressionCount;
+ bPlaySounds = false;
+ }
+
+ const char *pGameSoundName = GetSelectedSoundName();
+ if ( pGameSoundName && bPlaySounds )
+ {
+ int len = V_strlen( pGameSoundName );
+ char *soundname = ( char* )stackalloc( len + 2 );
+ soundname[ 0 ] = '#'; // mark sound to bypass the dsp
+ V_strncpy( soundname + 1, pGameSoundName, len + 1 );
+
+ PlayGameSound( soundname );
+ }
+ return;
+ }
+
+ BaseClass::OnItemSelected( kv );
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the selected sound type
+//-----------------------------------------------------------------------------
+CSoundPicker::PickType_t CSoundPicker::GetSelectedSoundType( )
+{
+ if ( m_pGameSoundPage && ( m_pViewsSheet->GetActivePage() == m_pGameSoundPage ) )
+ return PICK_GAMESOUNDS;
+ if ( m_pWavPage && ( m_pViewsSheet->GetActivePage() == m_pWavPage ) )
+ return PICK_WAVFILES;
+ return PICK_NONE;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the selected sound count
+//-----------------------------------------------------------------------------
+int CSoundPicker::GetSelectedSoundCount()
+{
+ if ( m_pGameSoundPage && ( m_pViewsSheet->GetActivePage() == m_pGameSoundPage ) )
+ return m_pGameSoundList->GetSelectedItemsCount();
+
+ if ( m_pWavPage && ( m_pViewsSheet->GetActivePage() == m_pWavPage ) )
+ return GetSelectedAssetCount();
+
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the selected sound
+//-----------------------------------------------------------------------------
+const char *CSoundPicker::GetSelectedSoundName( int nSelectionIndex )
+{
+ if ( m_pGameSoundPage && ( m_pViewsSheet->GetActivePage() == m_pGameSoundPage ) )
+ {
+ int nCount = m_pGameSoundList->GetSelectedItemsCount();
+ if ( nCount == 0 )
+ return NULL;
+
+ if ( nSelectionIndex < 0 )
+ {
+ nSelectionIndex = nCount - 1;
+ }
+ int nIndex = m_pGameSoundList->GetSelectedItem( nSelectionIndex );
+ if ( nIndex >= 0 )
+ {
+ KeyValues *pkv = m_pGameSoundList->GetItem( nIndex );
+ return pkv->GetString( "gamesound", NULL );
+ }
+ return NULL;
+ }
+
+ if ( m_pWavPage && ( m_pViewsSheet->GetActivePage() == m_pWavPage ) )
+ return GetSelectedAsset( nSelectionIndex );
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Modal picker frame
+//
+//-----------------------------------------------------------------------------
+CSoundPickerFrame::CSoundPickerFrame( vgui::Panel *pParent, const char *pTitle, int nFlags ) :
+ BaseClass( pParent )
+{
+ SetAssetPicker( new CSoundPicker( this, nFlags ) );
+ LoadControlSettingsAndUserConfig( "resource/soundpickerframe.res" );
+ SetTitle( pTitle, false );
+}
+
+CSoundPickerFrame::~CSoundPickerFrame()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Activate the dialog
+//-----------------------------------------------------------------------------
+void CSoundPickerFrame::DoModal( CSoundPicker::PickType_t initialType, const char *pInitialValue, KeyValues *pContextKeyValues )
+{
+ vgui::surface()->SetCursor( dc_hourglass );
+ CSoundPicker *pPicker = static_cast <CSoundPicker*>( GetAssetPicker() );
+ if ( initialType != CSoundPicker::PICK_NONE && pInitialValue )
+ {
+ pPicker->SetSelectedSound( initialType, pInitialValue );
+ }
+ BaseClass::DoModal( pContextKeyValues );
+}
+
+
+//-----------------------------------------------------------------------------
+// On command
+//-----------------------------------------------------------------------------
+void CSoundPickerFrame::OnCommand( const char *pCommand )
+{
+ CSoundPicker *pPicker = static_cast <CSoundPicker*>( GetAssetPicker() );
+ if ( !Q_stricmp( pCommand, "Open" ) )
+ {
+ CSoundPicker::PickType_t type = pPicker->GetSelectedSoundType( );
+ if (( type == CSoundPicker::PICK_GAMESOUNDS ) || ( type == CSoundPicker::PICK_WAVFILES ))
+ {
+ const char *pSoundName = pPicker->GetSelectedSoundName();
+
+ int len = V_strlen( pSoundName );
+ char *soundname = ( char* )stackalloc( len + 2 );
+ soundname[ 0 ] = '#'; // mark sound to bypass the dsp
+ V_strncpy( soundname + 1, pSoundName, len + 1 );
+
+ int nSoundCount = pPicker->GetSelectedSoundCount();
+
+ KeyValues *pActionKeys = new KeyValues( "SoundSelected" );
+ pActionKeys->SetInt( "count", nSoundCount );
+ KeyValues *pSoundList = NULL;
+ if ( type == CSoundPicker::PICK_GAMESOUNDS )
+ {
+ pActionKeys->SetString( "gamesound", soundname );
+ if ( pPicker->IsMultiselectEnabled() )
+ {
+ pSoundList = pActionKeys->FindKey( "gamesounds", true );
+ }
+ }
+ else
+ {
+ pActionKeys->SetString( "wav", soundname );
+ if ( pPicker->IsMultiselectEnabled() )
+ {
+ pSoundList = pActionKeys->FindKey( "wavs", true );
+ }
+ }
+
+ if ( pSoundList )
+ {
+ // Adds them in selection order
+ for ( int i = 0; i < nSoundCount; ++i )
+ {
+ char pBuf[32];
+ Q_snprintf( pBuf, sizeof(pBuf), "%d", i );
+ pSoundName = pPicker->GetSelectedSoundName( i );
+
+ len = V_strlen( pSoundName );
+ soundname = ( char* )malloc( len + 2 );
+ soundname[ 0 ] = '#'; // mark sound to bypass the dsp
+ V_strncpy( soundname + 1, pSoundName, len + 1 );
+
+ pSoundList->SetString( pBuf, soundname );
+ free( soundname );
+ }
+ }
+
+ PostMessageAndClose( pActionKeys );
+ CloseModal();
+ }
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+