diff options
Diffstat (limited to 'tools/vmt')
| -rw-r--r-- | tools/vmt/vmt.vpc | 59 | ||||
| -rw-r--r-- | tools/vmt/vmtdoc.cpp | 1078 | ||||
| -rw-r--r-- | tools/vmt/vmtdoc.h | 133 | ||||
| -rw-r--r-- | tools/vmt/vmttool.cpp | 1337 | ||||
| -rw-r--r-- | tools/vmt/vmttool.h | 50 |
5 files changed, 2657 insertions, 0 deletions
diff --git a/tools/vmt/vmt.vpc b/tools/vmt/vmt.vpc new file mode 100644 index 0000000..920503e --- /dev/null +++ b/tools/vmt/vmt.vpc @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// VMT.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin\tools" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,../common" + } + + $Linker + { + $AdditionalDependencies "$BASE Psapi.lib" + } +} + +$Project "Vmt" +{ + $Folder "Source Files" + { + $File "$SRCDIR\public\interpolatortypes.cpp" + $File "$SRCDIR\public\movieobjects\movieobjects.cpp" + $File "$SRCDIR\public\registry.cpp" + $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" + $File "vmtdoc.cpp" + $File "vmttool.cpp" + } + + $Folder "Header Files" + { + $File "$SRCDIR\public\interpolatortypes.h" + $File "vmtdoc.h" + $File "vmttool.h" + } + + $Folder "Link Libraries" + { + $Lib datamodel + $Lib dmxloader + $Lib dme_controls + $Lib dmserializers + $Lib mathlib + $Lib matsys_controls + $Lib movieobjects + $Lib sfmobjects + $Lib tier2 + $Lib tier3 + $Lib toolutils + $Lib vgui_controls + } +} diff --git a/tools/vmt/vmtdoc.cpp b/tools/vmt/vmtdoc.cpp new file mode 100644 index 0000000..665d932 --- /dev/null +++ b/tools/vmt/vmtdoc.cpp @@ -0,0 +1,1078 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "vmtdoc.h" +#include "tier1/KeyValues.h" +#include "tier1/utlbuffer.h" +#include "datamodel/dmelement.h" +#include "vmttool.h" +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/ishader.h" +#include "toolutils/enginetools_int.h" +#include "filesystem.h" + + +//----------------------------------------------------------------------------- +// Standard properties +//----------------------------------------------------------------------------- +struct StandardParam_t +{ + const char *m_pParamName; + ShaderParamType_t m_ParamType; + const char *m_pDefaultValue; + const char *m_pWidgetType; + const char *m_pTextType; +}; + +// NOTE: All entries in here must have all-lowercase param names! +static StandardParam_t g_pStandardParams[] = +{ + { "$surfaceprop", SHADER_PARAM_TYPE_STRING, "default", "surfacepropertypicker", "surfacePropertyName" }, + { "%detailtype", SHADER_PARAM_TYPE_STRING, "", "detailtypepicker", "detailTypeName" }, + { "%compilesky", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilehint", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileskip", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileorigin", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileclip", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%playerclip", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilenpcclip", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilenochop", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compiletrigger", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilenolight", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileplayercontrolclip", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileladder", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilewet", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilenodraw", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileinvisible", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilenonsolid", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compiledetail", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compilewater", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { "%compileslime", SHADER_PARAM_TYPE_BOOL, "0", NULL, NULL }, + { NULL, SHADER_PARAM_TYPE_BOOL, NULL, NULL, NULL } +}; + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CVMTDoc::CVMTDoc( IVMTDocCallback *pCallback ) : m_pCallback( pCallback ) +{ + m_hRoot = NULL; + m_pFileName[0] = 0; + m_bDirty = false; + m_pCurrentIShader = NULL; + + KeyValues *pKeyValues = new KeyValues( "Wireframe" ); + m_pScratchMaterial.Init( "VMT Preview", pKeyValues ); + g_pDataModel->InstallNotificationCallback( this ); +} + +CVMTDoc::~CVMTDoc() +{ + if ( m_hRoot.Get() ) + { + RemoveAllShaderParams( m_hRoot ); + } + g_pDataModel->RemoveNotificationCallback( this ); +} + + +//----------------------------------------------------------------------------- +// Inherited from INotifyUI +//----------------------------------------------------------------------------- +void CVMTDoc::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + OnDataChanged( pReason, nNotifySource, nNotifyFlags ); +} + + +//----------------------------------------------------------------------------- +// Gets the file name +//----------------------------------------------------------------------------- +const char *CVMTDoc::GetFileName() +{ + return m_pFileName; +} + +void CVMTDoc::SetFileName( const char *pFileName ) +{ + Q_strncpy( m_pFileName, pFileName, sizeof( m_pFileName ) ); + Q_FixSlashes( m_pFileName ); + SetDirty( true ); +} + + +//----------------------------------------------------------------------------- +// Dirty bits +//----------------------------------------------------------------------------- +void CVMTDoc::SetDirty( bool bDirty ) +{ + m_bDirty = bDirty; +} + +bool CVMTDoc::IsDirty() const +{ + return m_bDirty; +} + + +//----------------------------------------------------------------------------- +// Creates the root element +//----------------------------------------------------------------------------- +bool CVMTDoc::CreateRootElement() +{ + Assert( !m_hRoot.Get() ); + + DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( GetFileName() ); + + // Create the main element + m_hRoot = g_pDataModel->CreateElement( "DmElement", GetFileName(), fileid ); + if ( m_hRoot == DMELEMENT_HANDLE_INVALID ) + return false; + + g_pDataModel->SetFileRoot( fileid, m_hRoot ); + + // Each VMT list needs to have an editortype associated with it so it displays nicely in editors + m_hRoot->SetValue( "editorType", "vmt" ); + m_hRoot->AddAttribute( "proxies", AT_ELEMENT_ARRAY ); + m_hRoot->AddAttribute( "fallbacks", AT_ELEMENT_ARRAY ); + + m_pCallback->RemoveAllToolParameters(); + + // Add standard parameters + for ( int i = 0; g_pStandardParams[i].m_pParamName; ++i ) + { + AddNewShaderParam( m_hRoot, g_pStandardParams[i].m_pParamName, g_pStandardParams[i].m_ParamType, + g_pStandardParams[i].m_pDefaultValue ); + + if ( g_pStandardParams[i].m_pParamName[0] == '%' ) + { + m_pCallback->AddToolParameter( g_pStandardParams[i].m_pParamName, g_pStandardParams[i].m_pWidgetType, g_pStandardParams[i].m_pTextType ); + } + else if ( g_pStandardParams[i].m_pWidgetType || g_pStandardParams[i].m_pTextType ) + { + m_pCallback->RemoveShaderParameter( g_pStandardParams[i].m_pParamName ); + m_pCallback->AddShaderParameter( g_pStandardParams[i].m_pParamName, g_pStandardParams[i].m_pWidgetType, g_pStandardParams[i].m_pTextType ); + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Creates a new VMT +//----------------------------------------------------------------------------- +void CVMTDoc::CreateNew() +{ + Assert( !m_hRoot.Get() ); + + // This is not undoable + CAppDisableUndoScopeGuard guard( "CVMTDoc::CreateNew", NOTIFY_CHANGE_OTHER ); + + Q_strncpy( m_pFileName, "untitled", sizeof( m_pFileName ) ); + + // Create the main element + if ( !CreateRootElement() ) + return; + + m_pPreviewMaterial.Init( m_pScratchMaterial ); + + SetShader( "wireframe" ); + SetDirty( false ); +} + + +//----------------------------------------------------------------------------- +// Copies VMT parameters into the root +//----------------------------------------------------------------------------- +void CVMTDoc::CopyParamsFromVMT( CDmElement *pVMT ) +{ + // First, set the shader parameters + SetShader( pVMT->GetValueString( "shader" ) ); + + // Now, copy the shader parameters over + CDmAttribute* pSrc; + CDmAttribute* pDst; + for ( pSrc = pVMT->FirstAttribute(); pSrc; pSrc = pSrc->NextAttribute() ) + { + // Only copy shader parameters + if ( !IsShaderParam( pSrc ) ) + continue; + + // Adds the attribute if it doesn't exist + const char *pSrcName = pSrc->GetName(); + if ( !m_hRoot->HasAttribute( pSrcName ) ) + { + m_hRoot->AddAttribute( pSrcName, pSrc->GetType() ); + } + pDst = m_hRoot->GetAttribute( pSrcName ); + pDst->AddFlag( FATTRIB_USERDEFINED ); + + DmAttributeType_t srcType = pSrc->GetType(); + DmAttributeType_t dstType = pDst->GetType(); + if ( dstType == srcType ) + { + pDst->SetValue( pSrc ); + continue; + } + + // Certain type conversions are allowed + switch( dstType ) + { + case AT_BOOL: + if ( srcType == AT_INT ) + { + pDst->SetValue( pSrc ); + } + break; + + case AT_INT: + if ( srcType == AT_BOOL ) + { + pDst->SetValue( pSrc ); + } + break; + + case AT_COLOR: + if ( srcType == AT_VECTOR3 ) + { + Color c; + int r, g, b; + Vector v = pSrc->GetValue<Vector>( ); + v *= 255.0f; + r = clamp( v[0], 0, 255 ); + g = clamp( v[1], 0, 255 ); + b = clamp( v[2], 0, 255 ); + c.SetColor( r, g, b, 255 ); + pDst->SetValue( c ); + } + break; + } + } + + // Any shader parameter that isn't in the VMT make undefined + for ( pDst = m_hRoot->FirstAttribute(); pDst; pDst = pDst->NextAttribute() ) + { + if ( !IsShaderParam( pDst ) ) + continue; + + if ( !pVMT->HasAttribute( pDst->GetName() ) ) + { + // Special hack for alpha + colors + if ( !Q_stricmp( pDst->GetName(), "$alpha" ) ) + { + pDst->SetValue( 1.0f ); + } + else if ( pDst->GetType() == AT_COLOR ) + { + Color c( 255, 255, 255, 255 ); + pDst->SetValue( c ); + } + else + { + pDst->SetToDefaultValue(); + } + } + } +} + + +//----------------------------------------------------------------------------- +// Hooks the preview to an existing material, if there is one +//----------------------------------------------------------------------------- +void CVMTDoc::SetupPreviewMaterial( ) +{ + // Extract a material name from the material + char pLocalName[MAX_PATH]; + + // relative paths can be passed in for in-game material picking + if ( !g_pFileSystem->FullPathToRelativePath( m_pFileName, pLocalName, sizeof(pLocalName) ) ) + { + Q_strcpy( pLocalName, m_pFileName ); + } + + if ( Q_strnicmp( pLocalName, "materials", 9 ) ) + goto noMaterialConnection; + + // Skip the '/' also + char pMaterialName[MAX_PATH]; + Q_StripExtension( pLocalName + 10, pMaterialName, sizeof(pMaterialName) ); + IMaterial *pMaterial = g_pMaterialSystem->FindMaterial( pMaterialName, "Editable material", false ); + if ( !pMaterial || pMaterial->IsErrorMaterial() ) + goto noMaterialConnection; + + m_pPreviewMaterial.Init( pMaterial ); + return; + +noMaterialConnection: + m_pPreviewMaterial.Init( m_pScratchMaterial ); +} + + +//----------------------------------------------------------------------------- +// Saves/loads from file +//----------------------------------------------------------------------------- +bool CVMTDoc::LoadFromFile( const char *pFileName ) +{ + Assert( !m_hRoot.Get() ); + + SetDirty( false ); + + Q_strncpy( m_pFileName, pFileName, sizeof( m_pFileName ) ); + if ( !m_pFileName[0] ) + return false; + + // This is not undoable + CAppDisableUndoScopeGuard guard( "CVMTDoc::LoadFromFile", NOTIFY_CHANGE_OTHER ); + + // Create the main element + if ( !CreateRootElement() ) + return false; + + // change the filename of all the elements under the root, so we can unload the imported elements later + DmFileId_t rootFileId = g_pDataModel->GetFileId( m_pFileName ); + g_pDataModel->SetFileName( rootFileId, "<temp>" ); + + // This will allow us to edit in context! + SetupPreviewMaterial( ); + + CDmElement *pIVMT = NULL; + g_pDataModel->RestoreFromFile( m_pFileName, NULL, "vmt", &pIVMT ); + CDmElement *pVMT = CastElement< CDmElement >( pIVMT ); + if ( !pVMT ) + return false; + + // FIXME: This is necessary so that all shader parameters appear in + // the same order, with the same type, as what you'd get using File->New. + // If we added a dependency to the material system into dmserializers, + // we could avoid this work here (I think!). + CopyParamsFromVMT( pVMT ); + + // unload the imported elements and change the root's filename back + DmFileId_t vmtFileId = g_pDataModel->GetFileId( m_pFileName ); + g_pDataModel->RemoveFileId( vmtFileId ); + g_pDataModel->SetFileName( rootFileId, m_pFileName ); + + SetDirty( false ); + return true; +} + +//----------------------------------------------------------------------------- +// Prior to saving to disk, extract all shader parameters which == the default +//----------------------------------------------------------------------------- +CDmElement* CVMTDoc::ExtractDefaultParameters( ) +{ + CDmElement *pMaterial = m_hRoot->Copy( ); + + CDmAttribute* pAttribute = pMaterial->FirstAttribute(); + CDmAttribute* pNextAttribute = NULL; + for ( ; pAttribute; pAttribute = pNextAttribute ) + { + pNextAttribute = pAttribute->NextAttribute(); + + const char *pShaderParam = pAttribute->GetName(); + + // Check for standard params + int i; + for ( i = 0; g_pStandardParams[i].m_pParamName != NULL; ++i ) + { + if ( !Q_stricmp( g_pStandardParams[i].m_pParamName, pShaderParam ) ) + { + char temp[512]; + CUtlBuffer buf( temp, sizeof(temp), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + pAttribute->Serialize( buf ); + + if ( !Q_stricmp( (char*)buf.Base(), g_pStandardParams[i].m_pDefaultValue ) ) + { + // Buffers match! Therefore it's still using the default parameter + pMaterial->RemoveAttributeByPtr( pAttribute ); + } + break; + } + } + + // Standard attribute found, continue + if ( g_pStandardParams[i].m_pParamName ) + continue; + + // Only remove shader parameters + if ( !IsShaderParam( pAttribute ) ) + continue; + + // Remove flags whose value is 0 + int nCount = g_pMaterialSystem->ShaderFlagCount(); + for ( i = 0; i < nCount; ++i ) + { + const char *pFlagName = g_pMaterialSystem->ShaderFlagName( i ); + if ( !Q_stricmp( pShaderParam, pFlagName ) ) + break; + } + + // It's a flag! Remove the attribute if its value is 0 + if ( i != nCount ) + { + if ( pAttribute->GetValue<bool>( ) == 0 ) + { + pMaterial->RemoveAttributeByPtr( pAttribute ); + } + continue; + } + + // FIXME: We can't do this.. the defaults in the strings need to be changed to + // make it so they actually match the true defaults + continue; + + // Remove parameters which match the default value + nCount = m_pCurrentIShader->GetNumParams(); + for ( i = 0; i < nCount; ++i ) + { + // FIXME: Check type matches + if ( Q_stricmp( pShaderParam, m_pCurrentIShader->GetParamName( i ) ) ) + continue; + + // NOTE: This isn't particularly efficient. Too bad! + // It's hard to do efficiently owing to all the import conversion + char temp[512]; + char temp2[512]; + CUtlBuffer buf( temp, sizeof(temp), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + CUtlBuffer buf2( temp2, sizeof(temp2), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + pAttribute->Serialize( buf ); + SetAttributeValueFromDefault( pMaterial, pAttribute, m_pCurrentIShader->GetParamDefault( i ) ); + pAttribute->Serialize( buf2 ); + + if ( ( buf.TellMaxPut() == buf2.TellMaxPut() ) && !memcmp( buf.Base(), buf2.Base(), buf.TellMaxPut() ) ) + { + // Buffers match! Therefore it's still using the default parameter + pMaterial->RemoveAttributeByPtr( pAttribute ); + } + else + { + // Restore the actual value + pAttribute->Unserialize( buf ); + } + break; + } + } + + return pMaterial; +} + + +//----------------------------------------------------------------------------- +// Saves to disk +//----------------------------------------------------------------------------- +bool CVMTDoc::SaveToFile( ) +{ + if ( m_hRoot.Get() && m_pFileName && m_pFileName[0] ) + { + CDisableUndoScopeGuard guard; + CDmElement *pSaveRoot = ExtractDefaultParameters(); + bool bOk = g_pDataModel->SaveToFile( m_pFileName, NULL, "keyvalues", "vmt", pSaveRoot ); + DestroyElement( pSaveRoot, TD_DEEP ); + if ( !bOk ) + return false; + } + + SetDirty( false ); + return true; +} + + +//----------------------------------------------------------------------------- +// Finds a shader +//----------------------------------------------------------------------------- +IShader *CVMTDoc::FindShader( const char *pShaderName ) +{ + int nCount = g_pMaterialSystem->ShaderCount(); + IShader **ppShaderList = (IShader**)_alloca( nCount * sizeof(IShader*) ); + g_pMaterialSystem->GetShaders( 0, nCount, ppShaderList ); + for ( int i = 0; i < nCount; ++i ) + { + if ( !Q_stricmp( pShaderName, ppShaderList[i]->GetName() ) ) + return ppShaderList[i]; + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Is this attribute a shader parameter? +//----------------------------------------------------------------------------- +bool CVMTDoc::IsShaderParam( CDmAttribute* pAttribute ) +{ + const char *pName = pAttribute->GetName(); + + // Shader params start with a $ or % + if ( pName[0] != '$' && pName[0] != '%' ) + return false; + + // Don't remove name, type, or id + if ( pAttribute->IsFlagSet( FATTRIB_STANDARD ) ) + return false; + + // All shader params have USERDEFINED set + if ( !pAttribute->IsFlagSet( FATTRIB_USERDEFINED ) ) + return false; + + // Don't remove arrays... those aren't shader parameters + if ( pAttribute->GetType() == AT_ELEMENT_ARRAY ) + return false; + + // Standard params aren't counted here + for ( int i = 0; g_pStandardParams[i].m_pParamName; ++i ) + { + if ( !Q_stricmp( g_pStandardParams[i].m_pParamName, pName ) ) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Remove all shader parameters +//----------------------------------------------------------------------------- +void CVMTDoc::RemoveAllShaderParams( CDmElement *pMaterial ) +{ + CDmAttribute* pAttribute; + CDmAttribute* pNextAttribute = NULL; + for ( pAttribute = pMaterial->FirstAttribute(); pAttribute; pAttribute = pNextAttribute ) + { + pNextAttribute = pAttribute->NextAttribute(); + + // Only remove shader parameters + if ( !IsShaderParam( pAttribute ) ) + continue; + + m_pCallback->RemoveShaderParameter( pAttribute->GetName() ); + pMaterial->RemoveAttributeByPtr( pAttribute ); + } +} + + +//----------------------------------------------------------------------------- +// Remove all shader parameters that don't exist in the new shader +//----------------------------------------------------------------------------- +void CVMTDoc::RemoveUnusedShaderParams( CDmElement *pMaterial, IShader *pShader, IShader *pOldShader ) +{ + CDmAttribute* pAttribute = pMaterial->FirstAttribute(); + CDmAttribute* pNextAttribute = NULL; + for ( ; pAttribute; pAttribute = pNextAttribute ) + { + pNextAttribute = pAttribute->NextAttribute(); + + // Only remove shader parameters + if ( !IsShaderParam( pAttribute ) ) + continue; + + // Don't remove flags + int nCount = g_pMaterialSystem->ShaderFlagCount(); + int i; + for ( i = 0; i < nCount; ++i ) + { + const char *pFlagName = g_pMaterialSystem->ShaderFlagName( i ); + if ( !Q_stricmp( pAttribute->GetName(), pFlagName ) ) + break; + } + + if ( i != nCount ) + continue; + + const char *pShaderParam = pAttribute->GetName(); + + // Remove parameters we've currently got but which don't exist in the new shader + nCount = pShader->GetNumParams(); + for ( i = 0; i < nCount; ++i ) + { + // FIXME: Check type matches + if ( !Q_stricmp( pShaderParam, pShader->GetParamName( i ) ) ) + break; + } + + // No match? Remove it! + if ( i == nCount ) + { + m_pCallback->RemoveShaderParameter( pAttribute->GetName() ); + pMaterial->RemoveAttributeByPtr( pAttribute ); + continue; + } + + // Remove parameters from the old shader which match the default value + // This will make the default values update to the new shader's defaults + if ( pOldShader ) + { + nCount = pOldShader->GetNumParams(); + for ( i = 0; i < nCount; ++i ) + { + // FIXME: Check type matches + if ( Q_stricmp( pShaderParam, pOldShader->GetParamName( i ) ) ) + continue; + + // NOTE: This isn't particularly efficient. Too bad! + // It's hard to do efficiently owing to all the import conversion + char temp1[512]; + char temp2[512]; + CUtlBuffer buf1( temp1, sizeof(temp1), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + CUtlBuffer buf2( temp2, sizeof(temp2), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + pAttribute->Serialize( buf1 ); + SetAttributeValueFromDefault( pMaterial, pAttribute, pOldShader->GetParamDefault( i ) ); + pAttribute->Serialize( buf2 ); + + if ( ( buf1.TellMaxPut() == buf2.TellMaxPut() ) && !memcmp( buf1.Base(), buf2.Base(), buf1.TellMaxPut() ) ) + { + // Buffers match! Therefore it's still using the default parameter + m_pCallback->RemoveShaderParameter( pAttribute->GetName() ); + pMaterial->RemoveAttributeByPtr( pAttribute ); + } + else + { + pAttribute->Unserialize( buf1 ); + } + break; + } + } + } +} + + +//----------------------------------------------------------------------------- +// Add attribute for shader parameter +//----------------------------------------------------------------------------- +CDmAttribute* CVMTDoc::AddAttributeForShaderParameter( CDmElement *pMaterial, const char *pParamName, ShaderParamType_t paramType ) +{ + CDmAttribute *pAttribute = NULL; + switch ( paramType ) + { + case SHADER_PARAM_TYPE_INTEGER: + pAttribute = pMaterial->AddAttribute( pParamName, AT_INT ); + break; + + case SHADER_PARAM_TYPE_BOOL: + pAttribute = pMaterial->AddAttribute( pParamName, AT_BOOL ); + break; + + case SHADER_PARAM_TYPE_FLOAT: + pAttribute = pMaterial->AddAttribute( pParamName, AT_FLOAT ); + break; + + case SHADER_PARAM_TYPE_STRING: + pAttribute = pMaterial->AddAttribute( pParamName, AT_STRING ); + break; + + case SHADER_PARAM_TYPE_COLOR: + pAttribute = pMaterial->AddAttribute( pParamName, AT_COLOR ); + break; + + case SHADER_PARAM_TYPE_VEC2: + pAttribute = pMaterial->AddAttribute( pParamName, AT_VECTOR2 ); + break; + + case SHADER_PARAM_TYPE_VEC3: + pAttribute = pMaterial->AddAttribute( pParamName, AT_VECTOR3 ); + break; + + case SHADER_PARAM_TYPE_VEC4: + pAttribute = pMaterial->AddAttribute( pParamName, AT_VECTOR4 ); + break; + + case SHADER_PARAM_TYPE_FOURCC: + Assert( 0 ); + break; + + case SHADER_PARAM_TYPE_MATRIX: + pAttribute = pMaterial->AddAttribute( pParamName, AT_VMATRIX ); + break; + + case SHADER_PARAM_TYPE_TEXTURE: + pAttribute = pMaterial->AddAttribute( pParamName, AT_STRING ); + m_pCallback->AddShaderParameter( pParamName, "vtfpicker", "vtfName" ); + break; + + case SHADER_PARAM_TYPE_MATERIAL: + pAttribute = pMaterial->AddAttribute( pParamName, AT_STRING ); + m_pCallback->AddShaderParameter( pParamName, "vmtpicker", "vmtName" ); + break; + + default: + break; + } + + if ( pAttribute ) + { + pAttribute->AddFlag( FATTRIB_USERDEFINED ); + } + + return pAttribute; +} + + +//----------------------------------------------------------------------------- +// A couple methods to set vmatrix param values from strings (OLD METHOD!) +//----------------------------------------------------------------------------- +bool CVMTDoc::SetVMatrixParamValue( CDmAttribute *pAttribute, const char *pValue ) +{ + // FIXME: Change default strings to match DME? + // Then we could remove this crap + VMatrix mat; + int count = sscanf( pValue, " [ %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ]", + &mat.m[0][0], &mat.m[0][1], &mat.m[0][2], &mat.m[0][3], + &mat.m[1][0], &mat.m[1][1], &mat.m[1][2], &mat.m[1][3], + &mat.m[2][0], &mat.m[2][1], &mat.m[2][2], &mat.m[2][3], + &mat.m[3][0], &mat.m[3][1], &mat.m[3][2], &mat.m[3][3] ); + if (count == 16) + { + pAttribute->SetValue( mat ); + return true; + } + + Vector2D scale, center; + float angle; + Vector2D translation; + count = sscanf( pValue, " center %f %f scale %f %f rotate %f translate %f %f", + ¢er.x, ¢er.y, &scale.x, &scale.y, &angle, &translation.x, &translation.y ); + if (count != 7) + return false; + + VMatrix temp; + MatrixBuildTranslation( mat, -center.x, -center.y, 0.0f ); + MatrixBuildScale( temp, scale.x, scale.y, 1.0f ); + MatrixMultiply( temp, mat, mat ); + MatrixBuildRotateZ( temp, angle ); + MatrixMultiply( temp, mat, mat ); + MatrixBuildTranslation( temp, center.x + translation.x, center.y + translation.y, 0.0f ); + MatrixMultiply( temp, mat, mat ); + pAttribute->SetValue( mat ); + return true; +} + + +//----------------------------------------------------------------------------- +// A couple methods to set vmatrix param values from strings (OLD METHOD!) +//----------------------------------------------------------------------------- +bool CVMTDoc::SetVector2DParamValue( CDmAttribute *pAttribute, const char *pValue ) +{ + Vector2D vec; + int count = sscanf( pValue, " [ %f %f ]", &vec[0], &vec[1] ); + if ( count == 2 ) + { + pAttribute->SetValue( vec ); + return true; + } + + count = sscanf( pValue, " { %f %f }", &vec[0], &vec[1] ); + if ( count == 2 ) + { + vec /= 255.0f; + pAttribute->SetValue( vec ); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// A couple methods to set vmatrix param values from strings (OLD METHOD!) +//----------------------------------------------------------------------------- +bool CVMTDoc::SetVector3DParamValue( CDmAttribute *pAttribute, const char *pValue ) +{ + Vector vec; + int count = sscanf( pValue, " [ %f %f %f ]", &vec[0], &vec[1], &vec[2] ); + if ( count == 3 ) + { + pAttribute->SetValue( vec ); + return true; + } + + count = sscanf( pValue, " { %f %f %f }", &vec[0], &vec[1], &vec[2] ); + if ( count == 3 ) + { + vec /= 255.0f; + pAttribute->SetValue( vec ); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// A couple methods to set vmatrix param values from strings (OLD METHOD!) +//----------------------------------------------------------------------------- +bool CVMTDoc::SetVector4DParamValue( CDmAttribute *pAttribute, const char *pValue ) +{ + Vector4D vec; + int count = sscanf( pValue, " [ %f %f %f %f ]", &vec[0], &vec[1], &vec[2], &vec[3] ); + if ( count == 4 ) + { + pAttribute->SetValue( vec ); + return true; + } + + count = sscanf( pValue, " { %f %f %f %f }", &vec[0], &vec[1], &vec[2], &vec[3] ); + if ( count == 4 ) + { + vec /= 255.0f; + pAttribute->SetValue( vec ); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// A couple methods to set vmatrix param values from strings (OLD METHOD!) +//----------------------------------------------------------------------------- +bool CVMTDoc::SetColorParamValue( CDmAttribute *pAttribute, const char *pValue ) +{ + Color c; + int r, g, b; + Vector vec; + int count = sscanf( pValue, " [ %f %f %f ]", &vec[0], &vec[1], &vec[2] ); + if ( count == 3 ) + { + vec *= 255.0f; + r = clamp( vec[0], 0, 255 ); + g = clamp( vec[1], 0, 255 ); + b = clamp( vec[2], 0, 255 ); + c.SetColor( r, g, b, 255 ); + pAttribute->SetValue( c ); + return true; + } + + count = sscanf( pValue, " { %d %d %d }", &r, &g, &b ); + if ( count == 3 ) + { + c.SetColor( r, g, b, 255 ); + pAttribute->SetValue( c ); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Sets an attribute value from the shader param default +//----------------------------------------------------------------------------- +void CVMTDoc::SetAttributeValueFromDefault( CDmElement *pMaterial, CDmAttribute *pAttribute, const char *pValue ) +{ + // FIXME: Change default strings to match DME? + // Then we could remove this crap + switch ( pAttribute->GetType() ) + { + case AT_VMATRIX: + if ( SetVMatrixParamValue( pAttribute, pValue ) ) + return; + break; + case AT_COLOR: + if ( SetColorParamValue( pAttribute, pValue ) ) + return; + break; + case AT_VECTOR2: + if ( SetVector2DParamValue( pAttribute, pValue ) ) + return; + break; + case AT_VECTOR3: + if ( SetVector3DParamValue( pAttribute, pValue ) ) + return; + break; + case AT_VECTOR4: + if ( SetVector4DParamValue( pAttribute, pValue ) ) + return; + break; + } + + pMaterial->SetValueFromString( pAttribute->GetName(), pValue ); +} + + +//----------------------------------------------------------------------------- +// Add a single shader parameter if it doesn't exist +//----------------------------------------------------------------------------- +void CVMTDoc::AddNewShaderParam( CDmElement *pMaterial, const char *pParamName, ShaderParamType_t paramType, const char *pValue ) +{ + char temp[512]; + Q_strncpy( temp, pParamName, sizeof(temp) ); + Q_strlower( temp ); + pParamName = temp; + + CDmAttribute* pAttribute = NULL; + for ( pAttribute = pMaterial->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() ) + { + // Don't bother testing against name, type, or id + if ( pAttribute->IsFlagSet( FATTRIB_STANDARD ) ) + continue; + + const char *pAttributeName = pAttribute->GetName(); + if ( !Q_stricmp( pAttributeName, pParamName ) ) + return; + } + + // No match? Add it! + pAttribute = AddAttributeForShaderParameter( pMaterial, pParamName, paramType ); + if ( pAttribute ) + { + SetAttributeValueFromDefault( pMaterial, pAttribute, pValue ); + } +} + + +//----------------------------------------------------------------------------- +// Add all shader parameters that don't currently exist +//----------------------------------------------------------------------------- +void CVMTDoc::AddNewShaderParams( CDmElement *pMaterial, IShader *pShader ) +{ + // First add all flags + m_pCallback->RemoveAllFlagParameters(); + int nCount = g_pMaterialSystem->ShaderFlagCount(); + int i; + for ( i = 0; i < nCount; ++i ) + { + const char *pParamName = g_pMaterialSystem->ShaderFlagName( i ); + AddNewShaderParam( pMaterial, pParamName, SHADER_PARAM_TYPE_BOOL, "0" ); + m_pCallback->AddFlagParameter( pParamName ); + } + + // Next add all shader-specific parameters + nCount = pShader->GetNumParams(); + for ( i = 0; i < nCount; ++i ) + { + const char *pParamName = pShader->GetParamName( i ); + + // Don't add parameters that don't want to be editable + if ( pShader->GetParamFlags( i ) & SHADER_PARAM_NOT_EDITABLE ) + continue; + + ShaderParamType_t paramType = pShader->GetParamType( i ); + const char *pDefault = pShader->GetParamDefault( i ); + AddNewShaderParam( pMaterial, pParamName, paramType, pDefault ); + } +} + + +//----------------------------------------------------------------------------- +// Sets shader parameters to the default for that shader +//----------------------------------------------------------------------------- +void CVMTDoc::SetParamsToDefault() +{ + // This is undoable + CAppUndoScopeGuard guard( 0, "Set Params to Default", "Set Params to Default" ); + + // Next add all shader-specific parameters + int nCount = m_pCurrentIShader->GetNumParams(); + for ( int i = 0; i < nCount; ++i ) + { + const char *pParamName = m_pCurrentIShader->GetParamName( i ); + + // Don't set parameters that don't want to be editable + if ( m_pCurrentIShader->GetParamFlags( i ) & SHADER_PARAM_NOT_EDITABLE ) + continue; + + char pAttributeName[512]; + Q_strncpy( pAttributeName, pParamName, sizeof(pAttributeName) ); + Q_strlower( pAttributeName ); + + if ( !m_hRoot->HasAttribute( pAttributeName ) ) + continue; + + CDmAttribute *pAttribute = m_hRoot->GetAttribute( pAttributeName ); + const char *pDefault = m_pCurrentIShader->GetParamDefault( i ); + SetAttributeValueFromDefault( m_hRoot, pAttribute, pDefault ); + } +} + + +//----------------------------------------------------------------------------- +// Sets the shader in the material +//----------------------------------------------------------------------------- +void CVMTDoc::SetShader( const char *pShaderName ) +{ + // No change? don't bother + if ( !Q_stricmp( m_CurrentShader, pShaderName ) ) + return; + + m_CurrentShader = pShaderName; + + // This is undoable + CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Set Shader", "Set Shader" ); + + char pActualShaderName[512]; + g_pMaterialSystem->GetShaderFallback( pShaderName, pActualShaderName, sizeof(pActualShaderName) ); + + m_hRoot->SetValue( "shader", pShaderName ); + + // First, find the shader + IShader *pShader = FindShader( pActualShaderName ); + + // Remove all shader parameters that don't exist in the new shader + // And also remove shader parameters that do match the default value + RemoveUnusedShaderParams( m_hRoot, pShader, m_pCurrentIShader ); + + // Add all shader parameters that don't currently exist + AddNewShaderParams( m_hRoot, pShader ); + + m_pCurrentIShader = pShader; +} + + +//----------------------------------------------------------------------------- +// Gets the preview material +//----------------------------------------------------------------------------- +IMaterial *CVMTDoc::GetPreviewMaterial() +{ + return m_pPreviewMaterial; +} + + +//----------------------------------------------------------------------------- +// Updates the preview material +//----------------------------------------------------------------------------- +void CVMTDoc::UpdatePreviewMaterial() +{ + if ( !m_hRoot.Get() ) + return; + + // Update all shader parameters + SetShader( m_hRoot->GetValueString( "shader" ) ); + + // Use the file conversion to write to a text format + char buf[1024]; + CUtlBuffer vmtBuf( buf, sizeof(buf), CUtlBuffer::TEXT_BUFFER | CUtlBuffer::EXTERNAL_GROWABLE ); + g_pDataModel->Serialize( vmtBuf, "vmt", "vmt", m_hRoot ); + + // Now use the text format to create a keyvalues + KeyValues *pVMTKeyValues = new KeyValues( "ShaderName" ); + pVMTKeyValues->LoadFromBuffer( "VMT Preview", vmtBuf, g_pFileSystem, "GAME" ); + + // Finally, hook the keyvalues into the material. + m_pPreviewMaterial->SetShaderAndParams( pVMTKeyValues ); + pVMTKeyValues->deleteThis(); +} + + +//----------------------------------------------------------------------------- +// Returns the root object +//----------------------------------------------------------------------------- +CDmElement *CVMTDoc::GetRootObject() +{ + return m_hRoot; +} + + +//----------------------------------------------------------------------------- +// Called when data changes +//----------------------------------------------------------------------------- +void CVMTDoc::OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + SetDirty( nNotifyFlags & NOTIFY_SETDIRTYFLAG ? true : false ); + UpdatePreviewMaterial(); + m_pCallback->OnDocChanged( pReason, nNotifySource, nNotifyFlags ); +} diff --git a/tools/vmt/vmtdoc.h b/tools/vmt/vmtdoc.h new file mode 100644 index 0000000..8b9d876 --- /dev/null +++ b/tools/vmt/vmtdoc.h @@ -0,0 +1,133 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef VMTDOC_H +#define VMTDOC_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "dme_controls/inotifyui.h" +#include "datamodel/dmehandle.h" +#include "materialsystem/MaterialSystemUtil.h" +#include "tier1/utlstring.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class IVMTDocCallback; +class IShader; +enum ShaderParamType_t; +class IMaterial; +class IShader; + + +//----------------------------------------------------------------------------- +// Contains all editable state +//----------------------------------------------------------------------------- +class CVMTDoc : public IDmNotify +{ +public: + CVMTDoc( IVMTDocCallback *pCallback ); + ~CVMTDoc(); + + // Inherited from INotifyUI + virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + + // Sets/Gets the file name + const char *GetFileName(); + void SetFileName( const char *pFileName ); + + // Dirty bits (has it changed since the last time it was saved?) + void SetDirty( bool bDirty ); + bool IsDirty() const; + + // Creates a new act busy list + void CreateNew(); + + // Saves/loads from file + bool LoadFromFile( const char *pFileName ); + bool SaveToFile( ); + + // Returns the root object + CDmElement *GetRootObject(); + + // Called when data changes (see INotifyUI for flags) + void OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + + // Sets the shader in the material + void SetShader( const char *pShaderName ); + + // Gets the preview material + IMaterial *GetPreviewMaterial(); + + // Sets shader parameters to the default for that shader + void SetParamsToDefault(); + +private: + // Creates the root element + bool CreateRootElement(); + + // Add attribute for shader parameter + CDmAttribute* AddAttributeForShaderParameter( CDmElement *pMaterial, const char *pParamName, ShaderParamType_t paramType ); + + // Add a single shader parameter if it doesn't exist + void AddNewShaderParam( CDmElement *pMaterial, const char *pParamName, ShaderParamType_t paramType, const char *pValue ); + + // Add all shader parameters that don't currently exist + void AddNewShaderParams( CDmElement *pMaterial, IShader *pShader ); + + // Is this attribute a shader parameter? + bool IsShaderParam( CDmAttribute* pAttribute ); + + // Remove all shader parameters that don't exist in the new shader + void RemoveUnusedShaderParams( CDmElement *pMaterial, IShader *pShader, IShader *pOldShader ); + + // Remove all shader parameters + void RemoveAllShaderParams( CDmElement *pMaterial ); + + // Finds a shader + IShader *FindShader( const char *pShaderName ); + + // Updates the preview material + void UpdatePreviewMaterial(); + + // Copies VMT parameters into the root + void CopyParamsFromVMT( CDmElement *pVMT ); + + // A couple methods to set param values from strings (OLD METHOD!) + bool SetVMatrixParamValue( CDmAttribute *pAttribute, const char *pValue ); + bool SetVector2DParamValue( CDmAttribute *pAttribute, const char *pValue ); + bool SetVector3DParamValue( CDmAttribute *pAttribute, const char *pValue ); + bool SetVector4DParamValue( CDmAttribute *pAttribute, const char *pValue ); + bool SetColorParamValue( CDmAttribute *pAttribute, const char *pValue ); + + // Sets an attribute value from the shader param default + void SetAttributeValueFromDefault( CDmElement *pMaterial, CDmAttribute *pAttribute, const char *pValue ); + + // Hooks the preview to an existing material, if there is one + void SetupPreviewMaterial( ); + + // Prior to saving to disk, extract all shader parameters which == the default + CDmElement* ExtractDefaultParameters( ); + + IVMTDocCallback *m_pCallback; + CMaterialReference m_pScratchMaterial; + CMaterialReference m_pPreviewMaterial; + CDmeHandle< CDmElement > m_hRoot; + CUtlString m_CurrentShader; + IShader *m_pCurrentIShader; + char m_pFileName[512]; + bool m_bDirty; +}; + + +#endif // VMTDOC_H diff --git a/tools/vmt/vmttool.cpp b/tools/vmt/vmttool.cpp new file mode 100644 index 0000000..a42f672 --- /dev/null +++ b/tools/vmt/vmttool.cpp @@ -0,0 +1,1337 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Act busy tool; main UI smarts class +// +//============================================================================= + +#include "toolutils/basetoolsystem.h" +#include "toolutils/toolmenubar.h" +#include "toolutils/toolswitchmenubutton.h" +#include "toolutils/toolfilemenubutton.h" +#include "toolutils/tooleditmenubutton.h" +#include "toolutils/toolmenubutton.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "toolutils/enginetools_int.h" +#include "toolframework/ienginetool.h" +#include "vgui/IInput.h" +#include "vgui/KeyCode.h" +#include "vgui_controls/FileOpenDialog.h" +#include "filesystem.h" +#include "vmtdoc.h" +#include "vgui/ilocalize.h" +#include "dme_controls/elementpropertiestree.h" +#include "matsys_controls/vmtpanel.h" +#include "vmttool.h" +#include "movieobjects/dmeeditortypedictionary.h" +#include "dme_controls/attributestringchoicepanel.h" +#include "matsys_controls/mdlsequencepicker.h" +#include "istudiorender.h" +#include "materialsystem/imaterialsystem.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "toolutils/toolwindowfactory.h" +#include "toolutils/basepropertiescontainer.h" +#include "toolutils/savewindowpositions.h" +#include "tier3/tier3.h" +#include "tier2/fileutils.h" +#include "vgui/ivgui.h" + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// Singleton interfaces +//----------------------------------------------------------------------------- +CDmeEditorTypeDictionary *g_pEditorTypeDict; + + +//----------------------------------------------------------------------------- +// Methods needed by scenedatabase. They have to live here instead of toolutils +// because this is a DLL but toolutils is only a static library +//----------------------------------------------------------------------------- +char const *GetVGuiControlsModuleName() +{ + return "VMTTool"; +} + +//----------------------------------------------------------------------------- +// Connect, disconnect +//----------------------------------------------------------------------------- +bool ConnectTools( CreateInterfaceFn factory ) +{ + return (g_pMDLCache != NULL) && (studiorender != NULL) && (materials != NULL) && (g_pMatSystemSurface != NULL); +} + +void DisconnectTools( ) +{ +} + + +//----------------------------------------------------------------------------- +// Implementation of the act busy tool +//----------------------------------------------------------------------------- +class CVMTTool : public CBaseToolSystem, public IFileMenuCallbacks, public IVMTDocCallback +{ + DECLARE_CLASS_SIMPLE( CVMTTool, CBaseToolSystem ); + +public: + CVMTTool(); + + // Inherited from IToolSystem + virtual char const *GetToolName() { return "Material Editor"; } + virtual const char *GetBindingsContextFile() { return "cfg/VMTTool.kb"; } + virtual bool Init(); + virtual void Shutdown(); + virtual bool CanQuit( ); + virtual void PostMessage( HTOOLHANDLE hEntity, KeyValues *message ); + + // Inherited from IFileMenuCallbacks + virtual int GetFileMenuItemsEnabled( ); + virtual void AddRecentFilesToMenu( vgui::Menu *menu ); + virtual bool GetPerforceFileName( char *pFileName, int nMaxLen ); + virtual vgui::Panel* GetRootPanel() { return this; } + + // Inherited from IVMTDocCallback + virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ); + virtual void AddShaderParameter( const char *pParam, const char *pWidget, const char *pTextType ); + virtual void RemoveShaderParameter( const char *pParam ); + virtual void AddFlagParameter( const char *pParam ); + virtual void AddToolParameter( const char *pParam, const char *pWidget, const char *pTextType ); + virtual void RemoveAllFlagParameters(); + virtual void RemoveAllToolParameters(); + + // Inherited from CBaseToolSystem + virtual vgui::HScheme GetToolScheme(); + virtual vgui::Menu *CreateActionMenu( vgui::Panel *pParent ); + virtual void OnCommand( const char *cmd ); + virtual const char *GetRegistryName() { return "VMT"; } + virtual vgui::MenuBar *CreateMenuBar( CBaseToolSystem *pParent ); + virtual void OnToolActivate(); + virtual void OnToolDeactivate(); + virtual CVMTDoc *GetDocument(); + virtual CBasePropertiesContainer *GetProperties(); + virtual void SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual bool OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual bool OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ); + virtual void OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues ); + +public: + // Commands related to the file menu + MESSAGE_FUNC( OnNew, "OnNew" ); + MESSAGE_FUNC( OnOpen, "OnOpen" ); + MESSAGE_FUNC( OnSave, "OnSave" ); + MESSAGE_FUNC( OnSaveAs, "OnSaveAs" ); + MESSAGE_FUNC( OnClose, "OnClose" ); + MESSAGE_FUNC( OnCloseNoSave, "OnCloseNoSave" ); + MESSAGE_FUNC( OnMarkNotDirty, "OnMarkNotDirty" ); + MESSAGE_FUNC( OnExit, "OnExit" ); + void PerformNew(); + void OpenFileFromHistory( int slot, const char *pCommand ); + void OpenSpecificFile( const char *pFileName ); + + // Commands related to the edit menu + KEYBINDING_FUNC( undo, KEY_Z, vgui::MODIFIER_CONTROL, OnUndo, "#undo_help", 0 ); + KEYBINDING_FUNC( redo, KEY_Z, vgui::MODIFIER_CONTROL | vgui::MODIFIER_SHIFT, OnRedo, "#redo_help", 0 ); + void OnDescribeUndo(); + + // Methods related to the view menu + MESSAGE_FUNC( OnToggleProperties, "OnToggleProperties" ); + MESSAGE_FUNC( OnToggleVMTPreview, "OnToggleVMTPreview" ); + MESSAGE_FUNC( OnShowFlags, "OnShowFlags" ); + MESSAGE_FUNC( OnShowToolParams, "OnShowToolParams" ); + MESSAGE_FUNC( OnDefaultLayout, "OnDefaultLayout" ); + + // Methods related to the material menu + MESSAGE_FUNC( OnSetParamsToDefault, "OnSetParamsToDefault" ); + + // Returns the VMT preview window + CVMTPanel *GetVMTPreview(); + + // Which parameters are visible? + bool IsFlagParamsVisible() const; + bool IsToolParamsVisible() const; + +private: + // Flags for HideStandardFields + enum EditorTypeStandardFields_t + { + EDITOR_FIELD_NAME = 0x1, + EDITOR_FIELD_TYPE = 0x2, + EDITOR_FIELD_ID = 0x4, + EDITOR_FIELD_EDITORTYPE = 0x8, + }; + + void HideStandardFields( CDmeEditorType *pEditorType, int nFieldFlags ); + + // Creates a new document + void NewDocument( ); + + // Loads up a new document + bool LoadDocument( char const *pDocName ); + + // Updates the menu bar based on the current file + void UpdateMenuBar( ); + + // Shows element properties + void ShowElementProperties( ); + + // Create custom editors + void InitEditorDict(); + + void CreateTools( CVMTDoc *doc ); + void InitTools(); + void DestroyTools(); + + void ToggleToolWindow( Panel *tool, char const *toolName ); + void ShowToolWindow( Panel *tool, char const *toolName, bool visible ); + + void DestroyToolContainers(); + + virtual char const *GetLogoTextureName(); + +private: + // All editable data + CVMTDoc *m_pDoc; + + // The menu bar + CToolFileMenuBar *m_pMenuBar; + + // Element properties for editing material + vgui::DHANDLE< CBasePropertiesContainer > m_hProperties; + + // The sequence picker! + vgui::DHANDLE< CVMTPanel > m_hVMTPreview; + + // The VMT editor type + CDmeEditorType *m_pVMTType; + + // Separate undo context for the act busy tool + CToolWindowFactory< ToolWindow > m_ToolWindowFactory; + + // List of tool + flag parameters + CUtlVector<CUtlString> m_ToolParams; + CUtlVector<CUtlString> m_FlagParams; + + bool m_bToolParamsVisible; + bool m_bFlagParamsVisible; + + CUtlVector< DmElementHandle_t > m_toolElements; +}; + + +//----------------------------------------------------------------------------- +// Singleton +//----------------------------------------------------------------------------- +CVMTTool *g_pVMTTool = NULL; + +void CreateTools() +{ + g_pVMTTool = new CVMTTool(); +} + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CVMTTool::CVMTTool() +{ + m_pVMTType = NULL; + m_pMenuBar = NULL; + m_pDoc = NULL; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CVMTTool::Init() +{ + m_bToolParamsVisible = false; + m_bFlagParamsVisible = true; + m_pDoc = NULL; + m_RecentFiles.LoadFromRegistry( GetRegistryName() ); + + // NOTE: This has to happen before BaseClass::Init + g_pVGuiLocalize->AddFile( "resource/toolvmt_%language%.txt" ); + + if ( !BaseClass::Init() ) + return false; + + InitEditorDict(); + + return true; +} + +void CVMTTool::Shutdown() +{ + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + + { + CDisableUndoScopeGuard sg; + int nElements = m_toolElements.Count(); + for ( int i = 0; i < nElements; ++i ) + { + g_pDataModel->DestroyElement( m_toolElements[ i ] ); + } + } + + BaseClass::Shutdown(); +} + + +//----------------------------------------------------------------------------- +// Tool activation/deactivation +//----------------------------------------------------------------------------- +void CVMTTool::OnToolActivate() +{ + BaseClass::OnToolActivate(); +} + +void CVMTTool::OnToolDeactivate() +{ + BaseClass::OnToolDeactivate(); +} + + +//----------------------------------------------------------------------------- +// Hides standard fields +//----------------------------------------------------------------------------- +void CVMTTool::HideStandardFields( CDmeEditorType *pEditorType, int nFieldFlags ) +{ + CDmeEditorAttributeInfo *pInfo; + + if ( nFieldFlags & EDITOR_FIELD_NAME ) + { + pInfo = CreateElement< CDmeEditorAttributeInfo >( "name info", pEditorType->GetFileId() ); + pEditorType->AddAttributeInfo( "name", pInfo ); + pInfo->m_bIsVisible = false; + m_toolElements.AddToTail( pInfo->GetHandle() ); + } + + if ( nFieldFlags & EDITOR_FIELD_TYPE ) + { + pInfo = CreateElement< CDmeEditorAttributeInfo >( "type info", pEditorType->GetFileId() ); + pInfo->m_bIsVisible = false; + pEditorType->AddAttributeInfo( "type", pInfo ); + m_toolElements.AddToTail( pInfo->GetHandle() ); + } + + if ( nFieldFlags & EDITOR_FIELD_ID ) + { + pInfo = CreateElement< CDmeEditorAttributeInfo >( "id info", pEditorType->GetFileId() ); + pInfo->m_bIsVisible = false; + pEditorType->AddAttributeInfo( "id", pInfo ); + m_toolElements.AddToTail( pInfo->GetHandle() ); + } + + if ( nFieldFlags & EDITOR_FIELD_EDITORTYPE ) + { + pInfo = CreateElement< CDmeEditorAttributeInfo >( "editor type info", pEditorType->GetFileId() ); + pInfo->m_bIsVisible = false; + pEditorType->AddAttributeInfo( "editorType", pInfo ); + m_toolElements.AddToTail( pInfo->GetHandle() ); + } +} + + +//----------------------------------------------------------------------------- +// Update the editor dict based on the current material parameters +//----------------------------------------------------------------------------- +void CVMTTool::AddShaderParameter( const char *pParam, const char *pWidget, const char *pTextType ) +{ + // anims only accept activity names + CDmeEditorAttributeInfo *pInfo = CreateElement< CDmeEditorAttributeInfo >( "shader param info", m_pVMTType->GetFileId() ); + m_pVMTType->AddAttributeInfo( pParam, pInfo ); + pInfo->m_Widget = pWidget; + if ( pTextType ) + { + pInfo->SetValue( "texttype", pTextType ); + } + m_toolElements.AddToTail( pInfo->GetHandle() ); +} + + +//----------------------------------------------------------------------------- +// Update the editor dict based on the current material parameters +//----------------------------------------------------------------------------- +void CVMTTool::RemoveShaderParameter( const char *pParam ) +{ + m_pVMTType->RemoveAttributeInfo( pParam ); +} + + +//----------------------------------------------------------------------------- +// Which parameters are visible? +//----------------------------------------------------------------------------- +inline bool CVMTTool::IsFlagParamsVisible() const +{ + return m_bFlagParamsVisible; +} + +inline bool CVMTTool::IsToolParamsVisible() const +{ + return m_bToolParamsVisible; +} + + +//----------------------------------------------------------------------------- +// Adds flags, tool parameters +//----------------------------------------------------------------------------- +void CVMTTool::AddFlagParameter( const char *pParam ) +{ + Assert( m_pVMTType->GetAttributeInfo( pParam ) == NULL ); + + int i = m_FlagParams.AddToTail( ); + m_FlagParams[i] = pParam; + + CDmeEditorAttributeInfo *pInfo = CreateElement< CDmeEditorAttributeInfo >( "flag param info", m_pVMTType->GetFileId() ); + m_pVMTType->AddAttributeInfo( pParam, pInfo ); + pInfo->m_bIsVisible = m_bFlagParamsVisible; + pInfo->m_Widget = NULL; + m_toolElements.AddToTail( pInfo->GetHandle() ); +} + +void CVMTTool::AddToolParameter( const char *pParam, const char *pWidget, const char *pTextType ) +{ + Assert( m_pVMTType->GetAttributeInfo( pParam ) == NULL ); + + int i = m_ToolParams.AddToTail( ); + m_ToolParams[i] = pParam; + + CDmeEditorAttributeInfo *pInfo = CreateElement< CDmeEditorAttributeInfo >( "tool param info", m_pVMTType->GetFileId() ); + m_pVMTType->AddAttributeInfo( pParam, pInfo ); + pInfo->m_bIsVisible = m_bToolParamsVisible; + pInfo->m_Widget = pWidget; + if ( pTextType ) + { + pInfo->SetValue( "texttype", pTextType ); + } + m_toolElements.AddToTail( pInfo->GetHandle() ); +} + +void CVMTTool::RemoveAllFlagParameters() +{ + int nCount = m_FlagParams.Count(); + for ( int i = 0; i < nCount; ++i ) + { + RemoveShaderParameter( m_FlagParams[i] ); + } + m_FlagParams.RemoveAll(); +} + +void CVMTTool::RemoveAllToolParameters() +{ + int nCount = m_ToolParams.Count(); + for ( int i = 0; i < nCount; ++i ) + { + RemoveShaderParameter( m_ToolParams[i] ); + } + m_ToolParams.RemoveAll(); +} + + +//----------------------------------------------------------------------------- +// Create custom editors +//----------------------------------------------------------------------------- +void CVMTTool::InitEditorDict() +{ + CDmeEditorAttributeInfo *pInfo; + + // FIXME: This eventually will move to an .fgd-like file. + g_pEditorTypeDict = CreateElement< CDmeEditorTypeDictionary >( "DmeEditorTypeDictionary", DMFILEID_INVALID ); + m_toolElements.AddToTail( g_pEditorTypeDict->GetHandle() ); + + m_pVMTType = CreateElement< CDmeEditorType >( "vmt", DMFILEID_INVALID ); + HideStandardFields( m_pVMTType, EDITOR_FIELD_NAME | EDITOR_FIELD_TYPE | EDITOR_FIELD_ID | EDITOR_FIELD_EDITORTYPE ); + g_pEditorTypeDict->AddEditorType( m_pVMTType ); + m_toolElements.AddToTail( m_pVMTType->GetHandle() ); + + // Create a picker for the shader name + pInfo = CreateElement< CDmeEditorAttributeInfo >( "shader name info", DMFILEID_INVALID ); + m_pVMTType->AddAttributeInfo( "shader", pInfo ); + pInfo->m_Widget = "shaderpicker"; + pInfo->SetValue( "texttype", "shaderName" ); + m_toolElements.AddToTail( pInfo->GetHandle() ); +} + + + +//----------------------------------------------------------------------------- +// +// The Material menu +// +//----------------------------------------------------------------------------- +class CVMTMaterialMenuButton : public CToolMenuButton +{ + DECLARE_CLASS_SIMPLE( CVMTMaterialMenuButton, CToolMenuButton ); +public: + CVMTMaterialMenuButton( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ); + virtual void OnShowMenu(vgui::Menu *menu); +}; + +CVMTMaterialMenuButton::CVMTMaterialMenuButton( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ) + : BaseClass( parent, panelName, text, pActionSignalTarget ) +{ + AddMenuItem( "default", "#VMTSetToDefault", new KeyValues( "OnSetParamsToDefault" ), pActionSignalTarget ); + SetMenu(m_pMenu); +} + +void CVMTMaterialMenuButton::OnShowMenu(vgui::Menu *menu) +{ + BaseClass::OnShowMenu( menu ); + + // Update the menu + int id; + + CVMTDoc *pDoc = g_pVMTTool->GetDocument(); + if ( pDoc ) + { + id = m_Items.Find( "default" ); + m_pMenu->SetItemEnabled( id, true ); + } + else + { + id = m_Items.Find( "default" ); + m_pMenu->SetItemEnabled( id, false ); + } +} + + +//----------------------------------------------------------------------------- +// +// The View menu +// +//----------------------------------------------------------------------------- +class CVMTViewMenuButton : public CToolMenuButton +{ + DECLARE_CLASS_SIMPLE( CVMTViewMenuButton, CToolMenuButton ); +public: + CVMTViewMenuButton( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ); + virtual void OnShowMenu(vgui::Menu *menu); +}; + +CVMTViewMenuButton::CVMTViewMenuButton( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget ) + : BaseClass( parent, panelName, text, pActionSignalTarget ) +{ + AddCheckableMenuItem( "properties", "#VMTProperties", new KeyValues( "OnToggleProperties" ), pActionSignalTarget ); + AddCheckableMenuItem( "preview", "#VMTPreview", new KeyValues( "OnToggleVMTPreview" ), pActionSignalTarget ); + + AddSeparator(); + + AddCheckableMenuItem( "showflagparams", "#VMTShowFlags", new KeyValues( "OnShowFlags" ), pActionSignalTarget ); + AddCheckableMenuItem( "showtoolparams", "#VMTShowToolParams", new KeyValues( "OnShowToolParams" ), pActionSignalTarget ); + + AddSeparator(); + + AddMenuItem( "defaultlayout", "#VMTViewDefault", new KeyValues( "OnDefaultLayout" ), pActionSignalTarget ); + + SetMenu(m_pMenu); +} + +void CVMTViewMenuButton::OnShowMenu(vgui::Menu *menu) +{ + BaseClass::OnShowMenu( menu ); + + // Update the menu + int id; + + CVMTDoc *pDoc = g_pVMTTool->GetDocument(); + if ( pDoc ) + { + id = m_Items.Find( "properties" ); + m_pMenu->SetItemEnabled( id, true ); + + Panel *p; + p = g_pVMTTool->GetProperties(); + Assert( p ); + m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false ); + + id = m_Items.Find( "preview" ); + m_pMenu->SetItemEnabled( id, true ); + + p = g_pVMTTool->GetVMTPreview(); + Assert( p ); + m_pMenu->SetMenuItemChecked( id, ( p && p->GetParent() ) ? true : false ); + + id = m_Items.Find( "showflagparams" ); + m_pMenu->SetItemEnabled( id, true ); + m_pMenu->SetMenuItemChecked( id, g_pVMTTool->IsFlagParamsVisible() ); + + id = m_Items.Find( "showtoolparams" ); + m_pMenu->SetItemEnabled( id, true ); + m_pMenu->SetMenuItemChecked( id, g_pVMTTool->IsToolParamsVisible() ); + } + else + { + id = m_Items.Find( "properties" ); + m_pMenu->SetItemEnabled( id, false ); + id = m_Items.Find( "preview" ); + m_pMenu->SetItemEnabled( id, false ); + id = m_Items.Find( "showflagparams" ); + m_pMenu->SetItemEnabled( id, false ); + id = m_Items.Find( "showtoolparams" ); + m_pMenu->SetItemEnabled( id, false ); + } +} + + +//----------------------------------------------------------------------------- +// Initializes the menu bar +//----------------------------------------------------------------------------- +vgui::MenuBar *CVMTTool::CreateMenuBar( CBaseToolSystem *pParent ) +{ + m_pMenuBar = new CToolFileMenuBar( pParent, "VMTMenuBar" ); + + // Sets info in the menu bar + char title[ 64 ]; + ComputeMenuBarTitle( title, sizeof( title ) ); + m_pMenuBar->SetInfo( title ); + m_pMenuBar->SetToolName( GetToolName() ); + UpdateMenuBar(); + + // Add menu buttons + CToolMenuButton *pFileButton = CreateToolFileMenuButton( m_pMenuBar, "File", "&File", GetActionTarget(), this ); + CToolMenuButton *pEditButton = CreateToolEditMenuButton( m_pMenuBar, "Edit", "&Edit", GetActionTarget() ); + CToolMenuButton *pMaterialButton = new CVMTMaterialMenuButton( m_pMenuBar, "Material", "&Material", GetActionTarget() ); + CToolMenuButton *pSwitchButton = CreateToolSwitchMenuButton( m_pMenuBar, "Switcher", "&Tools", GetActionTarget() ); + CVMTViewMenuButton *pViewButton = new CVMTViewMenuButton( m_pMenuBar, "View", "&View", GetActionTarget() ); + + m_pMenuBar->AddButton( pFileButton ); + m_pMenuBar->AddButton( pEditButton ); + m_pMenuBar->AddButton( pMaterialButton ); + m_pMenuBar->AddButton( pViewButton ); + m_pMenuBar->AddButton( pSwitchButton ); + + return m_pMenuBar; +} + + +//----------------------------------------------------------------------------- +// Updates the menu bar based on the current file +//----------------------------------------------------------------------------- +void CVMTTool::UpdateMenuBar( ) +{ + if ( !m_pDoc ) + { + m_pMenuBar->SetFileName( "#VMTNoFile" ); + return; + } + + if ( m_pDoc->IsDirty() ) + { + char sz[ 512 ]; + Q_snprintf( sz, sizeof( sz ), "* %s", m_pDoc->GetFileName() ); + m_pMenuBar->SetFileName( sz ); + } + else + { + m_pMenuBar->SetFileName( m_pDoc->GetFileName() ); + } +} + + +//----------------------------------------------------------------------------- +// Inherited from IFileMenuCallbacks +//----------------------------------------------------------------------------- +int CVMTTool::GetFileMenuItemsEnabled( ) +{ + int nFlags; + if ( !m_pDoc ) + { + nFlags = FILE_NEW | FILE_OPEN | FILE_RECENT | FILE_CLEAR_RECENT | FILE_EXIT; + } + else + { + nFlags = FILE_ALL; + } + + if ( m_RecentFiles.IsEmpty() ) + { + nFlags &= ~(FILE_RECENT | FILE_CLEAR_RECENT); + } + return nFlags; +} + +void CVMTTool::AddRecentFilesToMenu( vgui::Menu *pMenu ) +{ + m_RecentFiles.AddToMenu( pMenu, GetActionTarget(), "OnRecent" ); +} + + +//----------------------------------------------------------------------------- +// Returns the file name for perforce +//----------------------------------------------------------------------------- +bool CVMTTool::GetPerforceFileName( char *pFileName, int nMaxLen ) +{ + if ( !m_pDoc ) + return false; + Q_strncpy( pFileName, m_pDoc->GetFileName(), nMaxLen ); + return true; +} + + +//----------------------------------------------------------------------------- +// Derived classes can implement this to get a new scheme to be applied to this tool +//----------------------------------------------------------------------------- +vgui::HScheme CVMTTool::GetToolScheme() +{ + return vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" ); +} + + +//----------------------------------------------------------------------------- +// Creates the action menu +//----------------------------------------------------------------------------- +vgui::Menu *CVMTTool::CreateActionMenu( vgui::Panel *pParent ) +{ + vgui::Menu *pActionMenu = new Menu( pParent, "ActionMenu" ); + pActionMenu->AddMenuItem( "#ToolHide", new KeyValues( "Command", "command", "HideActionMenu" ), GetActionTarget() ); + return pActionMenu; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void CVMTTool::OnExit() +{ + // Throw up a "save" dialog? + enginetools->Command( "quit\n" ); +} + + +//----------------------------------------------------------------------------- +// Handle commands from the action menu and other menus +//----------------------------------------------------------------------------- +void CVMTTool::OnCommand( const char *cmd ) +{ + if ( !V_stricmp( cmd, "HideActionMenu" ) ) + { + if ( GetActionMenu() ) + { + GetActionMenu()->SetVisible( false ); + } + } + else if ( !V_stricmp( cmd, "OnUndo" ) ) + { + OnUndo(); + } + else if ( !V_stricmp( cmd, "OnRedo" ) ) + { + OnRedo(); + } + else if ( !V_stricmp( cmd, "OnDescribeUndo" ) ) + { + OnDescribeUndo(); + } + else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnRecent" ) ) + { + int idx = Q_atoi( pSuffix ); + g_pVMTTool->OpenFileFromHistory( idx, cmd ); + } + else if ( const char *pSuffix = StringAfterPrefix( cmd, "OnTool" ) ) + { + int idx = Q_atoi( pSuffix ); + enginetools->SwitchToTool( idx ); + } + else + { + BaseClass::OnCommand( cmd ); + } +} + + +//----------------------------------------------------------------------------- +// Messages from the engine +//----------------------------------------------------------------------------- +void CVMTTool::PostMessage( HTOOLHANDLE hEntity, KeyValues *message ) +{ + if ( !Q_stricmp( message->GetName(), "EditMaterial" ) ) + { + const char *pMaterialName = message->GetString( "material", "debug/debugempty" ); + + char pLocalPath[ MAX_PATH ]; + char pAbsPath[ MAX_PATH ]; + if ( pMaterialName[0] == '/' && pMaterialName[1] == '/' && pMaterialName[2] != '/' ) + { + Q_strncpy( pAbsPath, pMaterialName, sizeof(pAbsPath) ); + Q_DefaultExtension( pAbsPath, ".vmt", sizeof(pAbsPath) ); + } + else + { + Q_snprintf( pLocalPath, sizeof(pLocalPath), "materials/%s", pMaterialName ); + Q_DefaultExtension( pLocalPath, ".vmt", sizeof(pLocalPath) ); + g_pFileSystem->RelativePathToFullPath( pLocalPath, "GAME", pAbsPath, sizeof(pAbsPath) ); + } + + Q_FixSlashes( pAbsPath ); + OpenSpecificFile( pAbsPath ); + } +} + + +//----------------------------------------------------------------------------- +// Derived classes can implement this to get notified when files are saved/loaded +//----------------------------------------------------------------------------- +void CVMTTool::OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues ) +{ + if ( bWroteFile ) + { + OnMarkNotDirty(); + } + + if ( !pContextKeyValues ) + return; + + if ( state != FileOpenStateMachine::SUCCESSFUL ) + return; + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnNew" ) ) + { + PerformNew(); + return; + } + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnClose" ) ) + { + OnCloseNoSave(); + return; + } + + if ( !Q_stricmp( pContextKeyValues->GetName(), "OnQuit" ) ) + { + OnCloseNoSave(); + vgui::ivgui()->PostMessage( GetVPanel(), new KeyValues( "OnExit" ), 0 ); + return; + } +} + + +//----------------------------------------------------------------------------- +// Called by SaveFile to allow clients to set up the save dialog +//----------------------------------------------------------------------------- +void CVMTTool::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + // Compute starting directory + char pStartingDir[ MAX_PATH ]; + GetModSubdirectory( "materials", pStartingDir, sizeof(pStartingDir) ); + + if ( bOpenFile ) + { + pDialog->SetTitle( "Open Material .VMT File", true ); + } + else + { + pDialog->SetTitle( "Save Material .VMT File As", true ); + } + + pDialog->SetStartDirectoryContext( "vmt_session", pStartingDir ); + pDialog->AddFilter( "*.vmt", "VMT (*.vmt)", true ); +} + + +//----------------------------------------------------------------------------- +// Called by SaveFile to allow clients to actually write the file out +//----------------------------------------------------------------------------- +bool CVMTTool::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + OnCloseNoSave(); + if ( !LoadDocument( pFileName ) ) + return false; + + m_RecentFiles.Add( pFileName, pFileFormat ); + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + UpdateMenuBar(); + + return true; +} + + +//----------------------------------------------------------------------------- +// Called by SaveFile to allow clients to actually write the file out +//----------------------------------------------------------------------------- +bool CVMTTool::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) +{ + if ( !m_pDoc ) + return true; + + m_pDoc->SetFileName( pFileName ); + if ( !m_pDoc->SaveToFile( ) ) + return false; + + m_RecentFiles.Add( pFileName, pFileFormat ); + m_RecentFiles.SaveToRegistry( GetRegistryName() ); + UpdateMenuBar(); + return true; +} + + +//----------------------------------------------------------------------------- +// Command handlers +//----------------------------------------------------------------------------- +void CVMTTool::PerformNew() +{ + OnCloseNoSave(); + NewDocument(); +} + +void CVMTTool::OnNew() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + SaveFile( m_pDoc->GetFileName(), "vmt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnNew" ) ); + return; + } + PerformNew(); +} + +void CVMTTool::OnOpen( ) +{ + int nFlags = 0; + const char *pSaveFileName = NULL; + if ( m_pDoc && m_pDoc->IsDirty() ) + { + nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY; + pSaveFileName = m_pDoc->GetFileName(); + } + + OpenFile( "vmt", pSaveFileName, "vmt", nFlags ); +} + +void CVMTTool::OnSave() +{ + if ( m_pDoc ) + { + SaveFile( m_pDoc->GetFileName(), "vmt", FOSM_SHOW_PERFORCE_DIALOGS ); + } +} + +void CVMTTool::OnSaveAs() +{ + if ( m_pDoc ) + { + SaveFile( NULL, "vmt", FOSM_SHOW_PERFORCE_DIALOGS ); + } +} + +void CVMTTool::OnClose() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + SaveFile( m_pDoc->GetFileName(), "vmt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnClose" ) ); + return; + } + + OnCloseNoSave(); +} + +void CVMTTool::OnCloseNoSave() +{ + DestroyTools(); + + if ( m_pDoc ) + { + CAppNotifyScopeGuard sg( "CVMTTool::OnCloseNoSave", NOTIFY_CHANGE_OTHER ); + + delete m_pDoc; + m_pDoc = NULL; + + if ( m_hProperties ) + { + m_hProperties->SetObject( NULL ); + } + } + + UpdateMenuBar( ); +} + +void CVMTTool::OnMarkNotDirty() +{ + if ( m_pDoc ) + { + m_pDoc->SetDirty( false ); + } +} + + +//----------------------------------------------------------------------------- +// Open a specific file +//----------------------------------------------------------------------------- +void CVMTTool::OpenSpecificFile( const char *pFileName ) +{ + int nFlags = 0; + const char *pSaveFileName = NULL; + if ( m_pDoc ) + { + // File is already open + if ( !Q_stricmp( m_pDoc->GetFileName(), pFileName ) ) + return; + + if ( m_pDoc->IsDirty() ) + { + nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY; + pSaveFileName = m_pDoc->GetFileName(); + } + } + + OpenFile( pFileName, "vmt", pSaveFileName, "vmt", nFlags ); +} + + +//----------------------------------------------------------------------------- +// Show the save document query dialog +//----------------------------------------------------------------------------- +void CVMTTool::OpenFileFromHistory( int slot, const char *pCommand ) +{ + const char *pFileName = m_RecentFiles.GetFile( slot ); + if ( !pFileName ) + return; + OpenSpecificFile( pFileName ); +} + +bool CVMTTool::CanQuit() +{ + if ( m_pDoc && m_pDoc->IsDirty() ) + { + // Show Save changes Yes/No/Cancel and re-quit if hit yes/no + SaveFile( m_pDoc->GetFileName(), "vmt", FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY, + new KeyValues( "OnQuit" ) ); + return false; + } + return true; +} + + +//----------------------------------------------------------------------------- +// Various command handlers related to the Edit menu +//----------------------------------------------------------------------------- +void CVMTTool::OnUndo() +{ + CDisableUndoScopeGuard guard; + g_pDataModel->Undo(); +} + +void CVMTTool::OnRedo() +{ + CDisableUndoScopeGuard guard; + g_pDataModel->Redo(); +} + +void CVMTTool::OnDescribeUndo() +{ + CUtlVector< UndoInfo_t > list; + g_pDataModel->GetUndoInfo( list ); + + Msg( "%i operations in stack\n", list.Count() ); + + for ( int i = list.Count() - 1; i >= 0; --i ) + { + UndoInfo_t& entry = list[ i ]; + if ( entry.terminator ) + { + Msg( "[ '%s' ] - %i operations\n", entry.undo, entry.numoperations ); + } + + Msg( " +%s\n", entry.desc ); + } +} + + +//----------------------------------------------------------------------------- +// Inherited from IVMTDocCallback +//----------------------------------------------------------------------------- +void CVMTTool::OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) +{ + UpdateMenuBar(); + if ( ( nNotifySource != NOTIFY_SOURCE_PROPERTIES_TREE ) && m_hProperties.Get() ) + { + m_hProperties->Refresh(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : CVMTDoc +//----------------------------------------------------------------------------- +CVMTDoc *CVMTTool::GetDocument() +{ + return m_pDoc; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +// Output : virtual CBasePropertiesContainer +//----------------------------------------------------------------------------- +CBasePropertiesContainer *CVMTTool::GetProperties() +{ + return m_hProperties.Get(); +} + +CVMTPanel *CVMTTool::GetVMTPreview() +{ + return m_hVMTPreview.Get(); +} + + +//----------------------------------------------------------------------------- +// Initializes the tools +//----------------------------------------------------------------------------- +void CVMTTool::InitTools() +{ + ShowElementProperties(); + + // FIXME: There are no tool windows here; how should this work? + // These panels are saved + windowposmgr->RegisterPanel( "properties", m_hProperties, false ); + windowposmgr->RegisterPanel( "vmtpanel", m_hVMTPreview, false ); + + if ( !windowposmgr->LoadPositions( "cfg/vmt.txt", this, &m_ToolWindowFactory, "VMT" ) ) + { + OnDefaultLayout(); + } +} + + +//----------------------------------------------------------------------------- +// Loads up a new document +//----------------------------------------------------------------------------- +bool CVMTTool::LoadDocument( char const *pDocName ) +{ + Assert( !m_pDoc ); + + DestroyTools(); + + m_pDoc = new CVMTDoc( this ); + if ( !m_pDoc->LoadFromFile( pDocName ) ) + { + delete m_pDoc; + m_pDoc = NULL; + Warning( "Fatal error loading '%s'\n", pDocName ); + return false; + } + + CreateTools( m_pDoc ); + InitTools(); + return true; +} + + +//----------------------------------------------------------------------------- +// Loads up a new document +//----------------------------------------------------------------------------- +void CVMTTool::NewDocument( ) +{ + Assert( !m_pDoc ); + + m_pDoc = new CVMTDoc( this ); + m_pDoc->CreateNew( ); + + CreateTools( m_pDoc ); + UpdateMenuBar( ); + InitTools(); +} + + +//----------------------------------------------------------------------------- +// Shows element properties +//----------------------------------------------------------------------------- +void CVMTTool::ShowElementProperties( ) +{ + if ( !m_pDoc ) + return; + + if ( !m_pDoc->GetRootObject() ) + return; + + // It should already exist + Assert( m_hProperties.Get() ); + if ( m_hProperties.Get() ) + { + m_hProperties->SetObject( m_pDoc->GetRootObject() ); + } +} + +void CVMTTool::DestroyTools() +{ + windowposmgr->SavePositions( "cfg/vmt.txt", "VMT" ); + + int c = ToolWindow::GetToolWindowCount(); + for ( int i = c - 1; i >= 0 ; --i ) + { + ToolWindow *kill = ToolWindow::GetToolWindow( i ); + delete kill; + } + + UnregisterAllToolWindows(); + if ( m_hProperties.Get() ) + { + windowposmgr->UnregisterPanel( m_hProperties.Get() ); + delete m_hProperties.Get(); + m_hProperties = NULL; + } + if ( m_hVMTPreview.Get() ) + { + windowposmgr->UnregisterPanel( m_hVMTPreview.Get() ); + delete m_hVMTPreview.Get(); + m_hVMTPreview = NULL; + } +} + +void CVMTTool::CreateTools( CVMTDoc *doc ) +{ + if ( !m_hProperties.Get() ) + { + m_hProperties = new CBasePropertiesContainer( NULL, m_pDoc, g_pEditorTypeDict ); + } + if ( !m_hVMTPreview.Get() ) + { + m_hVMTPreview = new CVMTPanel( NULL, "VMT Preview" ); + SETUP_PANEL( m_hVMTPreview.Get() ); + m_hVMTPreview->SetMaterial( m_pDoc->GetPreviewMaterial() ); + } + RegisterToolWindow( m_hProperties ); + RegisterToolWindow( m_hVMTPreview ); +} + +void CVMTTool::ShowToolWindow( Panel *tool, char const *toolName, bool visible ) +{ + Assert( tool ); + + if ( tool->GetParent() == NULL && visible ) + { + m_ToolWindowFactory.InstanceToolWindow( this, false, tool, toolName, false ); + } + else if ( !visible ) + { + ToolWindow *tw = dynamic_cast< ToolWindow * >( tool->GetParent()->GetParent() ); + Assert( tw ); + tw->RemovePage( tool ); + } +} + +void CVMTTool::ToggleToolWindow( Panel *tool, char const *toolName ) +{ + Assert( tool ); + + if ( tool->GetParent() == NULL ) + { + ShowToolWindow( tool, toolName, true ); + } + else + { + ShowToolWindow( tool, toolName, false ); + } +} + +void CVMTTool::DestroyToolContainers() +{ + int c = ToolWindow::GetToolWindowCount(); + for ( int i = c - 1; i >= 0 ; --i ) + { + ToolWindow *kill = ToolWindow::GetToolWindow( i ); + delete kill; + } +} + +void CVMTTool::OnDefaultLayout() +{ + int y = m_pMenuBar->GetTall(); + + int usew, useh; + GetSize( usew, useh ); + + DestroyToolContainers(); + + Assert( ToolWindow::GetToolWindowCount() == 0 ); + + CBasePropertiesContainer *properties = GetProperties(); + CVMTPanel *pVMTPreview = GetVMTPreview(); + + // Need three containers + ToolWindow *pPropertyWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, properties, "#VMTProperties", false ); + ToolWindow *pVMTPreviewWindow = m_ToolWindowFactory.InstanceToolWindow( GetClientArea(), false, pVMTPreview, "#VMTPreview", false ); + + int halfScreen = usew / 2; + int bottom = useh - y; + int sy = (bottom - y) / 2; + + SetMiniViewportBounds( halfScreen, y, halfScreen, sy - y ); + pPropertyWindow->SetBounds( 0, y, halfScreen, bottom ); + pVMTPreviewWindow->SetBounds( halfScreen, sy, halfScreen, bottom - sy ); +} + +void CVMTTool::OnToggleProperties() +{ + if ( m_hProperties.Get() ) + { + ToggleToolWindow( m_hProperties.Get(), "#VMTProperties" ); + } +} + +void CVMTTool::OnToggleVMTPreview() +{ + if ( m_hVMTPreview.Get() ) + { + ToggleToolWindow( m_hVMTPreview.Get(), "#VMTPreview" ); + } +} + + +//----------------------------------------------------------------------------- +// Show/hide tool params + flags +//----------------------------------------------------------------------------- +void CVMTTool::OnShowFlags() +{ + m_bFlagParamsVisible = !m_bFlagParamsVisible; + + int nCount = m_FlagParams.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeEditorAttributeInfo *pInfo = m_pVMTType->GetAttributeInfo( m_FlagParams[i] ); + Assert( pInfo ); + pInfo->m_bIsVisible = m_bFlagParamsVisible; + } + if ( m_hProperties.Get() ) + { + m_hProperties->Refresh(); + } +} + +void CVMTTool::OnShowToolParams() +{ + m_bToolParamsVisible = !m_bToolParamsVisible; + + int nCount = m_ToolParams.Count(); + for ( int i = 0; i < nCount; ++i ) + { + CDmeEditorAttributeInfo *pInfo = m_pVMTType->GetAttributeInfo( m_ToolParams[i] ); + Assert( pInfo ); + pInfo->m_bIsVisible = m_bToolParamsVisible; + } + if ( m_hProperties.Get() ) + { + m_hProperties->Refresh(); + } +} + + +//----------------------------------------------------------------------------- +// Sets shader parameters to the default for that shader +//----------------------------------------------------------------------------- +void CVMTTool::OnSetParamsToDefault() +{ + if ( m_pDoc ) + { + m_pDoc->SetParamsToDefault(); + } +} + +char const *CVMTTool::GetLogoTextureName() +{ + return "vgui/tools/vmt/vmt_logo"; +}
\ No newline at end of file diff --git a/tools/vmt/vmttool.h b/tools/vmt/vmttool.h new file mode 100644 index 0000000..28e5ffe --- /dev/null +++ b/tools/vmt/vmttool.h @@ -0,0 +1,50 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: VMT tool; main UI smarts class +// +//============================================================================= + +#ifndef VMTTOOL_H +#define VMTTOOL_H + +#ifdef _WIN32 +#pragma once +#endif + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CDmeEditorTypeDictionary; + + +//----------------------------------------------------------------------------- +// Singleton interfaces +//----------------------------------------------------------------------------- +extern CDmeEditorTypeDictionary *g_pEditorTypeDict; + + +//----------------------------------------------------------------------------- +// Allows the doc to call back into the VMT editor tool +//----------------------------------------------------------------------------- +class IVMTDocCallback +{ +public: + // Called by the doc when the data changes + virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0; + + // Update the editor dict based on the current material parameters + virtual void AddShaderParameter( const char *pParam, const char *pWidget, const char *pTextType ) = 0; + + // Update the editor dict based on the current material parameters + virtual void RemoveShaderParameter( const char *pParam ) = 0; + + // Adds flags, tool parameters + virtual void AddFlagParameter( const char *pParam ) = 0; + virtual void AddToolParameter( const char *pParam, const char *pWidget = NULL, const char *pTextType = NULL ) = 0; + virtual void RemoveAllFlagParameters() = 0; + virtual void RemoveAllToolParameters() = 0; +}; + + +#endif // VMTTOOL_H |