diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/modelbrowser | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/modelbrowser')
| -rw-r--r-- | utils/modelbrowser/modelbrowser.cpp | 498 | ||||
| -rw-r--r-- | utils/modelbrowser/modelbrowser.vpc | 56 | ||||
| -rw-r--r-- | utils/modelbrowser/modelbrowsermaterialproxies.h | 412 |
3 files changed, 966 insertions, 0 deletions
diff --git a/utils/modelbrowser/modelbrowser.cpp b/utils/modelbrowser/modelbrowser.cpp new file mode 100644 index 0000000..8d304f0 --- /dev/null +++ b/utils/modelbrowser/modelbrowser.cpp @@ -0,0 +1,498 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// $Header: $ +// $NoKeywords: $ +// +// Material editor +//============================================================================= +#include <windows.h> +#include "vstdlib/cvar.h" +#include "appframework/vguimatsysapp.h" +#include "filesystem.h" +#include "materialsystem/imaterialsystem.h" +#include "vgui/IVGui.h" +#include "vgui/ISystem.h" +#include "vgui_controls/Panel.h" +#include "vgui/ISurface.h" +#include "vgui_controls/controls.h" +#include "vgui/IScheme.h" +#include "vgui/ILocalize.h" +#include "vgui/IPanel.h" +#include "tier0/dbg.h" +#include "vgui_controls/Frame.h" +#include "vgui_controls/AnimationController.h" +#include "tier0/icommandline.h" +#include "materialsystem/MaterialSystem_Config.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "filesystem_init.h" +#include "vstdlib/iprocessutils.h" +#include "matsys_controls/matsyscontrols.h" +#include "matsys_controls/mdlpicker.h" +#include "IStudioRender.h" +#include "datacache/idatacache.h" +#include "datacache/imdlcache.h" +#include "vphysics_interface.h" +#include "vgui_controls/frame.h" +#include "materialsystem/IMaterialSystemHardwareConfig.h" +#include "materialsystem/MaterialSystemUtil.h" +#include "tier3/tier3.h" +#include "vgui_controls/consoledialog.h" +#include "icvar.h" +#include "vgui/keycode.h" +#include "tier2/p4helpers.h" +#include "p4lib/ip4.h" +#include "ivtex.h" +#include "modelbrowsermaterialproxies.h" + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +const MaterialSystem_Config_t *g_pMaterialSystemConfig; + +static CModelBrowserMaterialProxyFactory g_materialProxyFactory; + +//----------------------------------------------------------------------------- +// Spew func +//----------------------------------------------------------------------------- +SpewRetval_t ModelBrowserSpewFunc( SpewType_t spewType, const tchar *pMsg ) +{ + OutputDebugString( pMsg ); + switch( spewType ) + { + case SPEW_ASSERT: + g_pCVar->ConsoleColorPrintf( Color( 255, 192, 0, 255 ), pMsg ); +#ifdef _DEBUG + return SPEW_DEBUGGER; +#else + return SPEW_CONTINUE; +#endif + + case SPEW_ERROR: + g_pCVar->ConsoleColorPrintf( Color( 255, 0, 0, 255 ), pMsg ); + return SPEW_ABORT; + + case SPEW_WARNING: + g_pCVar->ConsoleColorPrintf( Color( 192, 192, 0, 255 ), pMsg ); + break; + + case SPEW_MESSAGE: + { + Color c = *GetSpewOutputColor(); + if ( !Q_stricmp( GetSpewOutputGroup(), "developer" ) ) + g_pCVar->ConsoleDPrintf( pMsg ); + else + g_pCVar->ConsoleColorPrintf( c, pMsg ); + } + break; + } + + return SPEW_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// FIXME: This should be moved into studiorender +//----------------------------------------------------------------------------- +static ConVar r_showenvcubemap( "r_showenvcubemap", "0", FCVAR_CHEAT ); +static ConVar r_eyegloss ( "r_eyegloss", "1", FCVAR_ARCHIVE ); // wet eyes +static ConVar r_eyemove ( "r_eyemove", "1", FCVAR_ARCHIVE ); // look around +static ConVar r_eyeshift_x ( "r_eyeshift_x", "0", FCVAR_ARCHIVE ); // eye X position +static ConVar r_eyeshift_y ( "r_eyeshift_y", "0", FCVAR_ARCHIVE ); // eye Y position +static ConVar r_eyeshift_z ( "r_eyeshift_z", "0", FCVAR_ARCHIVE ); // eye Z position +static ConVar r_eyesize ( "r_eyesize", "0", FCVAR_ARCHIVE ); // adjustment to iris textures +static ConVar mat_softwareskin( "mat_softwareskin", "0", FCVAR_CHEAT ); +static ConVar r_nohw ( "r_nohw", "0", FCVAR_CHEAT ); +static ConVar r_nosw ( "r_nosw", "0", FCVAR_CHEAT ); +static ConVar r_teeth ( "r_teeth", "1" ); +static ConVar r_drawentities ( "r_drawentities", "1", FCVAR_CHEAT ); +static ConVar r_flex ( "r_flex", "1" ); +static ConVar r_eyes ( "r_eyes", "1" ); +static ConVar r_skin ( "r_skin","0", FCVAR_CHEAT ); +static ConVar r_maxmodeldecal ( "r_maxmodeldecal", "50" ); +static ConVar r_modelwireframedecal ( "r_modelwireframedecal", "0", FCVAR_CHEAT ); +static ConVar mat_wireframe ( "mat_wireframe", "0", FCVAR_CHEAT ); +static ConVar mat_normals ( "mat_normals", "0", FCVAR_CHEAT ); +static ConVar r_eyeglintlodpixels ( "r_eyeglintlodpixels", "0", FCVAR_CHEAT ); +static ConVar r_rootlod ( "r_rootlod", "0" ); + +static StudioRenderConfig_t s_StudioRenderConfig; + +void UpdateStudioRenderConfig( void ) +{ + memset( &s_StudioRenderConfig, 0, sizeof(s_StudioRenderConfig) ); + + s_StudioRenderConfig.bEyeMove = !!r_eyemove.GetInt(); + s_StudioRenderConfig.fEyeShiftX = r_eyeshift_x.GetFloat(); + s_StudioRenderConfig.fEyeShiftY = r_eyeshift_y.GetFloat(); + s_StudioRenderConfig.fEyeShiftZ = r_eyeshift_z.GetFloat(); + s_StudioRenderConfig.fEyeSize = r_eyesize.GetFloat(); + if( mat_softwareskin.GetInt() || mat_wireframe.GetInt() ) + { + s_StudioRenderConfig.bSoftwareSkin = true; + } + else + { + s_StudioRenderConfig.bSoftwareSkin = false; + } + s_StudioRenderConfig.bNoHardware = !!r_nohw.GetInt(); + s_StudioRenderConfig.bNoSoftware = !!r_nosw.GetInt(); + s_StudioRenderConfig.bTeeth = !!r_teeth.GetInt(); + s_StudioRenderConfig.drawEntities = r_drawentities.GetInt(); + s_StudioRenderConfig.bFlex = !!r_flex.GetInt(); + s_StudioRenderConfig.bEyes = !!r_eyes.GetInt(); + s_StudioRenderConfig.bWireframe = !!mat_wireframe.GetInt(); + s_StudioRenderConfig.bDrawNormals = mat_normals.GetBool(); + s_StudioRenderConfig.skin = r_skin.GetInt(); + s_StudioRenderConfig.maxDecalsPerModel = r_maxmodeldecal.GetInt(); + s_StudioRenderConfig.bWireframeDecals = r_modelwireframedecal.GetInt() != 0; + + s_StudioRenderConfig.fullbright = g_pMaterialSystemConfig->nFullbright; + s_StudioRenderConfig.bSoftwareLighting = g_pMaterialSystemConfig->bSoftwareLighting; + + s_StudioRenderConfig.bShowEnvCubemapOnly = r_showenvcubemap.GetInt() ? true : false; + s_StudioRenderConfig.fEyeGlintPixelWidthLODThreshold = r_eyeglintlodpixels.GetFloat(); + + g_pStudioRender->UpdateConfig( s_StudioRenderConfig ); +} + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +class CModelBrowserApp : public CVguiMatSysApp +{ + typedef CVguiMatSysApp BaseClass; + +public: + // Methods of IApplication + virtual bool Create(); + virtual bool PreInit(); + virtual int Main(); + virtual bool AppUsesReadPixels() { return true; } + +private: + virtual const char *GetAppName() { return "ModelBrowser"; } + + // Sets a default env_cubemap for rendering materials w/ specularity + void InitDefaultEnvCubemap( ); + void ShutdownDefaultEnvCubemap( ); + CTextureReference m_DefaultEnvCubemap; +}; + +DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CModelBrowserApp ); + + +//----------------------------------------------------------------------------- +// Create all singleton systems +//----------------------------------------------------------------------------- +bool CModelBrowserApp::Create() +{ + if ( !BaseClass::Create() ) + return false; + + AppSystemInfo_t appSystems[] = + { + { "vstdlib.dll", PROCESS_UTILS_INTERFACE_VERSION }, + { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION }, + { "vphysics.dll", VPHYSICS_INTERFACE_VERSION }, + { "datacache.dll", DATACACHE_INTERFACE_VERSION }, + { "datacache.dll", MDLCACHE_INTERFACE_VERSION }, + { "vtex_dll", IVTEX_VERSION_STRING }, + + { "", "" } // Required to terminate the list + }; + + if ( !AddSystems( appSystems ) ) + return false; + + if ( !CommandLine()->CheckParm( "-nop4" )) + { + AppModule_t hModule = LoadModule( "p4lib" ); + AddSystem( hModule, P4_INTERFACE_VERSION ); + } + else + { + g_p4factory->SetDummyMode( true ); + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CModelBrowserApp::PreInit( ) +{ + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false ); + + if ( !BaseClass::PreInit() ) + return false; + + // initialize interfaces + CreateInterfaceFn appFactory = GetFactory(); + if (!vgui::VGui_InitMatSysInterfacesList( "ModelBrowser", &appFactory, 1 )) + return false; + + if ( !g_pFullFileSystem || !g_pMaterialSystem || !g_pVGui || !g_pVGuiSurface || !g_pMatSystemSurface || !g_pVTex ) + { + Warning( "Model browser is missing a required interface!\n" ); + return false; + } + + g_p4factory->SetOpenFileChangeList( "ModelBrowser Auto Checkout" ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Sets a default env_cubemap for rendering materials w/ specularity +//----------------------------------------------------------------------------- +void CModelBrowserApp::InitDefaultEnvCubemap( ) +{ + // Deal with the default cubemap + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + ITexture *pCubemapTexture = g_pMaterialSystem->FindTexture( "editor/cubemap", NULL, true ); + m_DefaultEnvCubemap.Init( pCubemapTexture ); + pRenderContext->BindLocalCubemap( pCubemapTexture ); +} + +void CModelBrowserApp::ShutdownDefaultEnvCubemap( ) +{ + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + pRenderContext->BindLocalCubemap( NULL ); + m_DefaultEnvCubemap.Shutdown( ); +} + + +//----------------------------------------------------------------------------- +// Sequence picker frame +//----------------------------------------------------------------------------- +class CMDLBrowserFrame : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( CMDLBrowserFrame, vgui::Frame ); +public: + CMDLBrowserFrame() : BaseClass( NULL, "MDLPickerFrame" ) + { + m_pMDLPicker = new CMDLPicker( this ); + SetTitle( "Model Browser", true ); + SetSizeable( false ); + SetCloseButtonVisible( false ); + SetMoveable( false ); + Activate(); + m_pMDLPicker->Activate(); + m_bPositioned = false; + + SetKeyBoardInputEnabled( true ); + + m_pConsole = new vgui::CConsoleDialog( this, "ConsoleDialog", false ); + m_pConsole->AddActionSignalTarget( this ); + } + + virtual ~CMDLBrowserFrame() + { + delete m_pMDLPicker; + } + + virtual void PerformLayout() + { + BaseClass::PerformLayout(); + + int x, y, w, h; + GetClientArea( x, y, w, h ); + m_pMDLPicker->SetBounds( x, y, w, h ); + + if ( !m_bPositioned ) + { + m_pConsole->SetSize( w/2, h/2 ); + m_pConsole->MoveToCenterOfScreen(); + m_bPositioned = true; + } + } + + virtual void OnKeyCodePressed( vgui::KeyCode code ) + { + BaseClass::OnKeyCodePressed( code ); + if ( code == KEY_BACKQUOTE ) + { + if ( !m_pConsole->IsVisible() ) + { + m_pConsole->Activate(); + } + else + { + m_pConsole->Hide(); + } + } + } + + MESSAGE_FUNC_CHARPTR( OnCommandSubmitted, "CommandSubmitted", command ) + { + CCommand args; + args.Tokenize( command ); + + ConCommandBase *pCommandBase = g_pCVar->FindCommandBase( args[0] ); + if ( !pCommandBase ) + { + ConWarning( "Unknown command or convar '%s'!\n", args[0] ); + return; + } + + if ( pCommandBase->IsCommand() ) + { + ConCommand *pCommand = static_cast<ConCommand*>( pCommandBase ); + pCommand->Dispatch( args ); + return; + } + + ConVar *pConVar = static_cast< ConVar* >( pCommandBase ); + if ( args.ArgC() == 1) + { + if ( pConVar->IsFlagSet( FCVAR_NEVER_AS_STRING ) ) + { + ConMsg( "%s = %f\n", args[0], pConVar->GetFloat() ); + } + else + { + ConMsg( "%s = %s\n", args[0], pConVar->GetString() ); + } + return; + } + + if ( pConVar->IsFlagSet( FCVAR_NEVER_AS_STRING ) ) + { + pConVar->SetValue( (float)atof( args[1] ) ); + } + else + { + pConVar->SetValue( args.ArgS() ); + } + } + +private: + CMDLPicker *m_pMDLPicker; + vgui::CConsoleDialog *m_pConsole; + bool m_bPositioned; +}; + + +//----------------------------------------------------------------------------- +// Creates the picker frame +//----------------------------------------------------------------------------- +vgui::PHandle CreatePickerFrame() +{ + vgui::Frame *pMainPanel = new CMDLBrowserFrame( ); + pMainPanel->SetParent( g_pVGuiSurface->GetEmbeddedPanel() ); + + vgui::PHandle hMainPanel; + hMainPanel = pMainPanel; + + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + int x, y, w, h; + pRenderContext->GetViewport( x, y, w, h ); + pMainPanel->SetBounds( x+2, y+2, w-4, h-4 ); + + return hMainPanel; +} + + +//----------------------------------------------------------------------------- +// main application +//----------------------------------------------------------------------------- +int CModelBrowserApp::Main() +{ + SpewOutputFunc( ModelBrowserSpewFunc ); + SpewActivate( "console", 1 ); + + g_pMaterialSystem->ModInit(); + g_pMaterialSystem->SetMaterialProxyFactory( &g_materialProxyFactory ); + if (!SetVideoMode()) + return 0; + + g_pDataCache->SetSize( 64 * 1024 * 1024 ); + + InitDefaultEnvCubemap(); + + g_pMaterialSystemConfig = &g_pMaterialSystem->GetCurrentConfigForVideoCard(); + + // configuration settings + vgui::system()->SetUserConfigFile( "modelbrowser.vdf", "EXECUTABLE_PATH"); + + // load scheme + if (!vgui::scheme()->LoadSchemeFromFile( "resource/BoxRocket.res", "ModelBrowser" )) + { + Assert( 0 ); + } + + // load the boxrocket localization file + g_pVGuiLocalize->AddFile( "resource/boxrocket_%language%.txt" ); + + // start vgui + g_pVGui->Start(); + + // add our main window + vgui::PHandle hMainPanel; + + // load the base localization file + g_pVGuiLocalize->AddFile( "Resource/valve_%language%.txt" ); + g_pFullFileSystem->AddSearchPath("platform", "PLATFORM"); + g_pVGuiLocalize->AddFile( "Resource/vgui_%language%.txt"); + + // run app frame loop + CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); + vgui::VPANEL root = g_pVGuiSurface->GetEmbeddedPanel(); + g_pVGuiSurface->Invalidate( root ); + while (g_pVGui->IsRunning()) + { + UpdateStudioRenderConfig(); + + AppPumpMessages(); + + vgui::GetAnimationController()->UpdateAnimations( Sys_FloatTime() ); + + g_pMaterialSystem->BeginFrame( 0 ); + g_pStudioRender->BeginFrame(); + + pRenderContext->ClearColor4ub( 76, 88, 68, 255 ); + pRenderContext->ClearBuffers( true, true ); + + g_pVGui->RunFrame(); + + g_pVGuiSurface->PaintTraverseEx( root, true ); + + g_pStudioRender->EndFrame(); + g_pMaterialSystem->EndFrame( ); + + g_pMaterialSystem->SwapBuffers(); + + // Disallow closing the dialog + if ( !hMainPanel.Get() ) + { + hMainPanel = CreatePickerFrame(); + } + } + + if ( hMainPanel.Get() ) + { + delete hMainPanel.Get(); + } + + ShutdownDefaultEnvCubemap(); + + g_pMaterialSystem->ModShutdown(); + + SpewOutputFunc( NULL ); + return 1; +} + + + diff --git a/utils/modelbrowser/modelbrowser.vpc b/utils/modelbrowser/modelbrowser.vpc new file mode 100644 index 0000000..3154002 --- /dev/null +++ b/utils/modelbrowser/modelbrowser.vpc @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// MODELBROWSER.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,$SRCDIR\vgui2\include,$SRCDIR\vgui2\controls,..\common" + } + + $Linker + { + $AdditionalDependencies "$BASE comctl32.lib odbc32.lib odbccp32.lib Rpcrt4.lib" + } +} + +$Project "Modelbrowser" +{ + $Folder "Source Files" + { + $File "$SRCDIR\public\interpolatortypes.cpp" + $File "$SRCDIR\public\interpolatortypes.h" + $File "modelbrowser.cpp" + $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" + $File "$SRCDIR\public\bone_setup.cpp" + $File "$SRCDIR\public\studio.cpp" + $File "$SRCDIR\public\collisionutils.cpp" + } + + $Folder "Header Files" + { + $File "..\common\cmdlib.h" + $File "$SRCDIR\public\filesystem.h" + $File "$SRCDIR\utils\common\FileSystem_Tools.h" + $File "$SRCDIR\public\tier1\interface.h" + } + + $Folder "Link Libraries" + { + $Lib appframework + $Lib dmxloader + $Lib mathlib + $Lib matsys_controls + $Lib tier2 + $Lib tier3 + $Lib vgui_controls + } +} diff --git a/utils/modelbrowser/modelbrowsermaterialproxies.h b/utils/modelbrowser/modelbrowsermaterialproxies.h new file mode 100644 index 0000000..0bd3c2f --- /dev/null +++ b/utils/modelbrowser/modelbrowsermaterialproxies.h @@ -0,0 +1,412 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include <windows.h> +#include "materialsystem/imaterialproxyfactory.h" +#include "materialsystem/imaterialvar.h" +#include "materialsystem/imaterialproxy.h" + +class C_BaseEntity; + +// Copied and bastardized a few material proxy classes from the TF client dll. The purpose here is +// to make TF materials for paintable items show the default paint color (using the SelectFirstIfNotZero proxy) +// and to completely hide the burn detail texture (fake BurnLevel proxy). +// Implemented a lame material proxy factory that only knows about these two proxies. + +//----------------------------------------------------------------------------- +// Helper class to deal with floating point inputs +//----------------------------------------------------------------------------- +class CFloatInput +{ +public: + bool Init( IMaterial *pMaterial, KeyValues *pKeyValues, const char *pKeyName, float flDefault = 0.0f ); + float GetFloat() const; + +private: + float m_flValue; + IMaterialVar *m_pFloatVar; + int m_FloatVecComp; +}; + +bool CFloatInput::Init( IMaterial *pMaterial, KeyValues *pKeyValues, const char *pKeyName, float flDefault ) +{ + m_pFloatVar = NULL; + KeyValues *pSection = pKeyValues->FindKey( pKeyName ); + if (pSection) + { + if (pSection->GetDataType() == KeyValues::TYPE_STRING) + { + const char *pVarName = pSection->GetString(); + + // Look for numbers... + float flValue; + int nCount = sscanf( pVarName, "%f", &flValue ); + if (nCount == 1) + { + m_flValue = flValue; + return true; + } + + // Look for array specification... + char pTemp[256]; + if (strchr(pVarName, '[')) + { + // strip off the array... + Q_strncpy( pTemp, pVarName, 256 ); + char *pArray = strchr( pTemp, '[' ); + *pArray++ = 0; + + char* pIEnd; + m_FloatVecComp = strtol( pArray, &pIEnd, 10 ); + + // Use the version without the array... + pVarName = pTemp; + } + else + { + m_FloatVecComp = -1; + } + + bool bFoundVar; + m_pFloatVar = pMaterial->FindVar( pVarName, &bFoundVar, true ); + if (!bFoundVar) + return false; + } + else + { + m_flValue = pSection->GetFloat(); + } + } + else + { + m_flValue = flDefault; + } + return true; +} + +float CFloatInput::GetFloat() const +{ + if (!m_pFloatVar) + return m_flValue; + + if( m_FloatVecComp < 0 ) + return m_pFloatVar->GetFloatValue(); + + int iVecSize = m_pFloatVar->VectorSize(); + if ( m_FloatVecComp >= iVecSize ) + return 0; + + float v[4]; + m_pFloatVar->GetVecValue( v, iVecSize ); + return v[m_FloatVecComp]; +} + + + +//----------------------------------------------------------------------------- +// +// Result proxy; a result (with vector friendliness) +// +//----------------------------------------------------------------------------- +class CResultProxy : public IMaterialProxy +{ +public: + CResultProxy(); + virtual ~CResultProxy(); + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + virtual void Release( void ) { delete this; } + virtual IMaterial *GetMaterial(); + +protected: + C_BaseEntity *BindArgToEntity( void *pArg ); + void SetFloatResult( float result ); + + IMaterialVar* m_pResult; + int m_ResultVecComp; +}; + +CResultProxy::CResultProxy() : m_pResult(0) +{ +} + +CResultProxy::~CResultProxy() +{ +} + + +bool CResultProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + char const* pResult = pKeyValues->GetString( "resultVar" ); + if( !pResult ) + return false; + + // Look for array specification... + char pTemp[256]; + if (strchr(pResult, '[')) + { + // strip off the array... + Q_strncpy( pTemp, pResult, 256 ); + char *pArray = strchr( pTemp, '[' ); + *pArray++ = 0; + + char* pIEnd; + m_ResultVecComp = strtol( pArray, &pIEnd, 10 ); + + // Use the version without the array... + pResult = pTemp; + } + else + { + m_ResultVecComp = -1; + } + + bool foundVar; + m_pResult = pMaterial->FindVar( pResult, &foundVar, true ); + if( !foundVar ) + return false; + + return true; +} + + +//----------------------------------------------------------------------------- +// A little code to allow us to set single components of vectors +//----------------------------------------------------------------------------- +void CResultProxy::SetFloatResult( float result ) +{ + if (m_pResult->GetType() == MATERIAL_VAR_TYPE_VECTOR) + { + if ( m_ResultVecComp >= 0 ) + { + m_pResult->SetVecComponentValue( result, m_ResultVecComp ); + } + else + { + float v[4]; + int vecSize = m_pResult->VectorSize(); + + for (int i = 0; i < vecSize; ++i) + v[i] = result; + + m_pResult->SetVecValue( v, vecSize ); + } + } + else + { + m_pResult->SetFloatValue( result ); + } +} + +C_BaseEntity *CResultProxy::BindArgToEntity( void *pArg ) +{ + return NULL; + /* + IClientRenderable *pRend = (IClientRenderable *)pArg; + return pRend->GetIClientUnknown()->GetBaseEntity(); + */ +} + +IMaterial *CResultProxy::GetMaterial() +{ + return m_pResult->GetOwningMaterial(); +} + + +//----------------------------------------------------------------------------- +// +// Base functional proxy; two sources (one is optional) and a result +// +//----------------------------------------------------------------------------- +class CFunctionProxy : public CResultProxy +{ +public: + CFunctionProxy(); + virtual ~CFunctionProxy(); + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + +protected: + void ComputeResultType( MaterialVarType_t& resultType, int& vecSize ); + + IMaterialVar* m_pSrc1; + IMaterialVar* m_pSrc2; +}; + +CFunctionProxy::CFunctionProxy() : m_pSrc1(0), m_pSrc2(0) +{ +} + +CFunctionProxy::~CFunctionProxy() +{ +} + + +bool CFunctionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + if (!CResultProxy::Init( pMaterial, pKeyValues )) + return false; + + char const* pSrcVar1 = pKeyValues->GetString( "srcVar1" ); + if( !pSrcVar1 ) + return false; + + bool foundVar; + m_pSrc1 = pMaterial->FindVar( pSrcVar1, &foundVar, true ); + if( !foundVar ) + return false; + + // Source 2 is optional, some math ops may be single-input + char const* pSrcVar2 = pKeyValues->GetString( "srcVar2" ); + if( pSrcVar2 && (*pSrcVar2) ) + { + m_pSrc2 = pMaterial->FindVar( pSrcVar2, &foundVar, true ); + if( !foundVar ) + return false; + } + else + { + m_pSrc2 = 0; + } + + return true; +} + + +void CFunctionProxy::ComputeResultType( MaterialVarType_t& resultType, int& vecSize ) +{ + // Feh, this is ugly. Basically, don't change the result type + // unless it's undefined. + resultType = m_pResult->GetType(); + if (resultType == MATERIAL_VAR_TYPE_VECTOR) + { + if (m_ResultVecComp >= 0) + resultType = MATERIAL_VAR_TYPE_FLOAT; + vecSize = m_pResult->VectorSize(); + } + else if (resultType == MATERIAL_VAR_TYPE_UNDEFINED) + { + resultType = m_pSrc1->GetType(); + if (resultType == MATERIAL_VAR_TYPE_VECTOR) + { + vecSize = m_pSrc1->VectorSize(); + } + else if ((resultType == MATERIAL_VAR_TYPE_UNDEFINED) && m_pSrc2) + { + resultType = m_pSrc2->GetType(); + if (resultType == MATERIAL_VAR_TYPE_VECTOR) + { + vecSize = m_pSrc2->VectorSize(); + } + } + } +} + + +class CFakeBurnLevelProxy : public CResultProxy +{ +public: + virtual void OnBind( void *pC_BaseEntity ) + { + // Slam burn level to 0 to avoid the burn detail texture showing through in modelbrowser. + Assert( m_pResult ); + if ( m_pResult ) + { + m_pResult->SetFloatValue( 0.0f ); + } + } +}; + + +//----------------------------------------------------------------------------- +// Selects the first var value if it's non-zero, otherwise goes with the second +//----------------------------------------------------------------------------- + +class CSelectFirstIfNonZeroProxy : public CFunctionProxy +{ +public: + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + virtual void OnBind( void *pC_BaseEntity ); +}; + +bool CSelectFirstIfNonZeroProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + // Requires 2 args.. + bool ok = CFunctionProxy::Init( pMaterial, pKeyValues ); + ok = ok && m_pSrc2; + return ok; +} + +void CSelectFirstIfNonZeroProxy::OnBind( void *pC_BaseEntity ) +{ + Assert( m_pSrc1 && m_pSrc2 && m_pResult ); + + MaterialVarType_t resultType; + int vecSize; + ComputeResultType( resultType, vecSize ); + + switch( resultType ) + { + case MATERIAL_VAR_TYPE_VECTOR: + { + Vector a, b; + m_pSrc1->GetVecValue( a.Base(), vecSize ); + m_pSrc2->GetVecValue( b.Base(), vecSize ); + + if ( !a.IsZero() ) + { + m_pResult->SetVecValue( a.Base(), vecSize ); + } + else + { + m_pResult->SetVecValue( b.Base(), vecSize ); + } + } + break; + + case MATERIAL_VAR_TYPE_FLOAT: + if ( m_pSrc1->GetFloatValue() ) + { + SetFloatResult( m_pSrc1->GetFloatValue() ); + } + else + { + SetFloatResult( m_pSrc2->GetFloatValue() ); + } + break; + + case MATERIAL_VAR_TYPE_INT: + if ( m_pSrc1->GetIntValue() ) + { + m_pResult->SetFloatValue( m_pSrc1->GetIntValue() ); + } + else + { + m_pResult->SetFloatValue( m_pSrc2->GetIntValue() ); + } + break; + } +} + + +class CModelBrowserMaterialProxyFactory : public IMaterialProxyFactory +{ +public: + virtual IMaterialProxy *CreateProxy( const char *proxyName ) + { + if ( V_stricmp( proxyName, "SelectFirstIfNonZero" ) == 0 ) + { + return new CSelectFirstIfNonZeroProxy; + } + else if ( V_stricmp( proxyName, "BurnLevel" ) == 0 ) + { + return new CFakeBurnLevelProxy; + } + return NULL; + } + + virtual void DeleteProxy( IMaterialProxy *pProxy ) + { + if ( pProxy ) + { + pProxy->Release(); + } + } +}; |