//========= Copyright © 1996-2004, Valve LLC, All rights reserved. ============ // // //============================================================================= #include #include "MapEntity.h" #include "MapOverlayTrans.h" #include "DispShore.h" #include "TextureSystem.h" #include "ChunkFile.h" // memdbgon must be the last include file in a .cpp file!!! #include //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CMapOverlayTransition::CMapOverlayTransition() { m_ShoreData.m_pTexture = NULL; m_ShoreData.m_vecLengthTexcoord.Init(); m_ShoreData.m_vecWidthTexcoord.Init(); m_ShoreData.m_flWidths[0] = 0.0f; m_ShoreData.m_flWidths[1] = 0.0f; m_bIsWater = true; m_aFaceCache1.Purge(); m_aFaceCache2.Purge(); m_bDebugDraw = false; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CMapOverlayTransition::~CMapOverlayTransition() { } //----------------------------------------------------------------------------- // Purpose: // NOTE: static //----------------------------------------------------------------------------- CMapClass *CMapOverlayTransition::Create( CHelperInfo *pInfo, CMapEntity *pParent ) { CMapOverlayTransition *pOverlayTrans = new CMapOverlayTransition; return pOverlayTrans; } //----------------------------------------------------------------------------- // Purpose: Called after the entire map has been loaded. This allows the object // to perform any linking with other map objects or to do other operations // that require all world objects to be present. // Input : pWorld - The world that we are in. //----------------------------------------------------------------------------- void CMapOverlayTransition::PostloadWorld( CMapWorld *pWorld ) { OnApply(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::CalcBounds( BOOL bFullUpdate ) { CMapClass::CalcBounds( bFullUpdate ); Shoreline_t *pShoreline = GetShoreManager()->GetShoreline( ( int )GetParent() ); if ( pShoreline ) { Vector vecMins( 99999.0f, 99999.0f, 99999.0f ); Vector vecMaxs( -99999.0f, -99999.0f, -99999.0f ); m_Render2DBox.ResetBounds(); m_CullBox.ResetBounds(); int nSegmentCount = pShoreline->m_aSegments.Count(); for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment ) { for ( int iAxis = 0; iAxis < 3; ++iAxis ) { if ( pShoreline->m_aSegments[iSegment].m_vecPoints[0][iAxis] < vecMins[iAxis] ) { vecMins[iAxis] = pShoreline->m_aSegments[iSegment].m_vecPoints[0][iAxis]; } if ( pShoreline->m_aSegments[iSegment].m_vecPoints[1][iAxis] < vecMins[iAxis] ) { vecMins[iAxis] = pShoreline->m_aSegments[iSegment].m_vecPoints[1][iAxis]; } if ( pShoreline->m_aSegments[iSegment].m_vecPoints[0][iAxis] > vecMaxs[iAxis] ) { vecMaxs[iAxis] = pShoreline->m_aSegments[iSegment].m_vecPoints[0][iAxis]; } if ( pShoreline->m_aSegments[iSegment].m_vecPoints[1][iAxis] > vecMaxs[iAxis] ) { vecMaxs[iAxis] = pShoreline->m_aSegments[iSegment].m_vecPoints[1][iAxis]; } } } m_Render2DBox.UpdateBounds( vecMins, vecMaxs ); m_CullBox = m_Render2DBox; m_BoundingBox = m_CullBox; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CMapClass *CMapOverlayTransition::Copy( bool bUpdateDependencies ) { CMapOverlayTransition *pCopy = new CMapOverlayTransition; if ( pCopy ) { pCopy->CopyFrom( this, bUpdateDependencies ); } return pCopy; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CMapClass *CMapOverlayTransition::CopyFrom( CMapClass *pObject, bool bUpdateDependencies ) { // Verify the object is of the correct type and cast. Assert( pObject->IsMapClass( MAPCLASS_TYPE( CMapOverlayTransition ) ) ); CMapOverlayTransition *pFrom = ( CMapOverlayTransition* )pObject; if ( pFrom ) { m_ShoreData.m_pTexture = pFrom->m_ShoreData.m_pTexture; m_ShoreData.m_vecLengthTexcoord = pFrom->m_ShoreData.m_vecLengthTexcoord; m_ShoreData.m_vecWidthTexcoord = pFrom->m_ShoreData.m_vecWidthTexcoord; m_ShoreData.m_flWidths[0] = pFrom->m_ShoreData.m_flWidths[0]; m_ShoreData.m_flWidths[1] = pFrom->m_ShoreData.m_flWidths[1]; } return this; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnParentKeyChanged( const char* szKey, const char* szValue ) { // Material data. if ( !stricmp( szKey, "material" ) ) { IEditorTexture *pTex = g_Textures.FindActiveTexture( szValue ); if ( pTex ) { m_ShoreData.m_pTexture = pTex; } } // Texture data. if ( !stricmp( szKey, "LengthTexcoordStart" ) ) { m_ShoreData.m_vecLengthTexcoord[0] = atof( szValue ); } if ( !stricmp( szKey, "LengthTexcoordEnd" ) ) { m_ShoreData.m_vecLengthTexcoord[1] = atof( szValue ); } if ( !stricmp( szKey, "WidthTexcoordStart" ) ) { m_ShoreData.m_vecWidthTexcoord[0] = atof( szValue ); } if ( !stricmp( szKey, "WidthTexcoordEnd" ) ) { m_ShoreData.m_vecWidthTexcoord[1] = atof( szValue ); } // Width data. if ( !stricmp( szKey, "Width1" ) ) { m_ShoreData.m_flWidths[0] = atof( szValue ); } if ( !stricmp( szKey, "Width2" ) ) { m_ShoreData.m_flWidths[1] = atof( szValue ); } // Debug data. if ( !stricmp( szKey, "DebugDraw" ) ) { m_bDebugDraw = true; if ( atoi( szValue ) == 0 ) { m_bDebugDraw = false; } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnNotifyDependent( CMapClass *pObject, Notify_Dependent_t eNotifyType ) { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnAddToWorld( CMapWorld *pWorld ) { OnApply(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnRemoveFromWorld( CMapWorld *pWorld, bool bNotifyChildren ) { GetShoreManager()->RemoveShoreline( ( int )GetParent() ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnUndoRedo( void ) { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::DoTransform( const VMatrix& matrix ) { return; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnPaste( CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList) { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::OnClone( CMapClass *pClone, CMapWorld *pWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList ) { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapOverlayTransition::Render3D( CRender3D *pRender ) { GetShoreManager()->Draw( pRender ); if ( m_bDebugDraw ) { GetShoreManager()->DebugDraw( pRender ); } } //----------------------------------------------------------------------------- // Purpose: Generate a face list from the parent entities' side list child. //----------------------------------------------------------------------------- bool CMapOverlayTransition::BuildFaceCaches( void ) { CMapEntity *pEntity = dynamic_cast( GetParent() ); if ( pEntity ) { const CMapObjectList *pChildren = pEntity->GetChildren(); FOR_EACH_OBJ( *pChildren, pos ) { CMapClass *pMapClass = (CUtlReference< CMapClass >)pChildren->Element(pos); CMapSideList *pSideList = dynamic_cast( pMapClass ); if ( pSideList ) { // Check name. if ( !stricmp( "sides" ,pSideList->GetKeyName() ) ) { int nFaceCount = pSideList->GetFaceCount(); for ( int iFace = 0; iFace < nFaceCount; ++iFace ) { m_aFaceCache1.AddToTail( pSideList->GetFace( iFace ) ); } } else if ( !stricmp( "sides2", pSideList->GetKeyName() ) ) { int nFaceCount = pSideList->GetFaceCount(); for ( int iFace = 0; iFace < nFaceCount; ++iFace ) { if ( m_bIsWater ) { // Verify that the face is a water face. if ( pSideList->GetFace( iFace )->GetTexture()->IsWater() ) { m_aFaceCache2.AddToTail( pSideList->GetFace( iFace ) ); } } else { m_aFaceCache2.AddToTail( pSideList->GetFace( iFace ) ); } } } } } } return ( ( m_aFaceCache1.Count() > 0 ) && ( m_aFaceCache2.Count() > 0 ) ); } //----------------------------------------------------------------------------- // Purpose: Create the transition overlays. //----------------------------------------------------------------------------- bool CMapOverlayTransition::OnApply( void ) { if ( m_bIsWater ) { // Create the shoreline. if ( GetShoreManager()->Init() ) { if ( BuildFaceCaches() ) { m_nShorelineId = ( int )GetParent(); GetShoreManager()->AddShoreline( m_nShorelineId ); Shoreline_t *pShoreline = GetShoreManager()->GetShoreline( m_nShorelineId ); pShoreline->m_ShoreData = m_ShoreData; GetShoreManager()->BuildShoreline( m_nShorelineId, m_aFaceCache1, m_aFaceCache2 ); // Clean up the face list. m_aFaceCache1.Purge(); m_aFaceCache2.Purge(); } GetShoreManager()->Shutdown(); } // Post updated. PostUpdate( Notify_Changed ); return true; } else { // This part is not implemented yet! return true; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- ChunkFileResult_t CMapOverlayTransition::LoadVMF( CChunkFile *pFile ) { // This doesn't need to be implemented until we can "edit" the overlay data. For // now just regenerate the data. return ChunkFile_Ok; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- ChunkFileResult_t CMapOverlayTransition::SaveVMF( CChunkFile *pFile, CSaveInfo *pSaveInfo ) { ChunkFileResult_t eResult = pFile->BeginChunk("overlaytransition"); m_nShorelineId = ( int )GetParent(); Shoreline_t *pShoreline = GetShoreManager()->GetShoreline( m_nShorelineId ); if ( pShoreline ) { int nOverlayCount = pShoreline->m_aOverlays.Count(); for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay ) { CMapOverlay *pOverlay = &pShoreline->m_aOverlays[iOverlay]; if ( pOverlay ) { pOverlay->SaveDataToVMF( pFile, pSaveInfo ); } } } if ( eResult == ChunkFile_Ok ) { eResult = pFile->EndChunk(); } return eResult; }