csgo-2018-source/hammer/toolsprinkle.cpp
2021-07-24 21:11:47 -07:00

1033 lines
25 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements the entity/prefab placement tool.
//
//=============================================================================//
#include "stdafx.h"
#include "History.h"
#include "MainFrm.h"
#include "MapDefs.h"
#include "MapSolid.h"
#include "MapDoc.h"
#include "MapWorld.h"
#include "MapView2D.h"
#include "MapView3D.h"
#include "Material.h"
#include "materialsystem/IMesh.h"
#include "Render2D.h"
#include "Render3D.h"
#include "StatusBarIDs.h"
#include "TextureSystem.h"
#include "toolsprinkle.h"
#include "ToolManager.h"
#include "hammer.h"
#include "vgui/Cursor.h"
#include "Selection.h"
#include "vstdlib/random.h"
#include "KeyValues.h"
#include "entitysprinkledlg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define SPRINKLE_PATH "scripts/hammer/sprinkle/"
//#pragma warning(disable:4244)
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CToolEntitySprinkle::CToolEntitySprinkle(void)
{
SetEmpty();
m_vecPos.Init();
pSprinkleDlg = NULL;
m_pSprinkleInfo = NULL;
m_OrigBrushSize = m_BrushSize = 256;
m_vMousePoint.Init();
m_bWorldValid = false;
m_vWorldMousePoint.Init();
m_InSizingMode = false;
m_InDrawMode = false;
m_bCtrlDown = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CToolEntitySprinkle::~CToolEntitySprinkle(void)
{
}
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgoff.h>
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::OnActivate()
{
if ( pSprinkleDlg == NULL )
{
pSprinkleDlg = new CEntitySprinkleDlg();
pSprinkleDlg->Create( CEntitySprinkleDlg::IDD, NULL );
}
if ( m_pSprinkleInfo != NULL )
{
m_pSprinkleInfo->deleteThis();
m_pSprinkleInfo = NULL;
}
m_pSprinkleInfo = new KeyValues( "Sprinkles" );
FileFindHandle_t findHandle;
const char *pFileName = g_pFullFileSystem->FindFirstEx( SPRINKLE_PATH "*.txt", "GAME", &findHandle );
while( pFileName )
{
CString FullPath = SPRINKLE_PATH;
FullPath += pFileName;
KeyValues *pLocalInfo = new KeyValues( "loading" );
if ( !pLocalInfo->LoadFromFile( g_pFileSystem, FullPath, "GAME" ) )
{
pLocalInfo->deleteThis();
}
m_pSprinkleInfo->AddSubKey( pLocalInfo );
pFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
pSprinkleDlg->SetSprinkleTypes( m_pSprinkleInfo );
pSprinkleDlg->ShowWindow( SW_SHOW );
}
void CToolEntitySprinkle::OnDeactivate()
{
pSprinkleDlg->ShowWindow( SW_HIDE );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pt -
// BOOL -
// Output :
//-----------------------------------------------------------------------------
int CToolEntitySprinkle::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles)
{
return HitRect( pView, ptClient, m_vecPos, 8 )?TRUE:FALSE;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bSave -
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::FinishTranslation(bool bSave)
{
Tool3D::FinishTranslation(bSave);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pt -
// uFlags -
// size -
// Output : Returns true if the translation delta was nonzero.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::UpdateTranslation( const Vector &vUpdate, UINT uFlags)
{
return true;
}
//-----------------------------------------------------------------------------
// Purpose: determines if any of the special keys ( control, shift, alt ) are pressed
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::DetermineKeysDown( )
{
m_bCtrlDown = ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
// m_bShiftDown = ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) != 0 );
// m_bAltDown = ( ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) != 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pRender -
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::RenderTool2D(CRender2D *pRender)
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pView -
// point -
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnContextMenu2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
{
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pView -
// nChar -
// nRepCnt -
// nFlags -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnKeyDown2D(CMapView2D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_RETURN:
{
return true;
}
case VK_ESCAPE:
{
OnEscape();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pView -
// nFlags -
// point -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
{
Tool3D::OnLMouseDown2D(pView, nFlags, vPoint);
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : Pre CWnd::OnLButtonUp.
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnLMouseUp2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
{
Tool3D::OnLMouseUp2D(pView, nFlags, vPoint);
return true;
}
//-----------------------------------------------------------------------------
// Returns true if the message was handled, false otherwise.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnMouseMove2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
{
Tool3D::OnMouseMove2D(pView, nFlags, vPoint);
return true;
}
//-----------------------------------------------------------------------------
// Returns true if the message was handled, false otherwise.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnMouseMove3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
{
DetermineKeysDown();
#if 0
Vector vecWorld;
pView->ClientToWorld( vecWorld, vPoint );
m_MousePoint.x = vecWorld.x;
m_MousePoint.y = vecWorld.y;
#else
if ( m_InSizingMode == true )
{
DoSizing( vPoint );
}
else
{
if ( FindWorldMousePoint( pView, vPoint ) == true )
{
if ( m_InDrawMode == true )
{
PerformSprinkle( false );
}
}
}
#endif
return true;
}
//-----------------------------------------------------------------------------
// Returns true if the message was handled, false otherwise.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnKeyDown3D(CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
{
CMapDoc *pDoc = pView->GetMapDoc();
if (pDoc == NULL)
{
return false;
}
switch (nChar)
{
case VK_RETURN:
{
return true;
}
case VK_ESCAPE:
{
OnEscape();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Handles the escape key in the 2D or 3D views.
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::OnEscape(void)
{
ToolManager()->SetTool( TOOL_PICK_ENTITY );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pView -
// nFlags -
// point -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
{
DetermineKeysDown();
if ( FindWorldMousePoint( pView, vPoint ) == true && m_InSizingMode == false )
{
m_InDrawMode = true;
PerformSprinkle( true );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pView -
// nFlags -
// point -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnLMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
{
DetermineKeysDown();
m_InDrawMode = false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
{
DetermineKeysDown();
if ( FindWorldMousePoint( pView, vPoint ) == true )
{
m_InDrawMode = false;
DoSizing( vPoint );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
{
DetermineKeysDown();
m_InSizingMode = false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Renders a selection gizmo at our bounds center.
// Input : pRender - Rendering interface.
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::RenderTool3D(CRender3D *pRender)
{
if ( m_bWorldValid == true )
{
pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
if ( m_InSizingMode )
{ // yellow for sizing mode
pRender->RenderWireframeSphere( m_vWorldMousePoint, m_BrushSize, 12, 12, 255, 255, 0 );
}
else
{
if ( m_bCtrlDown == true )
{
pRender->RenderWireframeSphere( m_vWorldMousePoint, m_BrushSize, 12, 12, 255, 0, 0 );
}
else
{
pRender->RenderWireframeSphere( m_vWorldMousePoint, m_BrushSize, 12, 12, 0, 255, 0 );
}
KeyValues *pSprinkleType = pSprinkleDlg->GetSprinkleType( );
if ( pSprinkleType != NULL )
{
float flGridXSize, flGridYSize;
float flXSize, flYSize;
Vector vCenter;
float flBrushSizeSq = m_BrushSize * m_BrushSize;
Vector vOffset = Vector( 0.0f, 0.0f, 64.0f );
CalcGridInfo( pSprinkleType, flGridXSize, flGridYSize, flXSize, flYSize, vCenter );
pRender->SetDrawColor( 255, 255, 0 );
for( float x = -flXSize; x <= flXSize; x += flGridXSize )
{
for( float y = -flYSize; y <= flYSize; y += flGridYSize )
{
#if 0
if ( ( ( x * x ) + ( y * y ) ) > flBrushSizeSq )
{
continue;
}
#endif
Vector vOrigin = vCenter + Vector( x, y, 0.0f );
if ( CToolEntitySprinkle::FindWorldSpot( vOrigin ) == true )
{
Vector vDelta = vOrigin - m_vWorldMousePoint;
if ( vDelta.LengthSqr() > flBrushSizeSq )
{
continue;
}
Vector vEnd = vOrigin + vOffset;
pRender->DrawLine( vOrigin, vEnd );
}
}
}
}
}
pRender->PopRenderMode();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::RemoveMapObjects( Vector &vOrigin, KeyValues *pSprinkleType, int nMode, int nDensity, CUtlVector< CMapEntity * > *pRemovedEntities, CMapEntity *pTouchedEntity )
{
float flCheckSizeSq;
KeyValues *pBaseInfo = pSprinkleType->FindKey( "base" );
KeyValues *pBaseClass = NULL;
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
CMapWorld *pWorld = pDoc->GetMapWorld();
const CMapEntityList *pEntityList = pWorld->EntityList_GetList();
CUtlVector< CMapEntity *> RemoveList;
Vector m_CheckOrigin;
if ( pTouchedEntity != NULL )
{
pTouchedEntity->GetOrigin( m_CheckOrigin );
flCheckSizeSq = 32 * 32;
}
else
{
m_CheckOrigin = m_vWorldMousePoint;
flCheckSizeSq = m_BrushSize * m_BrushSize;
}
if ( pBaseInfo != NULL )
{
pBaseClass = pBaseInfo->FindKey( "classname" );
}
FOR_EACH_OBJ( *pEntityList, pos )
{
CMapEntity *pEntity = ( CUtlReference< CMapEntity > )pEntityList->Element( pos );
if ( pEntity == NULL || pEntity == pTouchedEntity )
{
continue;
}
if ( pEntity->IsVisible() == false )
{
continue;
}
Vector vOrigin;
pEntity->GetOrigin( vOrigin );
Vector vDelta = vOrigin - m_CheckOrigin;
if ( vDelta.LengthSqr() > flCheckSizeSq )
{
continue;
}
if ( IsInSprinkle( pSprinkleType, pEntity->GetClassName() ) == false )
{
continue;
}
bool bRemove = false;
if ( pBaseClass != NULL && pEntity->ClassNameMatches( pBaseClass->GetString() )== true )
{
bRemove = true;
}
else
{
for ( KeyValues *pSub = pSprinkleType->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
KeyValues *pClass = pSub->FindKey( "classname" );
if ( pClass != NULL && pEntity->ClassNameMatches( pClass->GetString() )== true )
{
bRemove = true;
break;
}
}
}
if ( nMode == SPRINKLE_MODE_SUBTRACTIVE && pTouchedEntity == NULL )
{
if ( RandomInt( 1, 100 ) > nDensity )
{
continue;
}
}
if ( bRemove == true )
{
RemoveList.AddToTail( pEntity );
if ( pRemovedEntities != NULL )
{
pRemovedEntities->AddToTail( pEntity );
}
}
}
if ( nMode != SPRINKLE_MODE_OVERWRITE )
{
for( int i = 0; i < RemoveList.Count(); i++ )
{
GetHistory()->KeepForDestruction( RemoveList[ i ] );
pDoc->RemoveObjectFromWorld( RemoveList[ i ], true );
}
}
}
static const char *pszReserved[ ] =
{
"classname",
"grid",
NULL
};
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::PopulateEntity( CMapEntity *pEntity, KeyValues *pFields )
{
if ( pFields != NULL )
{
for ( KeyValues *pSub = pFields->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
int i;
for( i = 0; pszReserved[ i ] != NULL; i++ )
{
if ( strcmpi( pSub->GetName(), pszReserved[ i ] ) == 0 )
{
break;
}
}
if ( pszReserved[ i ] == NULL )
{
pEntity->SetKeyValue( pSub->GetName(), pSub->GetString() );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::CreateMapObject( Vector &vOrigin, KeyValues *pSprinkleType, int nMode, bool bRandomYaw, CMapEntity *pExisting )
{
int nTotal = 0;
KeyValues *pUseInfo = NULL;
for ( KeyValues *pSub = pSprinkleType->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
nTotal += atoi( pSub->GetName() );
}
int nPick = RandomInt( 1, nTotal );
nTotal = 0;
for ( KeyValues *pSub = pSprinkleType->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
nTotal += atoi( pSub->GetName() );
if ( nPick <= nTotal )
{
pUseInfo = pSub;
break;
}
}
if ( pUseInfo == NULL )
{
return;
}
KeyValues *pBaseInfo = pSprinkleType->FindKey( "base" );
KeyValues *pClass = pUseInfo->FindKey( "classname" );
if ( pClass == NULL )
{
if ( pBaseInfo != NULL )
{
pClass = pBaseInfo->FindKey( "classname" );
}
}
if ( pClass == NULL )
{
return;
}
CMapEntity *pEntity;
if ( pExisting != NULL )
{
pEntity = pExisting;
}
else
{
pEntity = new CMapEntity;
}
pEntity->SetOrigin( vOrigin );
pEntity->SetClass( pClass->GetString() );
PopulateEntity( pEntity, pBaseInfo );
PopulateEntity( pEntity, pUseInfo );
if ( bRandomYaw == true )
{
QAngle vAngles;
pEntity->GetAngles( vAngles );
vAngles[ YAW ] = ( float )RandomInt( 0.0f, 360.0f );
pEntity->SetAngles( vAngles );
}
if ( pExisting == NULL )
{
m_pDocument->AddObjectToWorld( pEntity );
GetHistory()->KeepNew( pEntity );
RemoveMapObjects( vOrigin, pSprinkleType, nMode, 0, NULL, pEntity );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::FindWorldMousePoint( CMapView3D *pView, const Vector2D &vPoint )
{
m_vMousePoint = vPoint;
ULONG ulFace;
CMapClass *pObject = pView->NearestObjectAt( m_vMousePoint, ulFace, FLAG_OBJECTS_AT_RESOLVE_INSTANCES | FLAG_OBJECTS_AT_ONLY_SOLIDS, &m_LocalMatrix );
m_bWorldValid = false;
if (pObject != NULL)
{
CMapSolid *pSolid = dynamic_cast <CMapSolid *> ( pObject );
if ( pSolid == NULL )
{ // Clicked on a point entity - do nothing.
return false;
}
m_LocalMatrix.InverseTR( m_LocalMatrixNeg );
// Build a ray to trace against the face that they clicked on to
// find the point of intersection.
Vector Start, End;
pView->GetCamera()->BuildRay( vPoint, Start, End);
Vector HitPos, HitNormal;
m_pHitFace = pSolid->GetFace( ulFace );
Vector vFinalStart, vFinalEnd;
m_LocalMatrixNeg.V3Mul( Start, vFinalStart );
m_LocalMatrixNeg.V3Mul( End, vFinalEnd );
if ( m_pHitFace->TraceLineInside( HitPos, HitNormal, vFinalStart, vFinalEnd ) )
{
Vector vFinalHitPos, vFinalHitNormal;
m_LocalMatrix.V3Mul( HitPos, vFinalHitPos );
vFinalHitNormal = m_LocalMatrix.ApplyRotation( HitNormal );
m_vWorldMousePoint = vFinalHitPos;
m_bWorldValid = true;
//CMapClass *pNewObject = NULL;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::FindWorldSpot( Vector &vOrigin )
{
Vector vStart, vEnd;
Vector vFinalStart, vFinalEnd;
Vector vHitPos, vHitNormal;
vStart = vOrigin - Vector( 0.0f, 0.0f, 600.0f );
vEnd = vOrigin + Vector( 0.0f, 0.0f, 600.0f );
m_LocalMatrixNeg.V3Mul( vStart, vFinalStart );
m_LocalMatrixNeg.V3Mul( vEnd, vFinalEnd );
if ( m_pHitFace->TraceLineInside( vHitPos, vHitNormal, vFinalStart, vFinalEnd ) )
{
Vector vFinalHitPos, vFinalHitNormal;
m_LocalMatrix.V3Mul( vHitPos, vFinalHitPos );
vFinalHitNormal = m_LocalMatrix.ApplyRotation( vHitNormal );
vOrigin = vFinalHitPos;
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::IsInSprinkle( KeyValues *pSprinkleType, const char *pszClassname )
{
KeyValues *pBaseInfo = pSprinkleType->FindKey( "base" );
if ( pBaseInfo != NULL )
{
KeyValues *pClass = pBaseInfo->FindKey( "classname" );
if ( pClass != NULL && strcmpi( pClass->GetString(), pszClassname ) == 0 )
{
return true;
}
}
for ( KeyValues *pSub = pSprinkleType->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
KeyValues *pClass = pSub->FindKey( "classname" );
if ( pClass != NULL && strcmpi( pClass->GetString(), pszClassname ) == 0 )
{
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
const char *CToolEntitySprinkle::FindField( KeyValues *pSprinkleType, const char *pszClassname, const char *pszFieldName )
{
KeyValues *pFoundClass = NULL;
for ( KeyValues *pSub = pSprinkleType->GetFirstSubKey() ; pSub != NULL; pSub = pSub->GetNextKey() )
{
KeyValues *pClass = pSub->FindKey( "classname" );
if ( pClass != NULL && strcmpi( pClass->GetString(), pszClassname ) == 0 )
{
pFoundClass = pClass;
break;
}
}
if ( pFoundClass != NULL )
{
pFoundClass = pFoundClass->FindKey( pszFieldName, false );
if ( pFoundClass != NULL )
{
return pFoundClass->GetString();
}
}
KeyValues *pBaseInfo = pSprinkleType->FindKey( "base" );
if ( pBaseInfo != NULL )
{
pFoundClass = pBaseInfo->FindKey( pszFieldName, false );
if ( pFoundClass != NULL )
{
return pFoundClass->GetString();
}
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose: toggles the sizing mode
// Input : vPoint - the mouse point
// Output : returns true if successful
//-----------------------------------------------------------------------------
bool CToolEntitySprinkle::DoSizing( const Vector2D &vPoint )
{
if ( !m_InSizingMode )
{
m_InSizingMode = true;
m_StartSizingPoint = vPoint;
m_OrigBrushSize = m_BrushSize;
}
else
{
m_BrushSize = m_OrigBrushSize + ( vPoint.x - m_StartSizingPoint.x );
if ( m_BrushSize < 1.0f )
{
m_BrushSize = 1.0f;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::CalcGridInfo( KeyValues *pSprinkleType, float &flGridXSize, float &flGridYSize, float &flXSize, float &flYSize, Vector &vCenter )
{
flGridXSize = 64;
flGridYSize = 64;
if ( pSprinkleDlg->UseDefinitionGridSize() )
{
KeyValues *pBaseInfo = pSprinkleType->FindKey( "base" );
if ( pBaseInfo != NULL )
{
KeyValues *pGridInfo = pBaseInfo->FindKey( "grid" );
if ( pGridInfo != NULL )
{
sscanf( pGridInfo->GetString(), "%g %g", &flGridXSize, &flGridYSize );
}
}
}
else
{
pSprinkleDlg->GetGridSize( flGridXSize, flGridYSize );
}
flXSize = ceil( m_BrushSize / flGridXSize ) * flGridXSize;
flYSize = ceil( m_BrushSize / flGridYSize ) * flGridXSize;
vCenter = m_vWorldMousePoint;
vCenter.x -= fmod( vCenter.x, flGridXSize );
vCenter.y -= fmod( vCenter.y, flGridYSize );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CToolEntitySprinkle::PerformSprinkle( bool bInitial )
{
if ( m_bWorldValid == false )
{
return;
}
KeyValues *pSprinkleType = pSprinkleDlg->GetSprinkleType( );
if ( pSprinkleType == NULL )
{
return;
}
int nDensity = pSprinkleDlg->GetSprinkleDensity();
int nMode = pSprinkleDlg->GetSprinkleMode();
bool bRandomYaw = pSprinkleDlg->UseRandomYaw();
float flGridXSize, flGridYSize;
float flXSize, flYSize;
float flBrushSizeSq = m_BrushSize * m_BrushSize;
Vector vCenter = m_vWorldMousePoint;
CUtlVector< CMapEntity * > ReplacedEntities;
if ( bInitial == true )
{
GetHistory()->MarkUndoPosition( m_pDocument->GetSelection()->GetList(), "Sprinkle" );
}
else if ( m_vLastDrawPoint.x == vCenter.x && m_vLastDrawPoint.y == vCenter.y )
{
return;
}
CalcGridInfo( pSprinkleType, flGridXSize, flGridYSize, flXSize, flYSize, vCenter );
if ( m_bCtrlDown == true )
{
nMode = SPRINKLE_MODE_SUBTRACTIVE;
}
m_vLastDrawPoint = vCenter;
if ( nMode == SPRINKLE_MODE_REPLACE || nMode == SPRINKLE_MODE_OVERWRITE )
{
RemoveMapObjects( m_vWorldMousePoint, pSprinkleType, nMode, nDensity, &ReplacedEntities );
}
switch( nMode )
{
case SPRINKLE_MODE_OVERWRITE:
for( int i = 0; i < ReplacedEntities.Count(); i++ )
{
Vector vOrigin;
ReplacedEntities[ i ]->GetOrigin( vOrigin );
CreateMapObject( vOrigin, pSprinkleType, nMode, bRandomYaw, ReplacedEntities[ i ] );
}
break;
case SPRINKLE_MODE_SUBTRACTIVE:
break;
default:
for( float x = -flXSize; x <= flXSize; x += flGridXSize )
{
for( float y = -flYSize; y <= flYSize; y += flGridYSize )
{
#if 0
if ( ( ( x * x ) + ( y * y ) ) > flBrushSizeSq )
{
continue;
}
#endif
int nValue = RandomInt( 1, 100 );
if ( nValue > nDensity )
{
continue;
}
Vector vOrigin = vCenter + Vector( x, y, 0.0f );
if ( CToolEntitySprinkle::FindWorldSpot( vOrigin ) == true )
{
Vector vDelta = vOrigin - m_vWorldMousePoint;
if ( vDelta.LengthSqr() > flBrushSizeSq )
{
continue;
}
CreateMapObject( vOrigin, pSprinkleType, nMode, bRandomYaw );
}
}
}
break;
}
if ( nMode == SPRINKLE_MODE_SUBTRACTIVE )
{
RemoveMapObjects( m_vWorldMousePoint, pSprinkleType, nMode, nDensity );
}
m_pDocument->SetModifiedFlag();
}