summaryrefslogtreecommitdiff
path: root/vgui2/matsys_controls/mdlpicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vgui2/matsys_controls/mdlpicker.cpp')
-rw-r--r--vgui2/matsys_controls/mdlpicker.cpp1742
1 files changed, 1742 insertions, 0 deletions
diff --git a/vgui2/matsys_controls/mdlpicker.cpp b/vgui2/matsys_controls/mdlpicker.cpp
new file mode 100644
index 0000000..9098c94
--- /dev/null
+++ b/vgui2/matsys_controls/mdlpicker.cpp
@@ -0,0 +1,1742 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "matsys_controls/mdlpicker.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utldict.h"
+#include "filesystem.h"
+#include "studio.h"
+#include "matsys_controls/matsyscontrols.h"
+#include "matsys_controls/mdlpanel.h"
+#include "vgui_controls/Splitter.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/Button.h"
+#include "vgui_controls/PropertySheet.h"
+#include "vgui_controls/MessageBox.h"
+#include "vgui_controls/PropertyPage.h"
+#include "vgui_controls/CheckButton.h"
+#include "vgui_controls/DirectorySelectDialog.h"
+#include "vgui/IVGui.h"
+#include "vgui/IInput.h"
+#include "vgui/ISurface.h"
+#include "vgui/Cursor.h"
+#include "matsys_controls/assetpicker.h"
+#include "matsys_controls/colorpickerpanel.h"
+#include "dmxloader/dmxloader.h"
+#include "tier1/utlbuffer.h"
+#include "bitmap/tgawriter.h"
+#include "tier3/tier3.h"
+#include "istudiorender.h"
+#include "../vgui2/src/VPanel.h"
+#include "tier2/p4helpers.h"
+#include "ivtex.h"
+#include "bitmap/tgaloader.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+using namespace vgui;
+
+static bool SaveTgaAndAddToP4( unsigned char *pImage, ImageFormat imageFormat, int Width, int Height, const char *szDestFilename )
+{
+
+ // allocate a buffer to write the tga into
+ int iMaxTGASize = 1024 + (Width * Height * 4);
+ void *pTGA = malloc( iMaxTGASize );
+ CUtlBuffer buffer( pTGA, iMaxTGASize );
+
+ if( !TGAWriter::WriteToBuffer( pImage, buffer, Width, Height, imageFormat, IMAGE_FORMAT_BGRA8888 ) )
+ {
+ Error( "Couldn't write bitmap data snapshot.\n" );
+ return false;
+ }
+
+ CP4AutoEditAddFile autop4( szDestFilename );
+
+ // async write to disk (this will take ownership of the memory)
+ char szDirName[ _MAX_PATH ];
+ strcpy( szDirName, szDestFilename );
+ V_StripFilename( szDirName );
+ g_pFullFileSystem->CreateDirHierarchy( szDirName, "" );
+ g_pFullFileSystem->AsyncWrite( szDestFilename, buffer.Base(), buffer.TellPut(), true );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+//
+// MDL Picker
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Sort by MDL name
+//-----------------------------------------------------------------------------
+static int __cdecl MDLBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("mdl");
+ const char *string2 = item2.kv->GetString("mdl");
+ return stricmp( string1, string2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CMDLPicker::CMDLPicker( vgui::Panel *pParent, int nFlags ) :
+ BaseClass( pParent, "MDL Files", "mdl", "models", "mdlName" )
+{
+ for( int i = 0; i < MAX_SELECTED_MODELS; i++ )
+ {
+ m_hSelectedMDL[ i ] = MDLHANDLE_INVALID;
+ }
+
+ m_nFlags = nFlags; // remember what we show and what not
+
+ m_pRenderPage = NULL;
+ m_pSequencesPage = NULL;
+ m_pActivitiesPage = NULL;
+ m_pSkinsPage = NULL;
+ m_pInfoPage = NULL;
+ m_pScreenCapsPage = NULL;
+
+ m_pSequencesList = NULL;
+ m_pActivitiesList = NULL;
+
+ m_hDirectorySelectDialog = NULL;
+
+ // Horizontal splitter for mdls
+ m_pFileBrowserSplitter = new Splitter( this, "FileBrowserSplitter", SPLITTER_MODE_VERTICAL, 1 );
+
+ float flFractions[] = { 0.33f, 0.67f };
+
+ m_pFileBrowserSplitter->RespaceSplitters( flFractions );
+
+ vgui::Panel *pSplitterLeftSide = m_pFileBrowserSplitter->GetChild( 0 );
+ vgui::Panel *pSplitterRightSide = m_pFileBrowserSplitter->GetChild( 1 );
+
+ // Standard browser controls
+ pSplitterLeftSide->RequestFocus();
+ CreateStandardControls( pSplitterLeftSide, false );
+
+ // property sheet - revisions, changes, etc.
+ m_pPreviewSplitter = new Splitter( pSplitterRightSide, "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 );
+
+ // now add wanted features
+ if ( nFlags & PAGE_RENDER )
+ {
+ m_pRenderPage = new vgui::PropertyPage( m_pViewsSheet, "RenderPage" );
+
+ m_pRenderPage->AddActionSignalTarget( this );
+
+ m_pRenderPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerrender.res" );
+
+ RefreshRenderSettings();
+
+ // ground
+ Button *pSelectProbe = (Button*)m_pRenderPage->FindChildByName( "ChooseLightProbe" );
+ pSelectProbe->AddActionSignalTarget( this );
+ }
+
+ if ( nFlags & PAGE_SEQUENCES )
+ {
+ m_pSequencesPage = new vgui::PropertyPage( m_pViewsSheet, "SequencesPage" );
+
+ m_pSequencesList = new vgui::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, 6, 6, -6, -6 );
+ }
+
+ if ( nFlags & PAGE_ACTIVITIES )
+ {
+ m_pActivitiesPage = new vgui::PropertyPage( m_pViewsSheet, "ActivitiesPage" );
+
+ m_pActivitiesList = new vgui::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, 6, 6, -6, -6 );
+ }
+
+ if ( nFlags & PAGE_SKINS )
+ {
+ m_pSkinsPage = new vgui::PropertyPage( m_pViewsSheet, "SkinsPage" );
+
+ m_pSkinsList = new vgui::ListPanel( m_pSkinsPage, "SkinsList" );
+ m_pSkinsList->AddColumnHeader( 0, "skin", "skin", 52, 0 );
+ m_pSkinsList->AddActionSignalTarget( this );
+ m_pSkinsList->SetSelectIndividualCells( true );
+ m_pSkinsList->SetEmptyListText( "No .MDL file currently selected." );
+ m_pSkinsList->SetDragEnabled( true );
+ m_pSkinsList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 6, -6, -6 );
+ }
+
+ if ( nFlags & PAGE_INFO )
+ {
+ m_pInfoPage = new vgui::PropertyPage( m_pViewsSheet, "InfoPage" );
+
+ m_pInfoPage->AddActionSignalTarget( this );
+
+ m_pInfoPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerinfo.res" );
+
+ CheckButton * pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "PhysicsObject" );
+ pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
+ pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
+ pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "StaticObject" );
+ pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
+ pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
+ pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName( "DynamicObject" );
+ pTempCheck->SetDisabledFgColor1( pTempCheck->GetFgColor());
+ pTempCheck->SetDisabledFgColor2( pTempCheck->GetFgColor());
+
+ m_pPropDataList = new vgui::ListPanel( m_pInfoPage, "PropData" );
+ m_pPropDataList->AddColumnHeader( 0, "key", "key", 250, ListPanel::COLUMN_FIXEDSIZE );
+ m_pPropDataList->AddColumnHeader( 1, "value", "value", 52, 0 );
+ m_pPropDataList->AddActionSignalTarget( this );
+ m_pPropDataList->SetSelectIndividualCells( false );
+ m_pPropDataList->SetEmptyListText( "No prop_data available." );
+ m_pPropDataList->SetDragEnabled( true );
+ m_pPropDataList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 6, 72, -6, -6 );
+
+ RefreshRenderSettings();
+ }
+
+ if ( nFlags & PAGE_SCREEN_CAPS )
+ {
+ m_pScreenCapsPage = new vgui::PropertyPage( m_pViewsSheet, "ScreenCapsPage" );
+
+// not sure why we have to do this for the color picker
+ CColorPickerButton *m_pBackgroundColor;
+ m_pBackgroundColor = new CColorPickerButton( m_pScreenCapsPage, "BackgroundColor", this );
+
+ m_pScreenCapsPage->LoadControlSettingsAndUserConfig( "resource/mdlpickerscreencaps.res" );
+
+ TextEntry *pTempValue;
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
+ pTempValue->SetText( "256" );
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
+ pTempValue->SetText( "256" );
+
+// not sure why this doesn't work
+// m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
+ m_pBackgroundColor->SetColor( 255, 0, 0, 255 );
+
+ Label *m_pOutputDirectory;
+ m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->SetText( "c:\\" );
+
+ Button *pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "Capture" );
+ pSelectProbe->AddActionSignalTarget( this );
+ pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "OutputDirectorySelect" );
+ pSelectProbe->AddActionSignalTarget( this );
+ pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "SaveCaps" );
+ pSelectProbe->AddActionSignalTarget( this );
+ pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "RestoreCaps" );
+ pSelectProbe->AddActionSignalTarget( this );
+ pSelectProbe = ( Button * )m_pScreenCapsPage->FindChildByName( "GenerateBackpackIcons" );
+ pSelectProbe->AddActionSignalTarget( this );
+ }
+
+ // Load layout settings; has to happen before pinning occurs in code
+ LoadControlSettingsAndUserConfig( "resource/mdlpicker.res" );
+
+ // Pages must be added after control settings are set up
+ if ( m_pRenderPage )
+ {
+ m_pViewsSheet->AddPage( m_pRenderPage, "Render" );
+ }
+ if ( m_pSequencesPage )
+ {
+ m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
+ }
+ if ( m_pActivitiesPage )
+ {
+ m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
+ }
+ if ( m_pSkinsPage )
+ {
+ m_pViewsSheet->AddPage( m_pSkinsPage, "Skins" );
+ }
+ if ( m_pInfoPage )
+ {
+ m_pViewsSheet->AddPage( m_pInfoPage, "Info" );
+ }
+ if ( m_pScreenCapsPage )
+ {
+ m_pViewsSheet->AddPage( m_pScreenCapsPage, "Screen Caps" );
+ }
+}
+
+void CMDLPicker::RefreshRenderSettings()
+{
+ vgui::CheckButton *pToggle;
+
+ if ( !m_pRenderPage )
+ return;
+
+ // ground
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("NoGround");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetGroundGrid( !pToggle->IsSelected() );
+
+ // collision
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("Collision");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetCollsionModel( pToggle->IsSelected() );
+
+ // wireframe
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("Wireframe");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetWireFrame( pToggle->IsSelected() );
+
+ // lockview
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("LockView");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetLockView( pToggle->IsSelected() );
+
+ // look at camera
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("LookAtCamera");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetLookAtCamera( pToggle->IsSelected() );
+
+ // thumbnail safe zone
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName("ThumbnailSafeZone");
+ pToggle->AddActionSignalTarget( this );
+ m_pMDLPreview->SetThumbnailSafeZone( pToggle->IsSelected() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CMDLPicker::~CMDLPicker()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Performs layout
+//-----------------------------------------------------------------------------
+void CMDLPicker::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_pFileBrowserSplitter->SetBounds( 0, 0, w, h );
+}
+
+
+//-----------------------------------------------------------------------------
+// Buttons on various pages
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnAssetSelected( KeyValues *pParams )
+{
+ const char *pAsset = pParams->GetString( "asset" );
+
+ char pProbeBuf[MAX_PATH];
+ Q_snprintf( pProbeBuf, sizeof(pProbeBuf), "materials/lightprobes/%s", pAsset );
+
+ BeginDMXContext();
+ CDmxElement *pLightProbe = NULL;
+ bool bOk = UnserializeDMX( pProbeBuf, "GAME", true, &pLightProbe );
+ if ( !pLightProbe || !bOk )
+ {
+ char pBuf[1024];
+ Q_snprintf( pBuf, sizeof(pBuf), "Error loading lightprobe file '%s'!\n", pProbeBuf );
+ vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Error Loading File!\n", pBuf, GetParent() );
+ pMessageBox->DoModal( );
+
+ EndDMXContext( true );
+ return;
+ }
+
+ m_pMDLPreview->SetLightProbe( pLightProbe );
+ EndDMXContext( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Buttons on various pages
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "ChooseLightProbe" ) )
+ {
+ CAssetPickerFrame *pPicker = new CAssetPickerFrame( this, "Select Light Probe (.prb) File",
+ "Light Probe", "prb", "materials/lightprobes", "lightprobe" );
+ pPicker->DoModal();
+ return;
+ }
+ else if ( !Q_stricmp( pCommand, "OutputDirectorySelect" ) )
+ {
+ if ( !m_hDirectorySelectDialog.Get() )
+ {
+ m_hDirectorySelectDialog = new DirectorySelectDialog( this, "Choose Screen Caps output folder" );
+ }
+
+ Label *m_pOutputDirectory;
+ char temp[ MAX_PATH ];
+ m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->GetText( temp, sizeof( temp ) );
+
+ m_hDirectorySelectDialog->MakeReadyForUse();
+ m_hDirectorySelectDialog->SetStartDirectory( temp );
+ m_hDirectorySelectDialog->DoModal();
+ return;
+ }
+ else if ( !Q_stricmp( pCommand, "Capture" ) )
+ {
+ CaptureScreenCaps();
+ return;
+ }
+ else if ( !Q_stricmp( pCommand, "GenerateBackpackIcons" ) )
+ {
+ // shut off the ground grid
+ vgui::CheckButton *pGroundToggle = (vgui::CheckButton *)m_pRenderPage->FindChildByName( "NoGround" );
+ bool bOriginalGridState = pGroundToggle->IsSelected();
+
+ vgui::CheckButton *pSafeZoneToggle = (vgui::CheckButton *)m_pRenderPage->FindChildByName( "ThumbnailSafeZone" );
+ bool bOriginalSafeZoneState = pSafeZoneToggle->IsSelected();
+
+ m_pMDLPreview->SetGroundGrid( false );
+ m_pMDLPreview->SetThumbnailSafeZone( false );
+
+ // make the icons
+ GenerateBackpackIcons();
+
+ // return the ground grid to its original state
+ m_pMDLPreview->SetGroundGrid( !bOriginalGridState );
+ m_pMDLPreview->SetThumbnailSafeZone( bOriginalSafeZoneState );
+
+ return;
+ }
+ else if ( !Q_stricmp( pCommand, "SaveCaps" ) )
+ {
+ SaveCaps( NULL );
+ return;
+ }
+ else if ( !Q_stricmp( pCommand, "RestoreCaps" ) )
+ {
+ if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
+ {
+ int nCount = m_AssetList.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ i ].m_nItemId ) &&
+ m_pAssetBrowser->IsItemSelected( m_AssetList[ i ].m_nItemId ) )
+ {
+ KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ i ].m_nItemId );
+ const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
+
+ char szBathPath[ _MAX_PATH ];
+ Label *m_pOutputDirectory;
+
+ m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->GetText( szBathPath, sizeof( szBathPath ) );
+
+ char szPathedFileName[ _MAX_PATH ];
+ sprintf( szPathedFileName, "%s%s", szBathPath, pSelectedAsset );
+
+ Label *m_pResults = ( Label * )m_pScreenCapsPage->FindChildByName( "CaptureResults" );
+ if ( RestoreCaps( szPathedFileName ) )
+ {
+ m_pResults->SetText( "Prefs Restored" );
+ }
+ else
+ {
+ m_pResults->SetText( "Prefs NOT FOUND" );
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ RestoreCaps( NULL );
+ }
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// Handles the directory selection for screen caps
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnDirectorySelected( char const *dir )
+{
+ if ( m_hDirectorySelectDialog != 0 )
+ {
+ m_hDirectorySelectDialog->MarkForDeletion();
+ }
+
+ Label *m_pOutputDirectory;
+ m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->SetText( dir );
+}
+
+
+//-----------------------------------------------------------------------------
+// Screen captures the specific model and writes out a .tga. Assumes the MDLPreview
+// panel has been properly adjusted to 0,0 in screen space and that width / height
+// have been set.
+//-----------------------------------------------------------------------------
+const char *CMDLPicker::CaptureModel( int nModIndex, const char *AssetName, const char *OutputPath, int Width, int Height, Color BackgroundColor, bool bSelectedOnly )
+{
+ char pBuf[ MAX_PATH ];
+ Q_snprintf( pBuf, sizeof( pBuf ), "%s\\%s\\%s", GetModPath( nModIndex ), m_pAssetSubDir, AssetName );
+ Q_FixSlashes( pBuf );
+
+ if ( !bSelectedOnly )
+ {
+ SelectMDL( pBuf, false, -1 );
+ }
+
+ CMatRenderContextPtr pRenderContext( materials );
+
+ g_pMaterialSystem->BeginFrame( 0 );
+ g_pStudioRender->BeginFrame();
+
+// pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
+// pRenderContext->ClearBuffers( true, true );
+
+ Color NewPanelColor;
+
+ NewPanelColor.SetColor( 0, 0, 0, 0 );
+ m_pMDLPreview->SetBackgroundColor( NewPanelColor );
+
+ g_pVGuiSurface->PaintTraverseEx( m_pMDLPreview->GetVPanel(), false );
+
+ g_pStudioRender->EndFrame();
+ g_pMaterialSystem->EndFrame( );
+
+ // get the data from the backbuffer and save to disk
+ // bitmap bits
+ unsigned char *pImageBlack = ( unsigned char * )malloc( Width * 4 * Height );
+
+ // Get Bits from the material system
+ pRenderContext->ReadPixels( 0, 0, Width, Height, pImageBlack, IMAGE_FORMAT_BGRA8888 );
+
+
+ g_pMaterialSystem->BeginFrame( 0 );
+ g_pStudioRender->BeginFrame();
+
+// pRenderContext->ClearColor4ub( 255, 255, 255, 0 );
+// pRenderContext->ClearBuffers( true, true );
+
+ NewPanelColor.SetColor( 255, 255, 255, 0 );
+ m_pMDLPreview->SetBackgroundColor( NewPanelColor );
+
+ g_pVGuiSurface->PaintTraverseEx( m_pMDLPreview->GetVPanel(), false );
+
+ g_pStudioRender->EndFrame();
+ g_pMaterialSystem->EndFrame( );
+
+ // get the data from the backbuffer and save to disk
+ // bitmap bits
+ unsigned char *pImageWhite = ( unsigned char * )malloc( Width * 4 * Height );
+
+ // Get Bits from the material system
+ pRenderContext->ReadPixels( 0, 0, Width, Height, pImageWhite, IMAGE_FORMAT_BGRA8888 );
+
+ unsigned char *pBlackPos = pImageBlack;
+ unsigned char *pWhitePos = pImageWhite;
+ for( int y = 0; y < Height; y++ )
+ {
+ for( int x = 0; x < Width; x++, pBlackPos += 4, pWhitePos += 4 )
+ {
+ if ( ( *( pBlackPos + 0 ) ) != ( *( pWhitePos + 0 ) ) || // blue
+ ( *( pBlackPos + 1 ) ) != ( *( pWhitePos + 1 ) ) || // green
+ ( *( pBlackPos + 2 ) ) != ( *( pWhitePos + 2 ) ) ) // red
+ {
+ unsigned char nBlueDiff = ( *( pBlackPos + 0 ) );
+ unsigned char nGreenDiff = ( *( pBlackPos + 1 ) );
+ unsigned char nRedDiff = ( *( pBlackPos + 2 ) );
+
+ unsigned char nMax = nBlueDiff;
+ if ( nGreenDiff > nMax )
+ {
+ nMax = nGreenDiff;
+ }
+ if ( nRedDiff > nMax )
+ {
+ nMax = nRedDiff;
+ }
+
+ *( pBlackPos + 3 ) = nMax;
+ }
+ else
+ {
+ *( pBlackPos + 3 ) = 0xff;
+ }
+ }
+ }
+
+ static char szPathedFileName[ _MAX_PATH ];
+ sprintf( szPathedFileName, "%s%s", OutputPath, AssetName );
+ V_SetExtension( szPathedFileName, ".tga", sizeof( szPathedFileName ) );
+
+ bool bResult = SaveTgaAndAddToP4( pImageBlack, IMAGE_FORMAT_BGRA8888, Width, Height, szPathedFileName );
+
+ free( pImageBlack );
+ free( pImageWhite );
+
+ if ( !bResult) return NULL;
+
+ if ( bSelectedOnly )
+ {
+ SaveCaps( szPathedFileName );
+ }
+
+ return szPathedFileName;
+}
+
+
+//-----------------------------------------------------------------------------
+// Will go through the asset browser and capture each visible item.
+//-----------------------------------------------------------------------------
+void CMDLPicker::CaptureScreenCaps( void )
+{
+ char temp[ 256 ];
+ TextEntry *pTempValue;
+ int width;
+ int height;
+ char szBathPath[ _MAX_PATH ];
+ Label *m_pOutputDirectory;
+
+ m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->GetText( szBathPath, sizeof( szBathPath ) );
+
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
+ pTempValue->GetText( temp, sizeof( temp ) );
+ width = atoi( temp );
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
+ pTempValue->GetText( temp, sizeof( temp ) );
+ height = atoi( temp );
+
+ int PanelX, PanelY, PanelWidth, PanelHeight;
+ Color PanelColor;
+
+ Panel *pParent = m_pMDLPreview->GetParent();
+ m_pMDLPreview->GetPos( PanelX, PanelY );
+ m_pMDLPreview->GetSize( PanelWidth, PanelHeight );
+ PanelColor = m_pMDLPreview->GetBackgroundColor();
+
+ m_pMDLPreview->SetParent( ( vgui::Panel * )NULL );
+ m_pMDLPreview->SetPos( 0, 0 );
+ m_pMDLPreview->SetSize( width, height );
+
+ CColorPickerButton *m_pBackgroundColor;
+ m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
+
+ Color NewPanelColor = m_pBackgroundColor->GetColor();
+ NewPanelColor[3] = 0;
+ m_pMDLPreview->SetBackgroundColor( NewPanelColor );
+ ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
+
+ bool bSelectedOnly = false;
+ if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
+ {
+ bSelectedOnly = true;
+ }
+
+ int nCount = m_AssetList.Count();
+ int nNumItems = 0;
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ i ].m_nItemId ) &&
+ ( !bSelectedOnly || m_pAssetBrowser->IsItemSelected( m_AssetList[ i ].m_nItemId ) ) )
+ {
+ KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ i ].m_nItemId );
+ const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
+ int nModIndex = pItemKeyValues->GetInt( "modIndex" );
+
+ CaptureModel( nModIndex, pSelectedAsset, szBathPath, width, height, NewPanelColor, bSelectedOnly );
+ nNumItems++;
+ }
+ }
+
+ m_pMDLPreview->SetParent( pParent );
+ m_pMDLPreview->SetPos( PanelX, PanelY );
+ m_pMDLPreview->SetSize( PanelWidth, PanelHeight );
+ m_pMDLPreview->SetBackgroundColor( PanelColor );
+ ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
+
+ Label *m_pResults;
+
+ sprintf( temp, "Captured %d items", nNumItems );
+ m_pResults = ( Label * )m_pScreenCapsPage->FindChildByName( "CaptureResults" );
+ m_pResults->SetText( temp );
+}
+
+
+//-----------------------------------------------------------------------------
+// Stub for XBox360 compiles
+//-----------------------------------------------------------------------------
+#if defined( _X360 )
+const char *getenv( const char *varname )
+{
+ return NULL;
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Writes two very simple .vmt file, one for the passed in asset,
+// and the other for <asset>_large.
+//-----------------------------------------------------------------------------
+void CMDLPicker::WriteBackbackVMTFiles( const char *pAssetName )
+{
+ const char *pVProject = getenv( "VPROJECT" );
+ if ( !pVProject )
+ return;
+
+ char pStrippedAssetName[ MAX_PATH ];
+ V_StripExtension( pAssetName, pStrippedAssetName, sizeof( pStrippedAssetName ) );
+ V_strcat_safe( pStrippedAssetName, GetOutputFileSuffix().Get() );
+
+ char pVMTFilename[ MAX_PATH ];
+ Q_snprintf( pVMTFilename, sizeof( pVMTFilename ), "%s\\materials\\backpack\\%s.vmt", pVProject, pStrippedAssetName );
+ Q_FixSlashes( pVMTFilename );
+
+ char pBaseTextureName[ MAX_PATH ];
+ Q_snprintf( pBaseTextureName, sizeof( pBaseTextureName ), "backpack\\%s", pStrippedAssetName );
+ Q_FixSlashes( pBaseTextureName );
+
+ {
+ CP4AutoEditAddFile autop4( pVMTFilename );
+ FileHandle_t fileHandle = g_pFullFileSystem->Open( pVMTFilename, "w" );
+ if ( fileHandle )
+ {
+
+ g_pFullFileSystem->FPrintf( fileHandle, "\"UnlitGeneric\"\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, "{\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, " \"$baseTexture\" \"%s\"\n", pBaseTextureName );
+ g_pFullFileSystem->FPrintf( fileHandle, " $translucent 1\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, " $vertexcolor 1\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, "}\n" );
+
+ g_pFullFileSystem->Close( fileHandle );
+ }
+ }
+
+ // now write the _large version
+ Q_snprintf( pVMTFilename, sizeof( pVMTFilename ), "%s\\materials\\backpack\\%s_large", pVProject, pStrippedAssetName );
+ V_SetExtension( pVMTFilename, ".vmt", sizeof( pVMTFilename ) );
+ Q_FixSlashes( pVMTFilename );
+
+ Q_snprintf( pBaseTextureName, sizeof( pBaseTextureName ), "backpack\\%s_large", pStrippedAssetName );
+ Q_FixSlashes( pBaseTextureName );
+
+ {
+ CP4AutoEditAddFile autop4( pVMTFilename );
+ FileHandle_t fileHandle = g_pFullFileSystem->Open( pVMTFilename, "w" );
+ if ( fileHandle )
+ {
+ g_pFullFileSystem->FPrintf( fileHandle, "\"UnlitGeneric\"\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, "{\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, " \"$baseTexture\" \"%s\"\n", pBaseTextureName );
+ g_pFullFileSystem->FPrintf( fileHandle, " $translucent 1\n" );
+ g_pFullFileSystem->FPrintf( fileHandle, "}\n" );
+
+ g_pFullFileSystem->Close( fileHandle );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+void *VTexFilesystemFactory( const char *pName, int *pReturnCode )
+{
+ return g_pFullFileSystem;
+}
+
+
+void* MdlPickerFSFactory( const char *pName, int *pReturnCode )
+{
+ if ( IsX360() )
+ return NULL;
+
+ if ( Q_stricmp( pName, FILESYSTEM_INTERFACE_VERSION ) == 0 )
+ return g_pFullFileSystem;
+
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates the two required icons for the TF2 store/backpack system
+//-----------------------------------------------------------------------------
+void CMDLPicker::GenerateBackpackIcons( void )
+{
+ if ( !g_pVTex )
+ return;
+
+ int width;
+ int height;
+
+ // find the index of the item we are currently viewing
+ int selectedItemIndex;
+ for ( selectedItemIndex = 0; selectedItemIndex < m_AssetList.Count(); ++selectedItemIndex )
+ {
+ if ( m_pAssetBrowser->IsItemVisible( m_AssetList[ selectedItemIndex ].m_nItemId ) &&
+ m_pAssetBrowser->IsItemSelected( m_AssetList[ selectedItemIndex ].m_nItemId ) )
+ {
+ break;
+ }
+ }
+
+ if ( selectedItemIndex >= m_AssetList.Count() )
+ return;
+
+ //
+ // Fetch and check environment variables
+ //
+ const char *pVContent = getenv( "VCONTENT" );
+ if ( !pVContent )
+ {
+ Error( "VCONTENT environment variable not set" );
+ return;
+ }
+
+ const char *pVMod = getenv( "VMOD" );
+ if ( !pVMod )
+ {
+ Error( "VMOD environment variable not set" );
+ return;
+ }
+
+ const char *pVProject = getenv( "VPROJECT" );
+ if ( !pVProject )
+ {
+ Error( "VPROJECT environment variable not set" );
+ return;
+ }
+
+ // extract the filename of the model
+ KeyValues *pItemKeyValues = m_pAssetBrowser->GetItem( m_AssetList[ selectedItemIndex ].m_nItemId );
+ const char *pSelectedAsset = pItemKeyValues->GetString( "asset" );
+
+ // set the P4 changelist label to refer to this set of icons
+ char pChangelistLabel[ MAX_PATH ];
+ V_strcpy_safe( pChangelistLabel, pSelectedAsset );
+ V_FileBase( pChangelistLabel, pChangelistLabel, sizeof( pChangelistLabel ) );
+ V_strcat_safe( pChangelistLabel, " Auto Checkout", sizeof( pChangelistLabel ) );
+ g_p4factory->SetOpenFileChangeList( pChangelistLabel );
+
+ // generate .VMT files for normal and _large icons
+ WriteBackbackVMTFiles( pSelectedAsset );
+
+ // store original state of model preview panel
+ int PanelX, PanelY, PanelWidth, PanelHeight;
+ Color PanelColor;
+
+ Panel *pParent = m_pMDLPreview->GetParent();
+ m_pMDLPreview->GetPos( PanelX, PanelY );
+ m_pMDLPreview->GetSize( PanelWidth, PanelHeight );
+ PanelColor = m_pMDLPreview->GetBackgroundColor();
+
+ // slam preview panel to desired TGA size for large icon, and write it out
+ width = 512;
+ height = 512;
+ m_pMDLPreview->SetParent( ( vgui::Panel * )NULL );
+ m_pMDLPreview->SetPos( 0, 0 );
+ m_pMDLPreview->SetSize( width, height );
+
+ CColorPickerButton *m_pBackgroundColor;
+ m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
+
+ Color NewPanelColor = m_pBackgroundColor->GetColor();
+ NewPanelColor[3] = 0;
+ m_pMDLPreview->SetBackgroundColor( NewPanelColor );
+ ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
+
+ char pLargeAssetName[ MAX_PATH ];
+ V_strcpy_safe( pLargeAssetName, pSelectedAsset );
+ V_StripExtension( pLargeAssetName, pLargeAssetName, ARRAYSIZE( pLargeAssetName ) );
+
+ CUtlString strExtention = GetOutputFileSuffix();
+ strExtention += "_large.mdl";
+
+ V_strcat_safe( pLargeAssetName, strExtention.String() );
+
+ char pOutputPath[ MAX_PATH ];
+ Q_snprintf( pOutputPath, sizeof( pOutputPath ), "%s\\%s\\materialsrc\\backpack\\", pVContent, pVMod );
+ Q_FixSlashes( pOutputPath );
+
+ int nModIndex = pItemKeyValues->GetInt( "modIndex" );
+ const char *pLargeTGAName = CaptureModel( nModIndex, pLargeAssetName, pOutputPath, width, height, NewPanelColor, true );
+ if ( !pLargeTGAName )
+ return;
+
+ // write corresponding .txt file with vtex options
+ char pVTexOptionsFileName[ MAX_PATH ];
+ V_strcpy_safe( pVTexOptionsFileName, pLargeTGAName );
+ V_SetExtension( pVTexOptionsFileName, ".txt", sizeof( pVTexOptionsFileName ) );
+
+ {
+ CP4AutoEditAddFile autop4( pVTexOptionsFileName );
+ FileHandle_t hVTexOptionsFile = g_pFullFileSystem->Open( pVTexOptionsFileName, "w" );
+ if ( hVTexOptionsFile )
+ {
+ g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nomip 1\n" );
+ g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nolod 1\n" );
+ g_pFullFileSystem->Close( hVTexOptionsFile );
+ }
+ }
+
+ // !KLUDGE! Everybody I've talked to says that vtex is *supposed* to
+ // use VPROJECT. But it doesn't. I don't think I can safely change vtex
+ // without breaking tons of stuff. So just force the output directory.
+ // Determine the proper output directory based on VPROJECT
+ char pOutputPathGame[ MAX_PATH ];
+ Q_strncpy( pOutputPathGame, pVProject, sizeof( pOutputPathGame ) );
+ Q_StripTrailingSlash( pOutputPathGame );
+ Q_strncat( pOutputPathGame, "/materials/", sizeof( pOutputPathGame ) );
+ const char *pBackpack = Q_stristr( pLargeTGAName, "backpack" );
+ if ( pBackpack )
+ {
+ Q_strncat( pOutputPathGame, pBackpack, sizeof( pOutputPathGame ) );
+ Q_StripFilename( pOutputPathGame );
+ }
+ Q_FixSlashes( pOutputPathGame );
+
+ // run vtex on the TGA and .txt file to create .VTF and add it to our Perforce changelist
+ char *vTexArgv[64];
+ int vTexArgc = 0;
+ vTexArgv[ vTexArgc++ ] = "";
+ vTexArgv[ vTexArgc++ ] = "-quiet";
+ vTexArgv[ vTexArgc++ ] = "-UseStandardError";
+ vTexArgv[ vTexArgc++ ] = "-WarningsAsErrors";
+ vTexArgv[ vTexArgc++ ] = "-p4skip";
+ vTexArgv[ vTexArgc++ ] = "-outdir";
+ vTexArgv[ vTexArgc++ ] = pOutputPathGame;
+ vTexArgv[ vTexArgc++ ] = (char *)pLargeTGAName;
+
+ g_pVTex->VTex( MdlPickerFSFactory, pOutputPathGame, vTexArgc, vTexArgv );
+
+ // Generale small TGA name, by removing the "large" part
+ char pSmallTGAName[ MAX_PATH ];
+ strcpy( pSmallTGAName, pLargeTGAName );
+ char *_large = Q_stristr( pSmallTGAName, "_large");
+ Assert(_large);
+ strcpy(_large, _large+6);
+
+ // Load up the large icon
+ int nCheckWidth, nCheckHeight;
+ ImageFormat largeFmt;
+ float gamma;
+ CUtlBuffer largeTGAFileData;
+ CUtlMemory<unsigned char> largeTGAImageData;
+
+ if ( !g_pFullFileSystem->ReadFile( pLargeTGAName, NULL, largeTGAFileData )
+ || !TGALoader::GetInfo( largeTGAFileData, &nCheckWidth, &nCheckHeight, &largeFmt, &gamma )
+ || nCheckWidth != width || nCheckHeight != height )
+ {
+ Error( "Failed to reload image header %s", pLargeTGAName );
+ Assert( false );
+ return;
+ }
+
+ largeTGAFileData.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
+ if ( !TGALoader::LoadRGBA8888( largeTGAFileData, largeTGAImageData, nCheckWidth, nCheckHeight )
+ || nCheckWidth != width || nCheckHeight != height )
+ {
+ Error( "Failed to reload image data %s", pLargeTGAName );
+ Assert( false );
+ return;
+ }
+
+ //
+ // Perform a downsample. This is better than just re-rendering at the smaller size,
+ // which essentially just point-samples the image.
+ //
+ CUtlMemory<unsigned char> smallTGAImageData;
+ const int kSmallSize = 128;
+ smallTGAImageData.EnsureCapacity(kSmallSize*kSmallSize*4);
+ ImageLoader::ResampleInfo_t resampleInfo;
+ resampleInfo.m_nSrcWidth = width;
+ resampleInfo.m_nSrcHeight = height;
+ resampleInfo.m_flSrcGamma = gamma;
+ resampleInfo.m_pSrc = (unsigned char *)largeTGAImageData.Base();
+
+ resampleInfo.m_nDestWidth = kSmallSize;
+ resampleInfo.m_nDestHeight = kSmallSize;
+ resampleInfo.m_flDestGamma = gamma;
+ resampleInfo.m_pDest = (unsigned char *)smallTGAImageData.Base();
+
+ resampleInfo.m_nFlags = ImageLoader::RESAMPLE_CLAMPS | ImageLoader::RESAMPLE_CLAMPT;
+ //resampleInfo.m_nFlags |= ImageLoader::RESAMPLE_NICE_FILTER; // Turn this off. It has some sort of edge enhancement or something. Causes edges to ring.
+
+ if ( !ImageLoader::ResampleRGBA8888( resampleInfo ) )
+ {
+ Error( "Failed to resample %s", pLargeTGAName );
+ Assert( false );
+ return;
+ }
+
+ // Save it
+ if ( !SaveTgaAndAddToP4( resampleInfo.m_pDest, IMAGE_FORMAT_RGBA8888, resampleInfo.m_nDestWidth, resampleInfo.m_nDestHeight, pSmallTGAName ) )
+ {
+ return;
+ }
+
+ // Save the .cfg file.
+ SaveCaps( pSmallTGAName );
+
+ // write corresponding .txt file with vtex options
+ V_strcpy_safe( pVTexOptionsFileName, pSmallTGAName );
+ V_SetExtension( pVTexOptionsFileName, ".txt", sizeof( pVTexOptionsFileName ) );
+
+ {
+ CP4AutoEditAddFile autop4( pVTexOptionsFileName );
+ FileHandle_t hVTexOptionsFile = g_pFullFileSystem->Open( pVTexOptionsFileName, "w" );
+ if ( hVTexOptionsFile )
+ {
+ g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nomip 1\n" );
+ g_pFullFileSystem->FPrintf( hVTexOptionsFile, "nolod 1\n" );
+ g_pFullFileSystem->Close( hVTexOptionsFile );
+ }
+ }
+
+ // run vtex on the TGA and .txt file to create .VTF and add it to our Perforce changelist
+ vTexArgc = 0;
+ vTexArgv[ vTexArgc++ ] = "";
+ vTexArgv[ vTexArgc++ ] = "-quiet";
+ vTexArgv[ vTexArgc++ ] = "-UseStandardError";
+ vTexArgv[ vTexArgc++ ] = "-WarningsAsErrors";
+ vTexArgv[ vTexArgc++ ] = "-p4skip";
+ vTexArgv[ vTexArgc++ ] = "-outdir";
+ vTexArgv[ vTexArgc++ ] = pOutputPathGame;
+ vTexArgv[ vTexArgc++ ] = (char *)pSmallTGAName;
+ g_pVTex->VTex( MdlPickerFSFactory, pOutputPathGame, vTexArgc, vTexArgv );
+
+
+ // restore the preview panel to its original state
+ m_pMDLPreview->SetParent( pParent );
+ m_pMDLPreview->SetPos( PanelX, PanelY );
+ m_pMDLPreview->SetSize( PanelWidth, PanelHeight );
+ m_pMDLPreview->SetBackgroundColor( PanelColor );
+ ((VPanel *)m_pMDLPreview->GetVPanel())->Solve();
+}
+
+
+CUtlString CMDLPicker::GetOutputFileSuffix()
+{
+ char temp[256];
+ TextEntry *pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "SuffixText" );
+ if ( pTempValue )
+ {
+ pTempValue->GetText( temp, sizeof( temp ) );
+ }
+ return temp;
+}
+
+
+//-----------------------------------------------------------------------------
+// Saves the screen cap information and camera position
+//-----------------------------------------------------------------------------
+void CMDLPicker::SaveCaps( const char *szFileName )
+{
+ char temp[ _MAX_PATH ];
+
+ KeyValues *CaptureData = new KeyValues( "ScreenCaps" );
+
+ Vector vecPos;
+ QAngle angDir;
+ m_pMDLPreview->GetCameraPositionAndAngles( vecPos, angDir );
+ sprintf( temp, "%g %g %g", vecPos.x, vecPos.y, vecPos.z );
+ CaptureData->SetString( "CameraPosition", temp );
+ sprintf( temp, "%g %g %g", angDir.x, angDir.y, angDir.z );
+ CaptureData->SetString( "CameraAngles", temp );
+
+ Vector vecOffset;
+ m_pMDLPreview->GetCameraOffset( vecOffset );
+ sprintf( temp, "%g %g %g", vecOffset.x, vecOffset.y, vecOffset.z );
+ CaptureData->SetString( "CameraOffset", temp );
+
+ CColorPickerButton *m_pBackgroundColor;
+ m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
+ Color color = m_pBackgroundColor->GetColor();
+
+ sprintf( temp, "%d %d %d %d", color.r(), color.g(), color.b(), color.a() );
+ CaptureData->SetString( "BackgroundColor", temp );
+
+ TextEntry *pTempValue;
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
+ pTempValue->GetText( temp, sizeof( temp ) );
+ CaptureData->SetString( "Width", temp );
+
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
+ pTempValue->GetText( temp, sizeof( temp ) );
+ CaptureData->SetString( "Height", temp );
+
+ vgui::CheckButton *pToggle;
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "NoGround" );
+ CaptureData->SetInt( "NoGround", pToggle->IsSelected() ? 1 : 0 );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Collision" );
+ CaptureData->SetInt( "Collision", pToggle->IsSelected() ? 1 : 0 );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Wireframe" );
+ CaptureData->SetInt( "Wifeframe", pToggle->IsSelected() ? 1 : 0 );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LockView" );
+ CaptureData->SetInt( "LockView", pToggle->IsSelected() ? 1 : 0 );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LookAtCamera" );
+ CaptureData->SetInt( "LookAtCamera", pToggle->IsSelected() ? 1 : 0 );
+
+ for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
+ {
+ if ( m_hSelectedMDL[ i ] != MDLHANDLE_INVALID )
+ {
+ const char *MergedModelName = vgui::MDLCache()->GetModelName( m_hSelectedMDL[ i ] );
+ sprintf( temp, "Merged_%d", i );
+ CaptureData->SetString( temp, MergedModelName );
+ }
+ }
+
+ if ( szFileName != NULL )
+ {
+ strcpy( temp, szFileName );
+ V_SetExtension( temp, ".cfg", sizeof( temp ) );
+ }
+ else
+ {
+ Label *m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->GetText( temp, sizeof( temp ) );
+
+ strcat( temp, "ScreenCaps.cfg" );
+ }
+
+ CaptureData->SaveToFile( g_pFullFileSystem, temp );
+ CP4AutoAddFile autop4( temp );
+}
+
+
+//-----------------------------------------------------------------------------
+// Restores the screen cap information and camera position
+//-----------------------------------------------------------------------------
+bool CMDLPicker::RestoreCaps( const char *szFileName )
+{
+ char temp[ _MAX_PATH ];
+
+ if ( szFileName != NULL )
+ {
+ strcpy( temp, szFileName );
+ V_SetExtension( temp, ".cfg", sizeof( temp ) );
+ }
+ else
+ {
+ Label *m_pOutputDirectory = ( Label * )m_pScreenCapsPage->FindChildByName( "OutputDirectory" );
+ m_pOutputDirectory->GetText( temp, sizeof( temp ) );
+ strcat( temp, "ScreenCaps.cfg" );
+ }
+
+ KeyValues *CaptureData = new KeyValues( "ScreenCaps" );
+
+ if ( !CaptureData->LoadFromFile( g_pFullFileSystem, temp ) )
+ {
+ return false;
+ }
+
+ Vector vecPos;
+ QAngle angDir;
+ Vector vecOffset;
+ sscanf( CaptureData->GetString( "CameraPosition" ), "%g %g %g", &vecPos.x, &vecPos.y, &vecPos.z );
+ sscanf( CaptureData->GetString( "CameraAngles" ), "%g %g %g", &angDir.x, &angDir.y, &angDir.z );
+ sscanf( CaptureData->GetString( "CameraOffset" ), "%g %g %g", &vecOffset.x, &vecOffset.y, &vecOffset.z );
+
+ m_pMDLPreview->SetCameraOffset( vecOffset );
+ m_pMDLPreview->SetCameraPositionAndAngles( vecPos, angDir );
+
+ CColorPickerButton *m_pBackgroundColor;
+ int r, g, b, a;
+ m_pBackgroundColor = ( CColorPickerButton * )m_pScreenCapsPage->FindChildByName( "BackgroundColor" );
+ sscanf( CaptureData->GetString( "BackgroundColor" ), "%d %d %d %d", &r, &g, &b, &a );
+ m_pBackgroundColor->SetColor( r, g, b, a );
+
+ TextEntry *pTempValue;
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "WidthText" );
+ pTempValue->SetText( CaptureData->GetString( "Width" ) );
+
+ pTempValue = ( TextEntry * )m_pScreenCapsPage->FindChildByName( "HeightText" );
+ pTempValue->SetText( CaptureData->GetString( "Height" ) );
+
+
+ vgui::CheckButton *pToggle;
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "NoGround" );
+ pToggle->SetSelected( ( CaptureData->GetInt( "NoGround" ) == 1 ) );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Collision" );
+ pToggle->SetSelected( ( CaptureData->GetInt( "Collision" ) == 1 ) );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "Wireframe" );
+ pToggle->SetSelected( ( CaptureData->GetInt( "Wireframe" ) == 1 ) );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LockView" );
+ pToggle->SetSelected( ( CaptureData->GetInt( "LockView" ) == 1 ) );
+
+ pToggle = (vgui::CheckButton*)m_pRenderPage->FindChildByName( "LookAtCamera" );
+ pToggle->SetSelected( ( CaptureData->GetInt( "LookAtCamera" ) == 1 ) );
+
+ for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
+ {
+ sprintf( temp, "Merged_%d", i );
+ const char *MergedModelName = CaptureData->GetString( temp, NULL );
+ if ( MergedModelName )
+ {
+ SelectMDL( MergedModelName, false, i );
+ }
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: rebuilds the list of activities
+//-----------------------------------------------------------------------------
+void CMDLPicker::RefreshActivitiesAndSequencesList()
+{
+ m_pActivitiesList->RemoveAll();
+ m_pSequencesList->RemoveAll();
+ m_pMDLPreview->SetSequence( 0 );
+
+ if ( m_hSelectedMDL[ 0 ] == 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[ 0 ] );
+
+ 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[ 0 ] ) );
+ 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);
+ 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[ 0 ] ) );
+ m_pSequencesList->SetItemDragData( nItemID, pDrag );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// A MDL was selected
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnSelectedAssetPicked( const char *pMDLName )
+{
+ char pRelativePath[MAX_PATH];
+
+ int nSelectSecondary = -1;
+ if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) )
+ {
+ nSelectSecondary = 0;
+ }
+ else if ( input()->IsMouseDown(MOUSE_RIGHT) )
+ {
+ nSelectSecondary = 1;
+ }
+
+ if ( pMDLName )
+ {
+ Q_snprintf( pRelativePath, sizeof(pRelativePath), "models\\%s", pMDLName );
+ SelectMDL( pRelativePath, true, nSelectSecondary );
+ }
+ else
+ {
+ SelectMDL( NULL, true, nSelectSecondary );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Allows external apps to select a MDL
+//-----------------------------------------------------------------------------
+void CMDLPicker::SelectMDL( const char *pRelativePath, bool bDoLookAt, int nSelectSecondary )
+{
+ MDLHandle_t hSelectedMDL = pRelativePath ? vgui::MDLCache()->FindMDL( pRelativePath ) : MDLHANDLE_INVALID;
+ int index = ( nSelectSecondary > 0 ? nSelectSecondary : 0 );
+
+ // We didn't change models after all...
+ if ( hSelectedMDL == m_hSelectedMDL[ index ] )
+ {
+ // vgui::MDLCache()->FindMDL adds a reference by default we don't use, release it again
+ if ( hSelectedMDL != MDLHANDLE_INVALID )
+ {
+ vgui::MDLCache()->Release( hSelectedMDL );
+ }
+ return;
+ }
+
+ m_hSelectedMDL[ index ] = hSelectedMDL;
+
+ if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL[ index ] ) )
+ {
+ m_hSelectedMDL[ index ] = MDLHANDLE_INVALID;
+ }
+ if ( nSelectSecondary != -1 )
+ {
+ m_pMDLPreview->ClearMergeMDLs();
+ for( int i = 1; i < MAX_SELECTED_MODELS; i++ )
+ {
+ if ( i != index )
+ {
+ m_hSelectedMDL[ i ] = MDLHANDLE_INVALID;
+ }
+ }
+ }
+
+ if ( index > 0 )
+ {
+ m_pMDLPreview->SetMergeMDL( m_hSelectedMDL[ index ] );
+ }
+ else
+ {
+ m_pMDLPreview->SetMDL( m_hSelectedMDL[ index ] );
+
+ if ( bDoLookAt )
+ {
+ m_pMDLPreview->LookAtMDL();
+ }
+
+ if ( m_nFlags & ( PAGE_SKINS ) )
+ {
+ UpdateSkinsList();
+ }
+
+ if ( m_nFlags & ( PAGE_INFO ) )
+ {
+ UpdateInfoTab();
+ }
+
+ if ( m_nFlags & (PAGE_ACTIVITIES|PAGE_SEQUENCES) )
+ {
+ RefreshActivitiesAndSequencesList();
+ }
+ }
+
+ // vgui::MDLCache()->FindMDL adds a reference by default we don't use, release it again
+ if ( hSelectedMDL != MDLHANDLE_INVALID )
+ {
+ vgui::MDLCache()->Release( hSelectedMDL );
+ }
+
+ PostActionSignal( new KeyValues( "MDLPreviewChanged", "mdl", pRelativePath ? pRelativePath : "" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: updates revision view on a file being selected
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnCheckButtonChecked(KeyValues *kv)
+{
+// RefreshMDLList();
+ BaseClass::OnCheckButtonChecked( kv );
+ RefreshRenderSettings();
+}
+
+
+void CMDLPicker::GetSelectedMDLName( char *pBuffer, int nMaxLen )
+{
+ Assert( nMaxLen > 0 );
+ if ( GetSelectedAssetCount() > 0 )
+ {
+ Q_snprintf( pBuffer, nMaxLen, "models\\%s", GetSelectedAsset( ) );
+ }
+ else
+ {
+ pBuffer[0] = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Gets the selected activity/sequence
+//-----------------------------------------------------------------------------
+int CMDLPicker::GetSelectedPage( )
+{
+ if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
+ return PAGE_SEQUENCES;
+
+ if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
+ return PAGE_ACTIVITIES;
+
+ return PAGE_NONE;
+}
+
+const char *CMDLPicker::GetSelectedSequenceName()
+{
+ if ( !m_pSequencesPage )
+ return NULL;
+
+ int nIndex = m_pSequencesList->GetSelectedItem( 0 );
+ if ( nIndex >= 0 )
+ {
+ KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
+ return pkv->GetString( "sequence", NULL );
+ }
+
+ return NULL;
+}
+
+const char *CMDLPicker::GetSelectedActivityName()
+{
+ if ( !m_pActivitiesPage )
+ return NULL;
+
+ int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
+ if ( nIndex >= 0 )
+ {
+ KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
+ return pkv->GetString( "activity", NULL );
+ }
+ return NULL;
+}
+
+int CMDLPicker::GetSelectedSkin()
+{
+ if ( !m_pSkinsPage )
+ return 0;
+
+ int nIndex = m_pSkinsList->GetSelectedItem( 0 );
+ if ( nIndex >= 0 )
+ {
+ return nIndex;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Plays the selected activity
+//-----------------------------------------------------------------------------
+void CMDLPicker::SelectActivity( const char *pActivityName )
+{
+ studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
+ 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;
+ }
+ }
+
+ PostActionSignal( new KeyValues( "SequenceSelectionChanged", "activity", pActivityName ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Plays the selected sequence
+//-----------------------------------------------------------------------------
+void CMDLPicker::SelectSequence( const char *pSequenceName )
+{
+ studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
+ 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;
+ }
+ }
+
+ PostActionSignal( new KeyValues( "SequenceSelectionChanged", "sequence", pSequenceName ) );
+}
+
+void CMDLPicker::SelectSkin( int nSkin )
+{
+ m_pMDLPreview->SetSkin( nSkin );
+ PostActionSignal( new KeyValues( "SkinSelectionChanged", "skin", nSkin));
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates preview when an item is selected
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnItemSelected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
+ if ( m_pSequencesList && (pPanel == m_pSequencesList ) )
+ {
+ const char *pSequenceName = GetSelectedSequenceName();
+ if ( pSequenceName )
+ {
+ SelectSequence( pSequenceName );
+ }
+ return;
+ }
+
+ if ( m_pActivitiesList && ( pPanel == m_pActivitiesList ) )
+ {
+ const char *pActivityName = GetSelectedActivityName();
+ if ( pActivityName )
+ {
+ SelectActivity( pActivityName );
+ }
+ return;
+ }
+
+ if ( m_pSkinsList && ( pPanel == m_pSkinsList ) )
+ {
+ int nSelectedSkin = GetSelectedSkin();
+ SelectSkin( nSelectedSkin );
+
+ return;
+ }
+
+ BaseClass::OnItemSelected( kv );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when a page is shown
+//-----------------------------------------------------------------------------
+void CMDLPicker::OnPageChanged( )
+{
+ if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
+ {
+ m_pSequencesList->RequestFocus();
+
+ const char *pSequenceName = GetSelectedSequenceName();
+
+ if ( pSequenceName )
+ {
+ SelectSequence( pSequenceName );
+ }
+ return;
+ }
+
+ if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
+ {
+ m_pActivitiesList->RequestFocus();
+
+ const char *pActivityName = GetSelectedActivityName();
+
+ if ( pActivityName )
+ {
+ SelectActivity( pActivityName );
+ }
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Modal picker frame
+//
+//-----------------------------------------------------------------------------
+CMDLPickerFrame::CMDLPickerFrame( vgui::Panel *pParent, const char *pTitle, int nFlags ) :
+ BaseClass( pParent )
+{
+ SetAssetPicker( new CMDLPicker( this, nFlags ) );
+ LoadControlSettingsAndUserConfig( "resource/mdlpickerframe.res" );
+ SetTitle( pTitle, false );
+}
+
+CMDLPickerFrame::~CMDLPickerFrame()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Allows external apps to select a MDL
+//-----------------------------------------------------------------------------
+void CMDLPickerFrame::SelectMDL( const char *pRelativePath )
+{
+ static_cast<CMDLPicker*>( GetAssetPicker() )->SelectMDL( pRelativePath );
+}
+
+int CMDLPicker::UpdateSkinsList()
+{
+ int nNumSkins = 0;
+
+ if ( m_pSkinsList )
+ {
+ m_pSkinsList->RemoveAll();
+
+ studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
+ if ( hdr )
+ {
+ nNumSkins = hdr->numskinfamilies;
+ for ( int i = 0; i < nNumSkins; i++ )
+ {
+ char skinText[25] = "";
+ sprintf( skinText, "skin%i", i );
+ KeyValues *pkv = new KeyValues("node", "skin", skinText );
+ m_pSkinsList->AddItem( pkv, 0, false, false );
+ }
+ }
+ }
+
+ return nNumSkins;
+}
+
+void CMDLPicker::UpdateInfoTab()
+{
+ studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL[ 0 ] );
+ if ( !hdr )
+ return;
+
+ int nMass = hdr->mass;
+ Panel *pTempPanel = m_pInfoPage->FindChildByName("MassValue");
+ char massBuff[10];
+ Q_snprintf( massBuff, 10, "%d", nMass );
+ ((vgui::Label *)pTempPanel)->SetText( massBuff );
+ bool bIsStatic = hdr->flags & STUDIOHDR_FLAGS_STATIC_PROP;
+ bool bIsPhysics = false;
+ const char* buf = hdr->KeyValueText();
+ Label * pTempLabel = (Label *)m_pInfoPage->FindChildByName("StaticText");
+ pTempLabel->SetVisible( false );
+ if( buf )
+ {
+ buf = Q_strstr( buf, "prop_data" );
+ if ( buf )
+ {
+ int iPropDataCount = UpdatePropDataList( buf, bIsStatic );
+ if( iPropDataCount )
+ {
+ bIsPhysics = true;
+ }
+ }
+ else
+ {
+ m_pPropDataList->RemoveAll();
+ }
+ }
+ else
+ {
+ m_pPropDataList->RemoveAll();
+ }
+
+ CheckButton * pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("StaticObject");
+ pTempCheck->SetCheckButtonCheckable( true );
+ pTempCheck->SetSelected( bIsStatic );
+ pTempCheck->SetCheckButtonCheckable( false );
+ pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("PhysicsObject");
+ pTempCheck->SetCheckButtonCheckable( true );
+ pTempCheck->SetSelected( bIsPhysics );
+ pTempCheck->SetCheckButtonCheckable( false );
+ pTempCheck = (CheckButton *)m_pInfoPage->FindChildByName("DynamicObject");
+ pTempCheck->SetCheckButtonCheckable( true );
+ pTempCheck->SetSelected( !bIsPhysics );
+ pTempCheck->SetCheckButtonCheckable( false );
+
+
+}
+
+int CMDLPicker::UpdatePropDataList( const char* pszPropData, bool &bIsStatic )
+{
+ int iCount = 0;
+
+ if ( m_pPropDataList )
+ {
+ m_pPropDataList->RemoveAll();
+
+ const char * endPropData = strchr( pszPropData, '}' );
+ char keyText[255] = "";
+ char valueText[255] = "";
+ const char *beginChunk = strchr( pszPropData, '\"' );
+ if ( !beginChunk )
+ {
+ return 0;
+ }
+ beginChunk++;
+ const char *endChunk = strchr( beginChunk, '\"' );
+ while( endChunk )
+ {
+ Q_memcpy( keyText, beginChunk, endChunk - beginChunk );
+ beginChunk = endChunk + 1;
+ beginChunk = strchr( beginChunk, '\"' ) + 1;
+ endChunk = strchr( beginChunk, '\"' );
+ Q_memcpy( valueText, beginChunk, endChunk - beginChunk );
+ if( !Q_strcmp( keyText, "allowstatic" ) && !Q_strcmp( valueText , "1" ) )
+ {
+ if ( !bIsStatic )
+ {
+ Label * pTempLabel = (Label *)m_pInfoPage->FindChildByName("StaticText");
+ pTempLabel->SetVisible( true );
+ }
+ bIsStatic &= true;
+ }
+ KeyValues *pkv = new KeyValues("node", "key", keyText, "value", valueText );
+ m_pPropDataList->AddItem( pkv, 0, false, false );
+ Q_memset( keyText, 0, 255 );
+ Q_memset( valueText, 0, 255 );
+ iCount++;
+ beginChunk = endChunk + 1;
+ beginChunk = strchr( beginChunk, '\"' );
+ if ( !beginChunk || beginChunk > endPropData )
+ {
+ return iCount;
+ }
+ beginChunk++;
+ endChunk = strchr( beginChunk, '\"' );
+ }
+ }
+ return iCount;
+}