source-engine/hammer/mapoverlaytrans.cpp

390 lines
12 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//=============================================================================
#include <stdafx.h>
#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 <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// 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<CMapEntity*>( GetParent() );
if ( pEntity )
{
const CMapObjectList *pChildren = pEntity->GetChildren();
FOR_EACH_OBJ( *pChildren, pos )
{
CMapSideList *pSideList = dynamic_cast<CMapSideList*>( pChildren->Element(pos) );
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;
}