//======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ====== // // CSheetSequencePanel - Panel for selecting one sequence from a sprite sheet // //=============================================================================== #include "matsys_controls/sheetsequencepanel.h" #include "matsys_controls/matsyscontrols.h" #include "VGuiMatSurface/IMatSystemSurface.h" #include "materialsystem/imaterial.h" #include "tier1/keyvalues.h" #include "bitmap/psheet.h" #include "vgui/IScheme.h" #include "vgui/IVGui.h" #include "materialsystem/imaterialvar.h" // NOTE: This has to be the last file included! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // MOC_TODO: Power of two FB texture - do I really need to do this? static CTextureReference s_pPowerOfTwoFrameBufferTexture_SheetSeq; static ITexture *GetPowerOfTwoFrameBufferTexture( void ) { if ( !s_pPowerOfTwoFrameBufferTexture_SheetSeq ) { s_pPowerOfTwoFrameBufferTexture_SheetSeq.Init( vgui::MaterialSystem()->FindTexture( "_rt_PowerOfTwoFB", TEXTURE_GROUP_RENDER_TARGET ) ); } return s_pPowerOfTwoFrameBufferTexture_SheetSeq; } //----------------------------------------------------------------------------- // Statics bool CSheetSequencePanel::m_sMaterialsInitialized = false; CMaterialReference CSheetSequencePanel::m_sColorMat; CMaterialReference CSheetSequencePanel::m_sAlphaMat; const int SEQUENCE_PANEL_BORDER = 2; const int SEQUENCE_PANEL_MAX_SIZE = 256; CSheetSequencePanel::CSheetSequencePanel( vgui::Panel *pParent, const char *pPanelName ): BaseClass(pParent,pPanelName), m_pSheet(NULL), m_Material(NULL) { m_nHighlightedSequence = -1; m_bSeparateAlphaColorMaterial = false; m_bIsSecondSequenceView = false; EnsureMaterialsExist(); } void CSheetSequencePanel::EnsureMaterialsExist() { if ( !m_sMaterialsInitialized ) { KeyValues *pKeyValues = new KeyValues( "DebugTextureView" ); pKeyValues->SetString( "$basetexture", "" ); pKeyValues->SetInt( "$ShowAlpha", 1 ); m_sAlphaMat.Init( "SheetSequenceAlphaMaterial", pKeyValues ); m_sAlphaMat->Refresh(); pKeyValues = new KeyValues( "DebugTextureView" ); pKeyValues->SetString( "$basetexture", "" ); pKeyValues->SetInt( "$ShowAlpha", 0 ); m_sColorMat.Init( "SheetSequenceColorMaterial", pKeyValues ); m_sColorMat->Refresh(); m_sMaterialsInitialized = true; } } CSheetSequencePanel::~CSheetSequencePanel() { delete m_pSheet; m_pSheet = NULL; } void CSheetSequencePanel::PrepareMaterials() { if ( !m_Material ) { return; } m_bSeparateAlphaColorMaterial = CSheetExtended::IsMaterialSeparateAlphaColorMaterial( m_Material ); bool bFound = false; IMaterialVar *pVar = m_Material->FindVar( "$basetexture", &bFound ); if ( !pVar || !bFound || !pVar->IsDefined() ) return; ITexture *pTex = pVar->GetTextureValue(); if ( !pTex || pTex->IsError() ) return; ////////////////////////////// IMaterialVar *BaseTextureVar = m_sAlphaMat->FindVar( "$basetexture", &bFound ); if ( !bFound || !BaseTextureVar ) return; BaseTextureVar->SetTextureValue( pTex ); ////////////////////////////// BaseTextureVar = m_sColorMat->FindVar( "$basetexture", &bFound ); if ( !bFound || !BaseTextureVar ) return; BaseTextureVar->SetTextureValue( pTex ); } void CSheetSequencePanel::SetSecondSequenceView( bool bIsSecondSequenceView ) { m_bIsSecondSequenceView = bIsSecondSequenceView; } void CSheetSequencePanel::SetFromMaterialName( const char* pMaterialName ) { if ( m_pSheet ) { delete m_pSheet; } m_Material.Init( pMaterialName, "editor material" ); m_pSheet = new CSheetExtended(m_Material); PrepareMaterials(); PerformLayout(); } void CSheetSequencePanel::SetFromMaterial( IMaterial* sourceMaterial ) { if ( m_pSheet ) { delete m_pSheet; } m_Material.Init(sourceMaterial); m_pSheet = new CSheetExtended(m_Material); PrepareMaterials(); PerformLayout(); } void CSheetSequencePanel::PerformLayout() { int newWidth = SequenceGridCount() * SequenceGridSquareSize() + SEQUENCE_PANEL_BORDER*2; int newHeight = SequenceGridRows() * SequenceGridSquareSize() + SEQUENCE_PANEL_BORDER*2; if ( SequenceGridCount() == 0 ) { newWidth = 32; newHeight = 32; } SetSize( newWidth, newHeight ); Repaint(); } void CSheetSequencePanel::OnCursorExited() { m_nHighlightedSequence = -1; } void CSheetSequencePanel::OnCursorMoved(int x, int y) { BaseClass::OnCursorMoved(x,y); if ( m_pSheet == NULL || m_pSheet->GetSheetSequenceCount() == 0 ) { m_nHighlightedSequence = -1; return; } int nGridCount = SequenceGridCount(); int nGridSize = SequenceGridSquareSize(); int nGridX = (x - SEQUENCE_PANEL_BORDER) / nGridSize; int nGridY = (y - SEQUENCE_PANEL_BORDER) / nGridSize; if ( nGridX >= 0 && nGridY >= 0 && nGridX < nGridCount && nGridY < nGridCount ) { int nSeqIndex = nGridX + nGridY*nGridCount; if ( nSeqIndex < m_pSheet->GetSheetSequenceCount() ) { m_nHighlightedSequence = nSeqIndex; } else { m_nHighlightedSequence = -1; } } else { m_nHighlightedSequence = -1; } } int CSheetSequencePanel::SequenceGridCount() { return m_pSheet ? Ceil2Int(sqrt((float)m_pSheet->GetSheetSequenceCount())) : 0; } int CSheetSequencePanel::SequenceGridSquareSize() { int nGridCount = SequenceGridCount(); if ( nGridCount == 0 ) { return 0; } else { return (SEQUENCE_PANEL_MAX_SIZE / nGridCount); } } int CSheetSequencePanel::SequenceGridRows() { if ( !m_pSheet ) return 0; int nSequences = m_pSheet->GetSheetSequenceCount(); int nGridCount = SequenceGridCount(); if ( nSequences == 0 ) { return 0; } else { // nSequences / nGridCount, rounded up return (nSequences + nGridCount - 1) / nGridCount; } } void CSheetSequencePanel::OnMouseReleased( vgui::MouseCode mouseCode ) { if ( m_nHighlightedSequence != -1 ) { KeyValues *k = new KeyValues("SheetSequenceSelected"); k->SetPtr("panel", this); k->SetInt("nSequenceNumber", m_nHighlightedSequence); k->SetBool("bIsSecondSequence", m_bIsSecondSequenceView ); PostActionSignal( k ); } SetVisible(false); } void CSheetSequencePanel::Paint( void ) { int x, y, w, h; GetSize(w, h); GetPos(x,y); vgui::surface()->DrawSetColor( Color(0,0,0,255) ); vgui::surface()->DrawOutlinedRect( 1, 1, w-1, h-1 ); if ( m_pSheet == NULL || !m_pSheet->ValidSheetData() ) { return; } CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() ); vgui::MatSystemSurface()->Begin3DPaint( 2, 2, w-2, h-2 ); pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); pRenderContext->Ortho( 2, 2, w-2, h-2, -1.0f, 1.0f ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); // Deal with refraction if ( m_Material->NeedsPowerOfTwoFrameBufferTexture() ) { ITexture *pTexture = GetPowerOfTwoFrameBufferTexture(); if ( pTexture && !pTexture->IsError() ) { pRenderContext->CopyRenderTargetToTexture( pTexture ); pRenderContext->SetFrameBufferCopyTexture( pTexture ); } } Color bgColor = GetBgColor(); pRenderContext->ClearColor4ub( bgColor.r(), bgColor.g(), bgColor.b(), 255 ); pRenderContext->ClearBuffers( true, true ); pRenderContext->FogMode( MATERIAL_FOG_NONE ); pRenderContext->SetNumBoneWeights( 0 ); bool bOverrideSpriteCard = false; bool bOnlyColor = false; bool bOnlyAlpha = false; if ( m_bSeparateAlphaColorMaterial ) { if ( !m_bIsSecondSequenceView ) { pRenderContext->Bind( m_sAlphaMat ); bOnlyAlpha = true; } else { pRenderContext->Bind( m_sColorMat ); bOnlyColor = true; } bOverrideSpriteCard = true; } else { pRenderContext->Bind( m_Material ); } IMesh *pMesh = pRenderContext->GetDynamicMesh(); float flAge = fmodf( Plat_FloatTime(), m_pSheet->GetSequenceTimeSpan(0) ); int nGridCount = SequenceGridCount(); float flGridSquareSize = SequenceGridSquareSize(); float flOffset = 0.5f*flGridSquareSize+SEQUENCE_PANEL_BORDER; int nSequences = m_pSheet->GetSheetSequenceCount(); for ( int i = 0; i < nSequences; ++i ) { float x = i % nGridCount; float y = i / nGridCount; if ( bOnlyColor && !m_pSheet->SequenceHasColorData( i ) || bOnlyAlpha && !m_pSheet->SequenceHasAlphaData( i ) ) { continue; } m_pSheet->DrawSheet( pMesh, Vector(flOffset+x*flGridSquareSize,h-(flOffset+y*flGridSquareSize),0), flGridSquareSize*0.5f, i, flAge, 750.0f, true, -1, bOverrideSpriteCard ); } pRenderContext->PopMatrix(); pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PopMatrix(); vgui::MatSystemSurface()->End3DPaint( ); ////////////////////////////////////////////////////////////////////////// flOffset = SEQUENCE_PANEL_BORDER; for ( int i = 0; i < nSequences; ++i ) { float x = i % nGridCount; float y = i / nGridCount; Color drawColor = Color(0,0,0,255); if ( m_nHighlightedSequence == i ) { drawColor = Color(255,255,255,255); } vgui::surface()->DrawSetColor(drawColor); vgui::surface()->DrawSetTextColor(drawColor); vgui::surface()->DrawOutlinedRect( flOffset+x*flGridSquareSize, flOffset+y*flGridSquareSize, flOffset+(x+1)*flGridSquareSize, flOffset+(y+1)*flGridSquareSize ); wchar_t strBuffer[8]; V_snwprintf( strBuffer, ARRAYSIZE( strBuffer ), L"%d", i ); vgui::surface()->DrawSetTextFont( vgui::scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmall" ) ); vgui::surface()->DrawSetTextPos(flOffset+x*flGridSquareSize+2, flOffset+y*flGridSquareSize+1); vgui::surface()->DrawUnicodeString( strBuffer ); if ( bOnlyColor && !m_pSheet->SequenceHasColorData( i ) || bOnlyAlpha && !m_pSheet->SequenceHasAlphaData( i ) ) { vgui::surface()->DrawSetTextColor( Color(255,0,0,255) ); vgui::surface()->DrawSetTextPos(flOffset+(x+0.5f)*flGridSquareSize, flOffset+(y+0.5f)*flGridSquareSize+1); vgui::surface()->DrawUnicodeString( L"x" ); } } }