This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

View File

@@ -0,0 +1,664 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "DmeVMFEntity.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "toolframework/itoolentity.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystem.h"
#include "engine/iclientleafsystem.h"
#include "toolutils/enginetools_int.h"
#include "vcdblocktool.h"
#include "tier1/KeyValues.h"
// for tracing
#include "cmodel.h"
#include "engine/ienginetrace.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SPHERE_RADIUS 16
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeVMFEntity, CDmeVMFEntity );
//-----------------------------------------------------------------------------
// Used to store the next unique entity id;
//-----------------------------------------------------------------------------
int CDmeVMFEntity::s_nNextEntityId;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDmeVMFEntity::OnConstruction()
{
m_ClassName.Init( this, "classname", FATTRIB_HAS_CALLBACK );
m_TargetName.Init( this, "targetname" );
m_bIsPlaceholder.InitAndSet( this, "_placeholder", false, FATTRIB_DONTSAVE );
m_vecLocalOrigin.Init( this, "origin" );
m_vecLocalAngles.Init( this, "angles" );
m_bIsDeleted.Init( this, "deleted" );
if ( m_Name.Length() == 0 )
{
// Assign a unique ID to the name
char pNameString[128];
Q_snprintf( pNameString, sizeof(pNameString), "%d", GetNextEntityId() );
m_Name = pNameString;
}
// See if we need to bump the unique id up
int nEntityId = GetEntityId();
if ( s_nNextEntityId <= nEntityId )
{
s_nNextEntityId = nEntityId + 1;
}
// Get called back when the name changes
m_Name.GetAttribute()->AddFlag( FATTRIB_HAS_CALLBACK );
// Used to make sure these aren't saved if they aren't changed
//m_TargetName.GetAttribute()->AddFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
//m_vecLocalAngles.GetAttribute()->AddFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
m_bIsDirty = false;
m_bInfoTarget = false;
m_hEngineEntity = HTOOLHANDLE_INVALID;
m_Wireframe.Init( "debug/debugwireframevertexcolor", "editor" );
// FIXME: Need to abstract out rendering into a separate class
// based on information parsed from the FGD
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
pVMTKeyValues->SetString( "$basetexture", "editor/info_target" );
pVMTKeyValues->SetInt( "$nocull", 1 );
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
pVMTKeyValues->SetInt( "$no_fullbright", 1 );
pVMTKeyValues->SetInt( "$translucent", 1 );
m_InfoTargetSprite.Init( "__vcdblock_info_target", pVMTKeyValues );
pVMTKeyValues = new KeyValues( "UnlitGeneric" );
pVMTKeyValues->SetInt( "$nocull", 1 );
pVMTKeyValues->SetString( "$color", "{64 64 64}" );
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
pVMTKeyValues->SetInt( "$no_fullbright", 1 );
pVMTKeyValues->SetInt( "$additive", 1 );
m_SelectedInfoTarget.Init( "__selected_vcdblock_info_target", pVMTKeyValues );
}
void CDmeVMFEntity::OnDestruction()
{
// Unhook it from the engine
AttachToEngineEntity( false );
m_Wireframe.Shutdown();
m_SelectedInfoTarget.Shutdown();
m_InfoTargetSprite.Shutdown();
}
//-----------------------------------------------------------------------------
// Called whem attributes change
//-----------------------------------------------------------------------------
void CDmeVMFEntity::OnAttributeChanged( CDmAttribute *pAttribute )
{
BaseClass::OnAttributeChanged( pAttribute );
// Once these have changed, then save them out, and don't bother calling back
if ( pAttribute == m_TargetName.GetAttribute() ||
pAttribute == m_vecLocalAngles.GetAttribute() )
{
pAttribute->RemoveFlag( FATTRIB_DONTSAVE | FATTRIB_HAS_CALLBACK );
return;
}
if ( pAttribute == m_ClassName.GetAttribute() )
{
m_bInfoTarget = !Q_strncmp( m_ClassName, "info_target", 11 );
// FIXME: Change the model based on the current class
SetModelName( NULL );
return;
}
// Make sure we have unique ids for all entities
if ( pAttribute == m_Name.GetAttribute() )
{
int nEntityId = GetEntityId();
if ( s_nNextEntityId <= nEntityId )
{
s_nNextEntityId = nEntityId + 1;
}
}
}
//-----------------------------------------------------------------------------
// Returns the entity ID
//-----------------------------------------------------------------------------
int CDmeVMFEntity::GetEntityId() const
{
return atoi( GetName() );
}
//-----------------------------------------------------------------------------
// Returns the next available entity id
//-----------------------------------------------------------------------------
int CDmeVMFEntity::GetNextEntityId()
{
return s_nNextEntityId;
}
void CDmeVMFEntity::SetNextEntityId( int nEntityId )
{
s_nNextEntityId = nEntityId;
}
//-----------------------------------------------------------------------------
// Mark the entity as being dirty
//-----------------------------------------------------------------------------
void CDmeVMFEntity::MarkDirty( bool bDirty )
{
m_bIsDirty = bDirty;
// FIXME: this is doing two operations!!
CopyToServer();
}
//-----------------------------------------------------------------------------
// Is the renderable transparent?
//-----------------------------------------------------------------------------
bool CDmeVMFEntity::IsTransparent( void )
{
return m_bIsDirty || m_bInfoTarget || BaseClass::IsTransparent();
}
//-----------------------------------------------------------------------------
// Entity Key iteration
//-----------------------------------------------------------------------------
bool CDmeVMFEntity::IsEntityKey( CDmAttribute *pEntityKey )
{
return pEntityKey->IsFlagSet( FATTRIB_USERDEFINED );
}
CDmAttribute *CDmeVMFEntity::FirstEntityKey()
{
for ( CDmAttribute *pAttribute = FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
{
if ( IsEntityKey( pAttribute ) )
return pAttribute;
}
return NULL;
}
CDmAttribute *CDmeVMFEntity::NextEntityKey( CDmAttribute *pEntityKey )
{
if ( !pEntityKey )
return NULL;
for ( CDmAttribute *pAttribute = pEntityKey->NextAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
{
if ( IsEntityKey( pAttribute ) )
return pAttribute;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Attach/detach from an engine entity with the same editor index
//-----------------------------------------------------------------------------
void CDmeVMFEntity::AttachToEngineEntity( HTOOLHANDLE hToolHandle )
{
if ( m_hEngineEntity != HTOOLHANDLE_INVALID )
{
clienttools->SetEnabled( m_hEngineEntity, true );
}
m_hEngineEntity = hToolHandle;
if ( m_hEngineEntity != HTOOLHANDLE_INVALID )
{
clienttools->SetEnabled( m_hEngineEntity, false );
}
}
//-----------------------------------------------------------------------------
// Position and bounds for the model
//-----------------------------------------------------------------------------
const Vector &CDmeVMFEntity::GetRenderOrigin( void )
{
return m_vecLocalOrigin;
}
const QAngle &CDmeVMFEntity::GetRenderAngles( void )
{
return *(QAngle *)(&m_vecLocalAngles);
}
void CDmeVMFEntity::GetRenderBounds( Vector& mins, Vector& maxs )
{
if ( !m_bInfoTarget )
{
BaseClass::GetRenderBounds( mins, maxs );
return;
}
mins.Init( -SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS );
maxs.Init( SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS );
}
//-----------------------------------------------------------------------------
// Update renderable position
//-----------------------------------------------------------------------------
void CDmeVMFEntity::SetRenderOrigin( const Vector &vecOrigin )
{
m_vecLocalOrigin = vecOrigin;
clienttools->MarkClientRenderableDirty( this );
}
void CDmeVMFEntity::SetRenderAngles( const QAngle &angles )
{
m_vecLocalAngles.Set( Vector( angles.x, angles.y, angles.z ) ); // FIXME: angles is a vector due to the vmf "angles" having a problem parsing...
clienttools->MarkClientRenderableDirty( this );
}
//-----------------------------------------------------------------------------
// Draws the helper for the entity
//-----------------------------------------------------------------------------
void CDmeVMFEntity::DrawSprite( IMaterial *pMaterial )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
pRenderContext->Bind( pMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 4, 4 );
unsigned char nBaseR = 255;
unsigned char nBaseG = 255;
unsigned char nBaseB = 255;
unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
meshBuilder.Position3f( -SPHERE_RADIUS, -SPHERE_RADIUS, 0.0f );
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( SPHERE_RADIUS, -SPHERE_RADIUS, 0.0f );
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.TexCoord2f( 0, 1.0f, 1.0f );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( SPHERE_RADIUS, SPHERE_RADIUS, 0.0f );
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( -SPHERE_RADIUS, SPHERE_RADIUS, 0.0f );
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
meshBuilder.BoneWeight( 0, 1.0f );
meshBuilder.BoneMatrix( 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.FastIndex( 0 );
meshBuilder.FastIndex( 1 );
meshBuilder.FastIndex( 3 );
meshBuilder.FastIndex( 2 );
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws the helper for the entity
//-----------------------------------------------------------------------------
void CDmeVMFEntity::DrawDragHelpers( IMaterial *pMaterial )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
VMatrix worldToCamera;
// pRenderContext->GetMatrix( MATERIAL_VIEW, &worldToCamera );
worldToCamera.Identity();
worldToCamera.SetTranslation( m_vecLocalOrigin );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadMatrix( worldToCamera );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
pRenderContext->Bind( pMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
unsigned char nBaseR = 255;
unsigned char nBaseG = 255;
unsigned char nBaseB = 255;
unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( SPHERE_RADIUS * 10, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( 0, SPHERE_RADIUS * 10, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( 0, 0, SPHERE_RADIUS * 10 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
}
//-----------------------------------------------------------------------------
// Draws the helper for the entity
//-----------------------------------------------------------------------------
void CDmeVMFEntity::DrawFloorTarget( IMaterial *pMaterial )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
// test movement
Ray_t ray;
CTraceFilterWorldAndPropsOnly traceFilter;
CBaseTrace tr;
ray.Init( m_vecLocalOrigin.Get()+ Vector( 0, 0, 10 ), m_vecLocalOrigin.Get() + Vector( 0,0, -128 ), Vector( -13, -13, 0 ), Vector( 13, 13, 10 ) );
enginetools->TraceRayServer( ray, MASK_OPAQUE, &traceFilter, &tr );
VMatrix worldToCamera;
// pRenderContext->GetMatrix( MATERIAL_VIEW, &worldToCamera );
worldToCamera.Identity();
worldToCamera.SetTranslation( tr.endpos );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadMatrix( worldToCamera );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
pRenderContext->Bind( pMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
unsigned char nBaseR = 255;
unsigned char nBaseG = 255;
unsigned char nBaseB = 0;
unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
float block[4][2][3] = {
{ { -13, -13, 0 }, { -13, -13, 10 } },
{ { 13, -13, 0 }, { 13, -13, 10 } },
{ { 13, 13, 0 }, { 13, 13, 10 } },
{ { -13, 13, 0 }, { -13, 13, 10 } } };
for (int i = 0; i < 4; i++)
{
int j = (i + 1) % 4;
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[i][0][0], block[i][0][1], block[i][0][2] );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[i][1][0], block[i][1][1], block[i][1][2] );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[i][0][0], block[i][0][1], block[i][0][2] );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[j][0][0], block[j][0][1], block[j][0][2] );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[i][1][0], block[i][1][1], block[i][1][2] );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( nBaseR, nBaseG, nBaseB, nAlpha );
meshBuilder.Position3f( block[j][1][0], block[j][1][1], block[j][1][2] );
meshBuilder.AdvanceVertex();
}
// positive X
meshBuilder.Color4ub( 255, 0, 0, nAlpha );
meshBuilder.Position3f( 0, 0, 10 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 0, 0, nAlpha );
meshBuilder.Position3f( 10, 0, 10 );
meshBuilder.AdvanceVertex();
// positive Y
meshBuilder.Color4ub( 0, 255, 0, nAlpha );
meshBuilder.Position3f( 0, 0, 10 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 0, 255, 0, nAlpha );
meshBuilder.Position3f( 0, 10, 10 );
meshBuilder.AdvanceVertex();
// just Z
meshBuilder.Color4ub( 255, 255, 255, nAlpha );
meshBuilder.Position3f( 0, 0, 10 );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( 255, 255, 255, nAlpha );
meshBuilder.Position3f( 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
}
//-----------------------------------------------------------------------------
// Draws the helper for the entity
//-----------------------------------------------------------------------------
int CDmeVMFEntity::DrawModel( int flags )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
bool bSelected = ( g_pVcdBlockTool->GetCurrentEntity().Get() == this );
if ( !m_bInfoTarget )
{
// If we have a visible engine entity, we don't need to draw it here
// info targets always draw though, because they have no visible model.
CDisableUndoScopeGuard guard;
float t = 0.5f * sin( Plat_FloatTime() * M_PI / 1.0f ) + 0.5f;
unsigned char nAlpha = m_bIsDirty ? (unsigned char)(255 * t) : 255;
if ( bSelected )
{
GetMDL()->m_Color.SetColor( 255, 64, 64, nAlpha );
}
else
{
GetMDL()->m_Color.SetColor( 255, 255, 255, nAlpha );
}
return BaseClass::DrawModel( flags );
}
Assert( IsDrawingInEngine() );
matrix3x4_t mat;
VMatrix worldToCamera, cameraToWorld;
pRenderContext->GetMatrix( MATERIAL_VIEW, &worldToCamera );
MatrixInverseTR( worldToCamera, cameraToWorld );
MatrixCopy( cameraToWorld.As3x4(), mat );
MatrixSetColumn( m_vecLocalOrigin, 3, mat );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadMatrix( mat );
pRenderContext->FogMode( MATERIAL_FOG_NONE );
pRenderContext->SetNumBoneWeights( 0 );
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
DrawSprite( m_InfoTargetSprite );
if ( bSelected )
{
DrawSprite( m_SelectedInfoTarget );
DrawFloorTarget( m_Wireframe );
if (g_pVcdBlockTool->IsInNodeDrag())
{
DrawDragHelpers( m_Wireframe );
}
// DrawLine( Vector( 0, 0, 0 ), Vector( 10, 0, 0 ), 0, 255, 255, 255 );
}
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
return 1;
}
bool CDmeVMFEntity::CopyFromServer( CBaseEntity *pServerEnt )
{
CopyFromServer( pServerEnt, "targetname" );
CopyFromServer( pServerEnt, "classname" );
CopyFromServer( pServerEnt, "origin" );
CopyFromServer( pServerEnt, "angles" );
return true;
}
bool CDmeVMFEntity::CopyFromServer( CBaseEntity *pServerEnt, const char *szField )
{
return CopyFromServer( pServerEnt, szField, szField );
}
bool CDmeVMFEntity::CopyFromServer( CBaseEntity *pServerEnt, const char *szSrcField, const char *szDstField )
{
char text[256];
if ( servertools->GetKeyValue( pServerEnt, szSrcField, text, sizeof( text ) ) )
{
SetValueFromString( szDstField, text );
return true;
}
return false;
}
bool CDmeVMFEntity::CopyToServer( void )
{
if (GetEntityId() != 0)
{
CBaseEntity *pServerEntity = servertools->FindEntityByHammerID( GetEntityId() );
if (pServerEntity != NULL)
{
servertools->SetKeyValue( pServerEntity, "origin", m_vecLocalOrigin.Get() );
// FIXME: isn't there a string to vector conversion?
Vector tmp( m_vecLocalAngles.Get().x, m_vecLocalAngles.Get().y, m_vecLocalAngles.Get().z );
servertools->SetKeyValue( pServerEntity, "angles", tmp );
return true;
}
else
{
// FIXME: does one need to be spawned?
}
}
return false;
}
bool CDmeVMFEntity::IsSameOnServer( CBaseEntity *pServerEntity )
{
char text[256];
if (!pServerEntity)
{
return false;
}
// FIXME: check targetname? Can it be edited?
Vector mapOrigin;
servertools->GetKeyValue( pServerEntity, "origin", text, sizeof( text ) );
sscanf( text, "%f %f %f", &mapOrigin.x, &mapOrigin.y, &mapOrigin.z );
Vector mapAngles;
servertools->GetKeyValue( pServerEntity, "angles", text, sizeof( text ) );
sscanf( text, "%f %f %f", &mapAngles.x, &mapAngles.y, &mapAngles.z );
return ( mapOrigin == m_vecLocalOrigin.Get() && mapAngles == m_vecLocalAngles.Get() );
}
bool CDmeVMFEntity::CreateOnServer( void )
{
CBaseEntity *pServerEntity = servertools->CreateEntityByName( m_ClassName.Get() );
if (pServerEntity)
{
// test movement
Ray_t ray;
CTraceFilterWorldAndPropsOnly traceFilter;
CBaseTrace tr;
ray.Init( m_vecLocalOrigin.Get()+ Vector( 0, 0, 10 ), m_vecLocalOrigin.Get() + Vector( 0,0, -1000 ) );
enginetools->TraceRayServer( ray, MASK_OPAQUE, &traceFilter, &tr );
m_vecLocalOrigin.Set( tr.endpos );
servertools->SetKeyValue( pServerEntity, "hammerid", GetEntityId() );
servertools->SetKeyValue( pServerEntity, "targetname", m_TargetName.Get() );
servertools->SetKeyValue( pServerEntity, "origin", m_vecLocalOrigin.Get() );
servertools->SetKeyValue( pServerEntity, "angles", m_vecLocalAngles.Get() );
servertools->DispatchSpawn( pServerEntity );
return true;
}
return false;
}

View File

@@ -0,0 +1,131 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Represents an entity in a VMF
//
//=============================================================================
#ifndef DMEVMFENTITY_H
#define DMEVMFENTITY_H
#ifdef _WIN32
#pragma once
#endif
#include "toolutils/dmemdlrenderable.h"
#include "datamodel/dmelement.h"
#include "toolframework/itoolentity.h"
#include "materialsystem/MaterialSystemUtil.h"
//-----------------------------------------------------------------------------
// Represents an editable entity; draws its helpers
//-----------------------------------------------------------------------------
class CDmeVMFEntity : public CDmeMdlRenderable<CDmElement>
{
DEFINE_ELEMENT( CDmeVMFEntity, CDmeMdlRenderable<CDmElement> );
public:
// Inherited from CDmElement
virtual void OnAttributeChanged( CDmAttribute *pAttribute );
public:
// Inherited from DmeRenderable
virtual const Vector &GetRenderOrigin( void );
virtual const QAngle &GetRenderAngles( void );
virtual int DrawModel( int flags );
virtual bool IsTransparent( void );
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
public:
int GetEntityId() const;
// Returns the next available entity id
static int GetNextEntityId();
static void SetNextEntityId( int nEntityId );
const char *GetClassName() const;
const char *GetTargetName() const;
bool IsPlaceholder() const;
// Entity Key iteration
CDmAttribute *FirstEntityKey();
CDmAttribute *NextEntityKey( CDmAttribute *pEntityKey );
// Attach/detach from an engine entity with the same editor index
void AttachToEngineEntity( HTOOLHANDLE hToolHandle );
void SetRenderOrigin( const Vector &vecOrigin );
void SetRenderAngles( const QAngle &angles );
void MarkDirty( bool bDirty = true );
bool IsDirty( void ) { return m_bIsDirty; };
void MarkDeleted( bool bDeleted = true );
bool IsDeleted( void ) { return m_bIsDeleted; };
bool CopyFromServer( CBaseEntity *pServerEnt );
bool CopyFromServer( CBaseEntity *pServerEnt, const char *szField );
bool CopyFromServer( CBaseEntity *pServerEnt, const char *szSrcField, const char *szDstField );
bool CopyToServer( void );
bool IsSameOnServer( CBaseEntity *pServerEntity );
bool CreateOnServer( void );
private:
bool IsEntityKey( CDmAttribute *pEntityKey );
// Draws the helper for the entity
void DrawSprite( IMaterial *pMaterial );
void DrawDragHelpers( IMaterial *pMaterial );
void DrawFloorTarget( IMaterial *pMaterial );
CDmaVar<Vector> m_vecLocalOrigin;
// CDmAttributeVar<QAngle> m_vecLocalAngles;
CDmaVar<Vector> m_vecLocalAngles; // something funky with the vmf importer, it asserts when it's a QAngle
CDmaString m_ClassName;
CDmaString m_TargetName;
CDmaVar<bool> m_bIsPlaceholder;
// The entity it's connected to in the engine
HTOOLHANDLE m_hEngineEntity;
CMaterialReference m_Wireframe;
CMaterialReference m_SelectedInfoTarget;
CMaterialReference m_InfoTargetSprite;
// pretty sure this entity is edited
bool m_bIsDirty;
// entity needs to be deleted
CDmaVar<bool> m_bIsDeleted;
// FIXME: This is a hack for info targets
bool m_bInfoTarget;
// Used to store the next unique entity id;
static int s_nNextEntityId;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline const char *CDmeVMFEntity::GetClassName() const
{
return m_ClassName;
}
inline const char *CDmeVMFEntity::GetTargetName() const
{
return m_TargetName;
}
inline bool CDmeVMFEntity::IsPlaceholder() const
{
return m_bIsPlaceholder;
}
#endif // DMEVMFENTITY_H

View File

@@ -0,0 +1,297 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Singleton dialog that generates and presents the entity report.
//
//===========================================================================//
#include "InfoTargetBrowserPanel.h"
#include "tier1/KeyValues.h"
#include "tier1/utlbuffer.h"
#include "iregistry.h"
#include "vgui/ivgui.h"
#include "vgui_controls/listpanel.h"
#include "vgui_controls/textentry.h"
#include "vgui_controls/checkbutton.h"
#include "vgui_controls/combobox.h"
#include "vgui_controls/radiobutton.h"
#include "vgui_controls/messagebox.h"
#include "vcdblockdoc.h"
#include "vcdblocktool.h"
#include "datamodel/dmelement.h"
#include "vgui/keycode.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Sort by target name
//-----------------------------------------------------------------------------
static int __cdecl TargetNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("targetname");
const char *string2 = item2.kv->GetString("targetname");
int nRetVal = Q_stricmp( string1, string2 );
if ( nRetVal != 0 )
return nRetVal;
string1 = item1.kv->GetString("classname");
string2 = item2.kv->GetString("classname");
return Q_stricmp( string1, string2 );
}
//-----------------------------------------------------------------------------
// Sort by class name
//-----------------------------------------------------------------------------
static int __cdecl ClassNameSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("classname");
const char *string2 = item2.kv->GetString("classname");
int nRetVal = Q_stricmp( string1, string2 );
if ( nRetVal != 0 )
return nRetVal;
string1 = item1.kv->GetString("targetname");
string2 = item2.kv->GetString("targetname");
return Q_stricmp( string1, string2 );
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CInfoTargetBrowserPanel::CInfoTargetBrowserPanel( CVcdBlockDoc *pDoc, vgui::Panel* pParent, const char *pName )
: BaseClass( pParent, pName ), m_pDoc( pDoc )
{
SetPaintBackgroundEnabled( true );
m_pEntities = new vgui::ListPanel( this, "Entities" );
m_pEntities->AddColumnHeader( 0, "targetname", "Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
m_pEntities->AddColumnHeader( 1, "classname", "Class Name", 52, ListPanel::COLUMN_RESIZEWITHWINDOW );
m_pEntities->SetColumnSortable( 0, true );
m_pEntities->SetColumnSortable( 1, true );
m_pEntities->SetEmptyListText( "No info_targets" );
// m_pEntities->SetDragEnabled( true );
m_pEntities->AddActionSignalTarget( this );
m_pEntities->SetSortFunc( 0, TargetNameSortFunc );
m_pEntities->SetSortFunc( 1, ClassNameSortFunc );
m_pEntities->SetSortColumn( 0 );
LoadControlSettingsAndUserConfig( "resource/infotargetbrowserpanel.res" );
UpdateEntityList();
}
CInfoTargetBrowserPanel::~CInfoTargetBrowserPanel()
{
SaveUserConfig();
}
//-----------------------------------------------------------------------------
// Purpose: Shows the most recent selected object in properties window
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::OnProperties(void)
{
int iSel = m_pEntities->GetSelectedItem( 0 );
KeyValues *kv = m_pEntities->GetItem( iSel );
CDmeVMFEntity *pEntity = CastElement< CDmeVMFEntity >( (CDmElement *)kv->GetPtr( "entity" ) );
g_pVcdBlockTool->ShowEntityInEntityProperties( pEntity );
}
//-----------------------------------------------------------------------------
// Purpose: Deletes the marked objects.
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::OnDeleteEntities(void)
{
int iSel = m_pEntities->GetSelectedItem( 0 );
{
// This is undoable
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Entities", "Delete Entities" );
//
// Build a list of objects to delete.
//
int nCount = m_pEntities->GetSelectedItemsCount();
for (int i = 0; i < nCount; i++)
{
int nItemID = m_pEntities->GetSelectedItem(i);
KeyValues *kv = m_pEntities->GetItem( nItemID );
CDmeVMFEntity *pEntity = (CDmeVMFEntity *)kv->GetPtr( "entity" );
if ( pEntity )
{
m_pDoc->DeleteInfoTarget( pEntity );
}
}
}
// Update the list box selection.
if (iSel >= m_pEntities->GetItemCount())
{
iSel = m_pEntities->GetItemCount() - 1;
}
m_pEntities->SetSingleSelectedItem( iSel );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::OnKeyCodeTyped( vgui::KeyCode code )
{
if ( code == KEY_DELETE )
{
OnDeleteEntities();
}
else
{
BaseClass::OnKeyCodeTyped( code );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::OnItemSelected( void )
{
OnProperties();
}
//-----------------------------------------------------------------------------
// Select a particular node
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::SelectNode( CDmeVMFEntity *pNode )
{
m_pEntities->ClearSelectedItems();
for ( int nItemID = m_pEntities->FirstItem(); nItemID != m_pEntities->InvalidItemID(); nItemID = m_pEntities->NextItem( nItemID ) )
{
KeyValues *kv = m_pEntities->GetItem( nItemID );
CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
if ( pEntity == pNode )
{
m_pEntities->AddSelectedItem( nItemID );
break;
}
}
}
//-----------------------------------------------------------------------------
// Called when buttons are clicked
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "delete" ) )
{
// Confirm we want to do it
MessageBox *pConfirm = new MessageBox( "#VcdBlockDeleteObjects", "#VcdBlockDeleteObjectsMsg", g_pVcdBlockTool->GetRootPanel() );
pConfirm->AddActionSignalTarget( this );
pConfirm->SetOKButtonText( "Yes" );
pConfirm->SetCommand( new KeyValues( "DeleteEntities" ) );
pConfirm->SetCancelButtonVisible( true );
pConfirm->SetCancelButtonText( "No" );
pConfirm->DoModal();
return;
}
if ( !Q_stricmp( pCommand, "Save" ) )
{
g_pVcdBlockTool->Save();
return;
}
if ( !Q_stricmp( pCommand, "RestartMap" ) )
{
g_pVcdBlockTool->RestartMap();
return;
}
if ( !Q_stricmp( pCommand, "DropInfoTargets" ) )
{
g_pVcdBlockTool->EnterTargetDropMode();
return;
}
if ( !Q_stricmp( pCommand, "quicksave" ) )
{
g_pVcdBlockTool->QuickSave();
return;
}
if ( !Q_stricmp( pCommand, "quickload" ) )
{
g_pVcdBlockTool->QuickLoad();
return;
}
BaseClass::OnCommand( pCommand );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::UpdateEntityList(void)
{
m_pEntities->RemoveAll();
const CDmrElementArray<CDmElement> entityList( m_pDoc->GetEntityList() );
if ( !entityList.IsValid() )
return;
int nCount = entityList.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmElement *pEntity = entityList[i];
const char *pClassName = pEntity->GetValueString( "classname" );
if ( !pClassName || !pClassName[0] )
{
pClassName = "<no class>";
}
KeyValues *kv = new KeyValues( "node" );
kv->SetString( "classname", pClassName );
kv->SetPtr( "entity", pEntity );
const char *pTargetname = pEntity->GetValueString( "targetname" );
if ( !pTargetname || !pTargetname[0] )
{
pTargetname = "<no targetname>";
}
kv->SetString( "targetname", pTargetname );
int nItemID = m_pEntities->AddItem( kv, 0, false, false );
// Hide everything that isn't an info_target
m_pEntities->SetItemVisible( nItemID, !Q_stricmp( pClassName, "info_target" ) );
}
m_pEntities->SortList();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CInfoTargetBrowserPanel::Refresh(void)
{
for ( int nItemID = m_pEntities->FirstItem(); nItemID != m_pEntities->InvalidItemID(); nItemID = m_pEntities->NextItem( nItemID ) )
{
KeyValues *kv = m_pEntities->GetItem( nItemID );
CDmElement *pEntity = (CDmElement *)kv->GetPtr( "entity" );
const char *pTargetname = pEntity->GetValueString( "targetname" );
if ( !pTargetname || !pTargetname[0] )
{
pTargetname = "<no targetname>";
}
kv->SetString( "targetname", pTargetname );
}
}

View File

@@ -0,0 +1,68 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#ifndef INFOTARGETBROWSERPANEL_H
#define INFOTARGETBROWSERPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/editablepanel.h"
#include "tier1/utlstring.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CVcdBlockDoc;
class CDmeVMFEntity;
namespace vgui
{
class ComboBox;
class Button;
class TextEntry;
class ListPanel;
class CheckButton;
class RadioButton;
}
//-----------------------------------------------------------------------------
// Panel that shows all entities in the level
//-----------------------------------------------------------------------------
class CInfoTargetBrowserPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CInfoTargetBrowserPanel, vgui::EditablePanel );
public:
CInfoTargetBrowserPanel( CVcdBlockDoc *pDoc, vgui::Panel* pParent, const char *pName ); // standard constructor
virtual ~CInfoTargetBrowserPanel();
// Inherited from Panel
virtual void OnCommand( const char *pCommand );
virtual void OnKeyCodeTyped( vgui::KeyCode code );
// Methods related to updating the listpanel
void UpdateEntityList();
void Refresh();
// Select a particular node
void SelectNode( CDmeVMFEntity *pNode );
private:
// Messages handled
MESSAGE_FUNC( OnDeleteEntities, "DeleteEntities" );
MESSAGE_FUNC( OnItemSelected, "ItemSelected" );
// Shows the most recent selected object in properties window
void OnProperties();
CVcdBlockDoc *m_pDoc;
vgui::ListPanel *m_pEntities;
};
#endif // INFOTARGETBROWSERPANEL_H

View File

@@ -0,0 +1,225 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Singleton dialog that generates and presents the entity report.
//
//===========================================================================//
#include "InfoTargetPropertiesPanel.h"
#include "tier1/KeyValues.h"
#include "tier1/utlbuffer.h"
#include "iregistry.h"
#include "vgui/ivgui.h"
#include "vgui_controls/listpanel.h"
#include "vgui_controls/textentry.h"
#include "vgui_controls/checkbutton.h"
#include "vgui_controls/combobox.h"
#include "vgui_controls/radiobutton.h"
#include "vgui_controls/messagebox.h"
#include "vgui_controls/scrollbar.h"
#include "vcdblockdoc.h"
#include "vcdblocktool.h"
#include "datamodel/dmelement.h"
#include "dmevmfentity.h"
#include "dme_controls/soundpicker.h"
#include "dme_controls/soundrecordpanel.h"
#include "matsys_controls/picker.h"
#include "vgui_controls/fileopendialog.h"
#include "filesystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
class CScrollableEditablePanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CScrollableEditablePanel, vgui::EditablePanel );
public:
CScrollableEditablePanel( vgui::Panel *pParent, vgui::EditablePanel *pChild, const char *pName );
virtual ~CScrollableEditablePanel() {}
virtual void PerformLayout();
MESSAGE_FUNC( OnScrollBarSliderMoved, "ScrollBarSliderMoved" );
private:
vgui::ScrollBar *m_pScrollBar;
vgui::EditablePanel *m_pChild;
};
CScrollableEditablePanel::CScrollableEditablePanel( vgui::Panel *pParent, vgui::EditablePanel *pChild, const char *pName ) :
BaseClass( pParent, pName )
{
m_pChild = pChild;
m_pChild->SetParent( this );
m_pScrollBar = new vgui::ScrollBar( this, "VerticalScrollBar", true );
m_pScrollBar->SetWide( 16 );
m_pScrollBar->SetAutoResize( PIN_TOPRIGHT, AUTORESIZE_DOWN, 0, 0, -16, 0 );
m_pScrollBar->AddActionSignalTarget( this );
}
void CScrollableEditablePanel::PerformLayout()
{
BaseClass::PerformLayout();
m_pChild->SetWide( GetWide() - 16 );
m_pScrollBar->SetRange( 0, m_pChild->GetTall() );
m_pScrollBar->SetRangeWindow( GetTall() );
}
//-----------------------------------------------------------------------------
// Called when the scroll bar moves
//-----------------------------------------------------------------------------
void CScrollableEditablePanel::OnScrollBarSliderMoved()
{
InvalidateLayout();
int nScrollAmount = m_pScrollBar->GetValue();
m_pChild->SetPos( 0, -nScrollAmount );
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CInfoTargetPropertiesPanel::CInfoTargetPropertiesPanel( CVcdBlockDoc *pDoc, vgui::Panel* pParent )
: BaseClass( pParent, "InfoTargetPropertiesPanel" ), m_pDoc( pDoc )
{
SetPaintBackgroundEnabled( true );
SetKeyBoardInputEnabled( true );
m_pInfoTarget = new vgui::EditablePanel( (vgui::Panel*)NULL, "InfoTarget" );
m_pTargetName = new vgui::TextEntry( m_pInfoTarget, "TargetName" );
m_pTargetName->AddActionSignalTarget( this );
m_pTargetPosition[0] = new vgui::TextEntry( m_pInfoTarget, "PositionX" );
m_pTargetPosition[0]->AddActionSignalTarget( this );
m_pTargetPosition[1] = new vgui::TextEntry( m_pInfoTarget, "PositionY" );
m_pTargetPosition[1]->AddActionSignalTarget( this );
m_pTargetPosition[2] = new vgui::TextEntry( m_pInfoTarget, "PositionZ" );
m_pTargetPosition[2]->AddActionSignalTarget( this );
m_pTargetOrientation[0] = new vgui::TextEntry( m_pInfoTarget, "Pitch" );
m_pTargetOrientation[0]->AddActionSignalTarget( this );
m_pTargetOrientation[1] = new vgui::TextEntry( m_pInfoTarget, "Yaw" );
m_pTargetOrientation[1]->AddActionSignalTarget( this );
m_pTargetOrientation[2] = new vgui::TextEntry( m_pInfoTarget, "Roll" );
m_pTargetOrientation[2]->AddActionSignalTarget( this );
m_pInfoTarget->LoadControlSettings( "resource/infotargetpropertiessubpanel_target.res" );
m_pInfoTargetScroll = new CScrollableEditablePanel( this, m_pInfoTarget, "InfoTargetScroll" );
LoadControlSettings( "resource/infotargetpropertiespanel.res" );
m_pInfoTargetScroll->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Text to attribute...
//-----------------------------------------------------------------------------
void CInfoTargetPropertiesPanel::TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName )
{
int nLen = pEntry->GetTextLength();
char *pBuf = (char*)_alloca( nLen+1 );
pEntry->GetText( pBuf, nLen+1 );
m_hEntity->SetValue( pAttributeName, pBuf );
}
void CInfoTargetPropertiesPanel::TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName )
{
Vector vec;
for ( int i = 0; i < 3; ++i )
{
int nLen = pEntry[i]->GetTextLength();
char *pBuf = (char*)_alloca( nLen+1 );
pEntry[i]->GetText( pBuf, nLen+1 );
vec[i] = atof( pBuf );
}
m_hEntity->SetValue( pAttributeName, vec );
clienttools->MarkClientRenderableDirty( m_hEntity );
}
//-----------------------------------------------------------------------------
// Updates entity state when text fields change
//-----------------------------------------------------------------------------
void CInfoTargetPropertiesPanel::UpdateInfoTarget()
{
if ( !m_hEntity.Get() )
return;
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Info Target Change", "Info Target Change" );
TextEntryToAttribute( m_pTargetName, "targetname" );
TextEntriesToVector( m_pTargetPosition, "origin" );
TextEntriesToVector( m_pTargetOrientation, "angles" );
m_hEntity->MarkDirty();
}
//-----------------------------------------------------------------------------
// Populates the info_target fields
//-----------------------------------------------------------------------------
void CInfoTargetPropertiesPanel::PopulateInfoTargetFields()
{
if ( !m_hEntity.Get() )
return;
m_pTargetName->SetText( m_hEntity->GetTargetName() );
Vector vecPosition = m_hEntity->GetRenderOrigin();
QAngle vecAngles = m_hEntity->GetRenderAngles();
for ( int i = 0; i < 3; ++i )
{
char pTemp[512];
Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecPosition[i] );
m_pTargetPosition[i]->SetText( pTemp );
Q_snprintf( pTemp, sizeof(pTemp), "%.2f", vecAngles[i] );
m_pTargetOrientation[i]->SetText( pTemp );
}
}
//-----------------------------------------------------------------------------
// Sets the object to look at
//-----------------------------------------------------------------------------
void CInfoTargetPropertiesPanel::SetObject( CDmeVMFEntity *pEntity )
{
m_hEntity = pEntity;
m_pInfoTargetScroll->SetVisible( false );
if ( pEntity )
{
if ( !Q_stricmp( pEntity->GetClassName(), "info_target" ) )
{
PopulateInfoTargetFields();
m_pInfoTargetScroll->SetVisible( true );
m_pTargetName->RequestFocus();
return;
}
}
}
//-----------------------------------------------------------------------------
// Called when text is changed
//-----------------------------------------------------------------------------
void CInfoTargetPropertiesPanel::OnTextChanged( KeyValues *pParams )
{
vgui::Panel *pPanel = (vgui::Panel*)pParams->GetPtr( "panel" );
if ( pPanel->GetParent() == m_pInfoTarget )
{
UpdateInfoTarget();
return;
}
}

View File

@@ -0,0 +1,76 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#ifndef INFOTARGETPROPERTIESPANEL_H
#define INFOTARGETPROPERTIESPANEL_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_controls/editablepanel.h"
#include "tier1/utlstring.h"
#include "datamodel/dmehandle.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CVcdBlockDoc;
class CDmeVMFEntity;
class CScrollableEditablePanel;
namespace vgui
{
class ComboBox;
class Button;
class TextEntry;
class ListPanel;
class CheckButton;
class RadioButton;
}
//-----------------------------------------------------------------------------
// Panel that shows all entities in the level
//-----------------------------------------------------------------------------
class CInfoTargetPropertiesPanel : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CInfoTargetPropertiesPanel, vgui::EditablePanel );
public:
CInfoTargetPropertiesPanel( CVcdBlockDoc *pDoc, vgui::Panel* pParent ); // standard constructor
// Sets the object to look at
void SetObject( CDmeVMFEntity *pEntity );
private:
// Populates the info_target fields
void PopulateInfoTargetFields();
// Text to attribute...
void TextEntryToAttribute( vgui::TextEntry *pEntry, const char *pAttributeName );
void TextEntriesToVector( vgui::TextEntry *pEntry[3], const char *pAttributeName );
// Updates entity state when text fields change
void UpdateInfoTarget();
// Messages handled
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv );
CVcdBlockDoc *m_pDoc;
vgui::EditablePanel *m_pInfoTargetScroll;
vgui::EditablePanel *m_pInfoTarget;
vgui::TextEntry *m_pTargetName;
vgui::TextEntry *m_pTargetPosition[3];
vgui::TextEntry *m_pTargetOrientation[3];
CDmeHandle< CDmeVMFEntity > m_hEntity;
};
#endif // INFOTARGETPROPERTIESPANEL_H

View File

@@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// VCDBLOCK.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin\tools"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,.\,..\common;$SRCDIR\game\shared"
$PreprocessorDefinitions "$BASE;VCDBLOCK_EXPORTS"
}
$Linker
{
$AdditionalDependencies "$BASE Psapi.lib"
}
}
$Project "Vcdblock"
{
$Folder "Source Files"
{
$File "dmevmfentity.cpp"
$File "infotargetbrowserpanel.cpp"
$File "infotargetpropertiespanel.cpp"
$File "$SRCDIR\public\interpolatortypes.cpp"
$File "$SRCDIR\public\registry.cpp"
$File "vcdblockdoc.cpp"
$File "vcdblocktool.cpp"
$File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
}
$Folder "Header Files"
{
$File "dmevmfentity.h"
$File "infotargetbrowserpanel.h"
$File "infotargetpropertiespanel.h"
$File "$SRCDIR\public\mathlib\mathlib.h"
$File "vcdblockdoc.h"
$File "vcdblocktool.h"
}
$Folder "Link Libraries"
{
$Lib datamodel
$Lib dme_controls
$Lib dmserializers
$Lib mathlib
$Lib matsys_controls
$Lib movieobjects
$Lib sfmobjects
$Lib tier2
$Lib tier3
$Lib toolutils
$Lib vgui_controls
}
}

View File

@@ -0,0 +1,630 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "vcdblockdoc.h"
#include "tier1/KeyValues.h"
#include "tier1/utlbuffer.h"
#include "toolutils/enginetools_int.h"
#include "filesystem.h"
#include "vcdblocktool.h"
#include "toolframework/ienginetool.h"
#include "dmevmfentity.h"
#include "datamodel/idatamodel.h"
#include "toolutils/attributeelementchoicelist.h"
#include "infotargetbrowserpanel.h"
#include "vgui_controls/messagebox.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CVcdBlockDoc::CVcdBlockDoc( IVcdBlockDocCallback *pCallback ) : m_pCallback( pCallback )
{
m_hVMFRoot = NULL;
m_hEditRoot = NULL;
m_pBSPFileName[0] = 0;
m_pVMFFileName[0] = 0;
m_pEditFileName[0] = 0;
m_bDirty = false;
g_pDataModel->InstallNotificationCallback( this );
}
CVcdBlockDoc::~CVcdBlockDoc()
{
g_pDataModel->RemoveNotificationCallback( this );
}
//-----------------------------------------------------------------------------
// Inherited from INotifyUI
//-----------------------------------------------------------------------------
void CVcdBlockDoc::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
{
OnDataChanged( pReason, nNotifySource, nNotifyFlags );
}
//-----------------------------------------------------------------------------
// Gets the file name
//-----------------------------------------------------------------------------
const char *CVcdBlockDoc::GetBSPFileName()
{
return m_pBSPFileName;
}
const char *CVcdBlockDoc::GetVMFFileName()
{
return m_pVMFFileName;
}
void CVcdBlockDoc::SetVMFFileName( const char *pFileName )
{
Q_strncpy( m_pVMFFileName, pFileName, sizeof( m_pVMFFileName ) );
Q_FixSlashes( m_pVMFFileName );
SetDirty( true );
}
const char *CVcdBlockDoc::GetEditFileName()
{
return m_pEditFileName;
}
void CVcdBlockDoc::SetEditFileName( const char *pFileName )
{
Q_strncpy( m_pEditFileName, pFileName, sizeof( m_pEditFileName ) );
Q_FixSlashes( m_pEditFileName );
SetDirty( true );
}
//-----------------------------------------------------------------------------
// Dirty bits
//-----------------------------------------------------------------------------
void CVcdBlockDoc::SetDirty( bool bDirty )
{
m_bDirty = bDirty;
}
bool CVcdBlockDoc::IsDirty() const
{
return m_bDirty;
}
//-----------------------------------------------------------------------------
// Saves/loads from file
//-----------------------------------------------------------------------------
bool CVcdBlockDoc::LoadFromFile( const char *pFileName )
{
Assert( !m_hVMFRoot.Get() );
Assert( !m_hEditRoot.Get() );
CAppDisableUndoScopeGuard guard( "CVcdBlockDoc::LoadFromFile", NOTIFY_CHANGE_OTHER );
SetDirty( false );
if ( !pFileName[0] )
return false;
// Construct VMF file name from the BSP
const char *pGame = Q_stristr( pFileName, "\\game\\" );
if ( !pGame )
{
pGame = Q_stristr( pFileName, "\\content\\" );
if ( !pGame )
return false;
}
// Compute the map name
const char *pMaps = Q_stristr( pFileName, "\\maps\\" );
if ( !pMaps )
return false;
// Build map name
char mapname[ 256 ];
Q_StripExtension( pFileName, mapname, sizeof(mapname) );
char *pszFileName = (char*)Q_UnqualifiedFileName(mapname);
int nLen = (int)( (size_t)pGame - (size_t)pFileName ) + 1;
Q_strncpy( m_pVMFFileName, pFileName, nLen );
Q_strncat( m_pVMFFileName, "\\content\\", sizeof(m_pVMFFileName) );
Q_strncat( m_pVMFFileName, pGame + 6, sizeof(m_pVMFFileName) );
Q_SetExtension( m_pVMFFileName, ".vmf", sizeof(m_pVMFFileName) );
// Make sure new entities start with ids at 0
CDmeVMFEntity::SetNextEntityId( 0 );
// Build the Edit file name
Q_StripExtension( m_pVMFFileName, m_pEditFileName, sizeof(m_pEditFileName) );
Q_strncat( m_pEditFileName, ".vle", sizeof( m_pEditFileName ) );
// Store the BSP file name
Q_strncpy( m_pBSPFileName, pFileName, sizeof( m_pBSPFileName ) );
// Set the txt file name.
// If we loaded a .bsp, clear out what we're doing
// load the Edits file into memory, assign it as our "root"
CDmElement *pEdit = NULL;
if ( !V_stricmp( Q_GetFileExtension( pFileName ), "vle" ) )
{
if ( g_pDataModel->RestoreFromFile( m_pEditFileName, NULL, "vmf", &pEdit ) != DMFILEID_INVALID )
{
// If we successfully read the file in, ask it for the max hammer id
//int nMaxHammerId = pVMF->GetAttributeValue<int>( "maxHammerId" );
//CDmeVMFEntity::SetNextEntityId( nMaxHammerId + 1 );
m_hEditRoot = pEdit;
SetDirty( false );
}
}
if (pEdit == NULL)
{
if ( g_pFileSystem->FileExists( m_pEditFileName ) )
{
char pBuf[1024];
Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\n", m_pEditFileName );
m_pEditFileName[0] = 0;
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Unable to overwrite file!\n", pBuf, g_pVcdBlockTool );
pMessageBox->DoModal( );
return false;
}
DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( m_pEditFileName );
m_hEditRoot = CreateElement<CDmElement>( "root", fileid );
m_hEditRoot->AddAttribute( "entities", AT_ELEMENT_ARRAY );
g_pDataModel->SetFileRoot( fileid, m_hEditRoot );
SetDirty( true );
}
guard.Release();
// tell the engine to actually load the map
char cmd[ 256 ];
Q_snprintf( cmd, sizeof( cmd ), "disconnect; map %s\n", pszFileName );
enginetools->Command( cmd );
enginetools->Execute( );
return true;
}
void CVcdBlockDoc::SaveToFile( )
{
if ( m_hEditRoot.Get() && m_pEditFileName && m_pEditFileName[0] )
{
g_pDataModel->SaveToFile( m_pEditFileName, NULL, "keyvalues", "vmf", m_hEditRoot );
}
SetDirty( false );
}
//-----------------------------------------------------------------------------
// Returns the root object
//-----------------------------------------------------------------------------
CDmElement *CVcdBlockDoc::GetRootObject()
{
return m_hEditRoot;
}
//-----------------------------------------------------------------------------
// Returns the entity list
//-----------------------------------------------------------------------------
CDmAttribute *CVcdBlockDoc::GetEntityList()
{
return m_hEditRoot ? m_hEditRoot->GetAttribute( "entities", AT_ELEMENT_ARRAY ) : NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CVcdBlockDoc::AddNewInfoTarget( const Vector &vecOrigin, const QAngle &angAngles )
{
CDmrElementArray<> entities = GetEntityList();
CDmeVMFEntity *pTarget;
{
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Add Info Target", "Add Info Target" );
pTarget = CreateElement<CDmeVMFEntity>( "", entities.GetOwner()->GetFileId() );
pTarget->SetValue( "classname", "info_target" );
pTarget->SetRenderOrigin( vecOrigin );
pTarget->SetRenderAngles( angAngles );
entities.AddToTail( pTarget );
pTarget->MarkDirty();
pTarget->DrawInEngine( true );
}
g_pVcdBlockTool->GetInfoTargetBrowser()->SelectNode( pTarget );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CVcdBlockDoc::AddNewInfoTarget( void )
{
Vector vecOrigin;
QAngle angAngles;
float flFov;
clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov );
AddNewInfoTarget( vecOrigin, vec3_angle );
}
//-----------------------------------------------------------------------------
// Deletes a commentary node
//-----------------------------------------------------------------------------
void CVcdBlockDoc::DeleteInfoTarget( CDmeVMFEntity *pNode )
{
CDmrElementArray<CDmElement> entities = GetEntityList();
int nCount = entities.Count();
for ( int i = 0; i < nCount; ++i )
{
if ( pNode == entities[i] )
{
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Info Target", "Delete Info Target" );
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] );
pNode->DrawInEngine( false );
entities.FastRemove( i );
return;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &vecOrigin -
// &angAbsAngles -
// Output : CDmeVMFEntity
//-----------------------------------------------------------------------------
CDmeVMFEntity *CVcdBlockDoc::GetInfoTargetForLocation( Vector &vecOrigin, QAngle &angAbsAngles )
{
const CDmrElementArray<> entities = GetEntityList();
int nCount = entities.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] );
Vector &vecAngles = *(Vector*)(&pNode->GetRenderAngles());
if ( pNode->GetRenderOrigin().DistTo( vecOrigin ) < 1e-3 && vecAngles.DistTo( *(Vector*)&angAbsAngles ) < 1e-1 )
return pNode;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &vecStart -
// &vecEnd -
// Output : CDmeVMFEntity
//-----------------------------------------------------------------------------
CDmeVMFEntity *CVcdBlockDoc::GetInfoTargetForLocation( Vector &vecStart, Vector &vecEnd )
{
Vector vecDelta;
float flEndDist;
vecDelta = vecEnd - vecStart;
flEndDist = VectorNormalize( vecDelta );
CDmeVMFEntity *pSelectedNode = NULL;
float flMinDistFromLine = 1E30;
const CDmrElementArray<CDmElement> entities = GetEntityList();
int nCount = entities.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] );
float flDistAway = DotProduct( pNode->GetRenderOrigin() - vecStart, vecDelta );
if (flDistAway > 0.0 && flDistAway < flEndDist)
{
float flDistFromLine = (pNode->GetRenderOrigin() - vecStart - vecDelta * flDistAway).Length();
if (flDistFromLine < flMinDistFromLine)
{
pSelectedNode = pNode;
flMinDistFromLine = flDistFromLine;
}
}
}
return pSelectedNode;
}
//-----------------------------------------------------------------------------
// Populate string choice lists
//-----------------------------------------------------------------------------
bool CVcdBlockDoc::GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement,
const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list )
{
if ( !Q_stricmp( pChoiceListType, "info_targets" ) )
{
const CDmrElementArray<> entities = GetEntityList();
StringChoice_t sChoice;
sChoice.m_pValue = "";
sChoice.m_pChoiceString = "";
list.AddToTail( sChoice );
int nCount = entities.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] );
if ( !V_stricmp( pNode->GetClassName(), "info_target" ) )
{
StringChoice_t sChoice;
sChoice.m_pValue = pNode->GetTargetName();
sChoice.m_pChoiceString = pNode->GetTargetName();
list.AddToTail( sChoice );
}
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Populate element choice lists
//-----------------------------------------------------------------------------
bool CVcdBlockDoc::GetElementChoiceList( const char *pChoiceListType, CDmElement *pElement,
const char *pAttributeName, bool bArrayElement, ElementChoiceList_t &list )
{
if ( !Q_stricmp( pChoiceListType, "allelements" ) )
{
AddElementsRecursively( m_hEditRoot, list );
return true;
}
if ( !Q_stricmp( pChoiceListType, "info_targets" ) )
{
const CDmrElementArray<> entities = GetEntityList();
bool bFound = false;
int nCount = entities.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] );
if ( !V_stricmp( pNode->GetClassName(), "info_target" ) )
{
bFound = true;
ElementChoice_t sChoice;
sChoice.m_pValue = pNode;
sChoice.m_pChoiceString = pNode->GetTargetName();
list.AddToTail( sChoice );
}
}
return bFound;
}
// by default, try to treat the choice list type as a Dme element type
AddElementsRecursively( m_hEditRoot, list, pChoiceListType );
return list.Count() > 0;
}
//-----------------------------------------------------------------------------
// Called when data changes
//-----------------------------------------------------------------------------
void CVcdBlockDoc::OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags )
{
SetDirty( nNotifyFlags & NOTIFY_SETDIRTYFLAG ? true : false );
m_pCallback->OnDocChanged( pReason, nNotifySource, nNotifyFlags );
}
//-----------------------------------------------------------------------------
// List of all entity classnames to copy over from the original block
//-----------------------------------------------------------------------------
static const char *s_pUseOriginalClasses[] =
{
"worldspawn",
"func_occluder",
NULL
};
//-----------------------------------------------------------------------------
// The server just loaded, populate the list with the entities is has
//-----------------------------------------------------------------------------
void CVcdBlockDoc::ServerLevelInitPostEntity( void )
{
CDmrElementArray<> entityList = GetEntityList();
if ( entityList.Count() )
{
VerifyAllEdits( entityList );
}
else
{
InitializeFromServer( entityList );
}
}
//-----------------------------------------------------------------------------
// Create a list of entities based on what the server has
//-----------------------------------------------------------------------------
void CVcdBlockDoc::InitializeFromServer( CDmrElementArray<> &entityList )
{
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Initialize From Server" );
entityList.RemoveAll();
// initialize list with entities on the server
CBaseEntity *pServerEnt = servertools->FirstEntity();
while (pServerEnt)
{
char classname[256];
if (servertools->GetKeyValue( pServerEnt, "classname", classname, sizeof( classname ) ) )
{
if ( !Q_stricmp( classname, "info_target" ))
{
char hammerid[256];
if ( servertools->GetKeyValue( pServerEnt, "hammerid", hammerid, sizeof( hammerid ) ) )
{
int nextId = CDmeVMFEntity::GetNextEntityId();
CDmeVMFEntity::SetNextEntityId( atoi( hammerid ) );
CDmeVMFEntity *pTarget = CreateElement<CDmeVMFEntity>( "", entityList.GetOwner()->GetFileId() );
CDmeVMFEntity::SetNextEntityId( nextId );
if ( pTarget->CopyFromServer( pServerEnt ) )
{
entityList.AddToTail( pTarget );
}
}
}
}
pServerEnt = servertools->NextEntity( pServerEnt );
}
}
//-----------------------------------------------------------------------------
// Check the list of entities on the server against the edits that are already made
//-----------------------------------------------------------------------------
void CVcdBlockDoc::VerifyAllEdits( const CDmrElementArray<> &entityList )
{
// already filled in
for (int i = 0; i < entityList.Count(); i++)
{
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[i] );
CBaseEntity *pServerEntity = servertools->FindEntityByHammerID( pEntity->GetEntityId() );
if (pServerEntity != NULL)
{
if (!pEntity->IsSameOnServer( pServerEntity ))
{
pEntity->MarkDirty();
}
else
{
pEntity->MarkDirty(false);
}
}
else
{
pEntity->CreateOnServer();
pEntity->MarkDirty();
}
}
}
//-----------------------------------------------------------------------------
// Load the VMF file, merge in all the edits, write it back out
//-----------------------------------------------------------------------------
bool CVcdBlockDoc::CopyEditsToVMF( )
{
const CDmrElementArray<CDmElement> entityList = GetEntityList();
CDmElement *pVMF = NULL;
DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( m_pVMFFileName );
if ( g_pDataModel->RestoreFromFile( m_pVMFFileName, NULL, "vmf", &pVMF ) == DMFILEID_INVALID )
{
// needs some kind of error message
return false;
}
CDmrElementArray<CDmElement> vmfEntities( pVMF, "entities" );
int nVMFCount = vmfEntities.Count();
for (int i = 0; i < nVMFCount; i++)
{
CDmElement *pVMFEntity = vmfEntities[i];
char classname[256];
pVMFEntity->GetValueAsString( "classname", classname, sizeof( classname ) );
if ( Q_stricmp( "info_target", classname ) )
continue;
int nHammerID = atoi( pVMFEntity->GetName() );
// find a match.
int nCount = entityList.Count();
for (int j = 0; j < nCount; j++)
{
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[j] );
if ( pEntity->IsDirty() && pEntity->GetEntityId() == nHammerID)
{
char text[256];
pEntity->GetValueAsString( "targetname", text, sizeof( text ) );
pVMFEntity->SetValueFromString( "targetname", text );
pEntity->GetValueAsString( "origin", text, sizeof( text ) );
pVMFEntity->SetValueFromString( "origin", text );
pEntity->GetValueAsString( "angles", text, sizeof( text ) );
pVMFEntity->SetValueFromString( "angles", text );
pEntity->MarkDirty(false);
}
}
}
// add the new entities
int nCount = entityList.Count();
for (int j = 0; j < nCount; j++)
{
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[j] );
if ( pEntity->IsDirty())
{
CDmElement *pVMFEntity = CreateElement<CDmElement>( pEntity->GetName(), fileid );
char text[256];
pEntity->GetValueAsString( "classname", text, sizeof( text ) );
pVMFEntity->SetValue( "classname", text );
pEntity->GetValueAsString( "targetname", text, sizeof( text ) );
pVMFEntity->SetValue( "targetname", text );
pEntity->GetValueAsString( "origin", text, sizeof( text ) );
pVMFEntity->SetValue( "origin", text );
pEntity->GetValueAsString( "angles", text, sizeof( text ) );
pVMFEntity->SetValue( "angles", text );
vmfEntities.AddToTail( pVMFEntity );
pEntity->MarkDirty(false);
}
}
// currently, don't overwrite the vmf, not sure if this is serializing correctly yet
char tmpname[ 256 ];
Q_StripExtension( m_pVMFFileName, tmpname, sizeof(tmpname) );
Q_SetExtension( tmpname, ".vme", sizeof(tmpname) );
if (!g_pDataModel->SaveToFile( tmpname, NULL, "keyvalues", "vmf", pVMF ))
{
// needs some kind of error message
return false;
}
/*
// If we successfully read the file in, ask it for the max hammer id
int nMaxHammerId = pVMF->GetAttributeValue<int>( "maxHammerId" );
CDmeVMFEntity::SetNextEntityId( nMaxHammerId + 1 );
m_hVMFRoot = pVMF;
*/
return true;
}
bool CVcdBlockDoc::RememberPlayerPosition()
{
return true;
}

View File

@@ -0,0 +1,108 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef VCDBLOCKDOC_H
#define VCDBLOCKDOC_H
#ifdef _WIN32
#pragma once
#endif
#include "dme_controls/inotifyui.h"
#include "datamodel/dmehandle.h"
#include "datamodel/dmelement.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IVcdBlockDocCallback;
class CVcdBlockDoc;
class CDmeVMFEntity;
//-----------------------------------------------------------------------------
// Contains all editable state
//-----------------------------------------------------------------------------
class CVcdBlockDoc : public IDmNotify
{
public:
CVcdBlockDoc( IVcdBlockDocCallback *pCallback );
~CVcdBlockDoc();
// Inherited from INotifyUI
virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
// Sets/Gets the file name
const char *GetBSPFileName();
const char *GetVMFFileName();
const char *GetEditFileName();
void SetVMFFileName( const char *pFileName );
void SetEditFileName( const char *pFileName );
// Dirty bits (has it changed since the last time it was saved?)
void SetDirty( bool bDirty );
bool IsDirty() const;
// Saves/loads from file
bool LoadFromFile( const char *pFileName );
void SaveToFile( );
// Returns the root object
CDmElement *GetRootObject();
// Called when data changes (see INotifyUI for flags)
void OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
// Create a text block the engine can parse containing the entity data to spawn
void ServerLevelInitPostEntity( void );
// Returns the entity list
CDmAttribute *GetEntityList();
// Adds a new info_target
void AddNewInfoTarget( void );
void AddNewInfoTarget( const Vector &vecOrigin, const QAngle &angAngles );
// Deletes a commentary node
void DeleteInfoTarget( CDmeVMFEntity *pNode );
// Returns the commentary node at the specified location
CDmeVMFEntity *GetInfoTargetForLocation( Vector &vecOrigin, QAngle &angAbsAngles );
// Returns the info target that's closest to this line
CDmeVMFEntity *GetInfoTargetForLocation( Vector &vecStart, Vector &vecEnd );
// For element choice lists. Return false if it's an unknown choice list type
virtual bool GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement,
const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list );
virtual bool GetElementChoiceList( const char *pChoiceListType, CDmElement *pElement,
const char *pAttributeName, bool bArrayElement, ElementChoiceList_t &list );
void VerifyAllEdits( const CDmrElementArray<> &entityList );
void InitializeFromServer( CDmrElementArray<> &entityList );
bool CopyEditsToVMF( void );
bool RememberPlayerPosition( void );
private:
IVcdBlockDocCallback *m_pCallback;
CDmeHandle< CDmElement > m_hVMFRoot; // VMF file
CDmeHandle< CDmElement > m_hEditRoot; // VMF Edits file
char m_pBSPFileName[512];
char m_pVMFFileName[512];
char m_pEditFileName[512];
bool m_bDirty;
};
#endif // VCDBLOCKDOC_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: VcdBlock tool; main UI smarts class
//
//=============================================================================
#ifndef VCDBLOCKTOOL_H
#define VCDBLOCKTOOL_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "toolutils/basetoolsystem.h"
#include "toolutils/recentfilelist.h"
#include "toolutils/toolmenubar.h"
#include "toolutils/toolswitchmenubutton.h"
#include "toolutils/tooleditmenubutton.h"
#include "toolutils/toolfilemenubutton.h"
#include "toolutils/toolmenubutton.h"
#include "datamodel/dmelement.h"
#include "dmevmfentity.h"
#include "toolframework/ienginetool.h"
#include "toolutils/enginetools_int.h"
#include "toolutils/savewindowpositions.h"
#include "toolutils/toolwindowfactory.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CDmElement;
class CVcdBlockDoc;
class CInfoTargetPropertiesPanel;
class CInfoTargetBrowserPanel;
namespace vgui
{
class Panel;
}
//-----------------------------------------------------------------------------
// Allows the doc to call back into the VcdBlock editor tool
//-----------------------------------------------------------------------------
abstract_class IVcdBlockDocCallback
{
public:
// Called by the doc when the data changes
virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0;
};
//-----------------------------------------------------------------------------
// Global methods of the VCD Blocking tool
//-----------------------------------------------------------------------------
abstract_class IVcdBlockTool
{
public:
// Gets at the rool panel (for modal dialogs)
virtual vgui::Panel *GetRootPanel() = 0;
// Gets the registry name (for saving settings)
virtual const char *GetRegistryName() = 0;
// Shows a particular entity in the entity properties dialog
virtual void ShowEntityInEntityProperties( CDmeVMFEntity *pEntity ) = 0;
};
//-----------------------------------------------------------------------------
// Implementation of the VcdBlock tool
//-----------------------------------------------------------------------------
class CVcdBlockTool : public CBaseToolSystem, public IFileMenuCallbacks, public IVcdBlockDocCallback, public IVcdBlockTool
{
DECLARE_CLASS_SIMPLE( CVcdBlockTool, CBaseToolSystem );
public:
CVcdBlockTool();
// Inherited from IToolSystem
virtual const char *GetToolName() { return "VCD Blocking Tool"; }
virtual bool Init( );
virtual void Shutdown();
virtual bool CanQuit();
virtual void OnToolActivate();
virtual void OnToolDeactivate();
virtual void ServerLevelInitPostEntity();
virtual void DrawEntitiesInEngine( bool bDrawInEngine );
virtual void ClientLevelInitPostEntity();
virtual void ClientLevelShutdownPreEntity();
virtual bool TrapKey( ButtonCode_t key, bool down );
virtual void ClientPreRender();
// Inherited from IFileMenuCallbacks
virtual int GetFileMenuItemsEnabled( );
virtual void AddRecentFilesToMenu( vgui::Menu *menu );
virtual bool GetPerforceFileName( char *pFileName, int nMaxLen );
// Inherited from IVcdBlockDocCallback
virtual void OnDocChanged( const char *pReason, int nNotifySource, int nNotifyFlags );
virtual vgui::Panel *GetRootPanel() { return this; }
virtual void ShowEntityInEntityProperties( CDmeVMFEntity *pEntity );
// Inherited from CBaseToolSystem
virtual vgui::HScheme GetToolScheme();
virtual vgui::Menu *CreateActionMenu( vgui::Panel *pParent );
virtual void OnCommand( const char *cmd );
virtual const char *GetRegistryName() { return "VcdBlockTool"; }
virtual const char *GetBindingsContextFile() { return "cfg/VcdBlock.kb"; }
virtual vgui::MenuBar *CreateMenuBar( CBaseToolSystem *pParent );
MESSAGE_FUNC( Save, "OnSave" );
void SaveAndTest();
void RestartMap();
// Enter mode where we preview dropping nodes
void EnterTargetDropMode();
void LeaveTargetDropMode();
bool IsMiniViewportCursor( int x, int y, Vector &org, Vector &forward );
// Save/Load game state
void SetRememberPlayerPosition( bool state = true ) { m_bRememberPlayerPosition = state; };
bool GetRememberPlayerPosition( void ) { return m_bRememberPlayerPosition; };
void QuickLoad();
void QuickSave();
bool IsInNodeDrag( void ) { return m_bInNodeDragMode; };
public:
MESSAGE_FUNC( OnRestartLevel, "RestartLevel" );
MESSAGE_FUNC( OnNew, "OnNew" );
MESSAGE_FUNC( OnOpen, "OnOpen" );
MESSAGE_FUNC( OnSaveAs, "OnSaveAs" );
MESSAGE_FUNC( OnClose, "OnClose" );
MESSAGE_FUNC( OnCloseNoSave, "OnCloseNoSave" );
MESSAGE_FUNC( OnMarkNotDirty, "OnMarkNotDirty" );
MESSAGE_FUNC( OnExit, "OnExit" );
// Commands related to the edit menu
void OnDescribeUndo();
// Methods related to the VcdBlock menu
MESSAGE_FUNC( OnAddNewNodes, "AddNewNodes" );
MESSAGE_FUNC( OnCopyEditsToVMF, "CopyEditsToVMF" );
MESSAGE_FUNC( OnRememberPosition, "RememberPosition" );
// Methods related to the view menu
MESSAGE_FUNC( OnToggleProperties, "OnToggleProperties" );
MESSAGE_FUNC( OnToggleEntityReport, "OnToggleEntityReport" );
MESSAGE_FUNC( OnDefaultLayout, "OnDefaultLayout" );
// Keybindings
KEYBINDING_FUNC( undo, KEY_Z, vgui::MODIFIER_CONTROL, OnUndo, "#undo_help", 0 );
KEYBINDING_FUNC( redo, KEY_Z, vgui::MODIFIER_CONTROL | vgui::MODIFIER_SHIFT, OnRedo, "#redo_help", 0 );
KEYBINDING_FUNC_NODECLARE( VcdBlockAddNewNodes, KEY_A, vgui::MODIFIER_CONTROL, OnAddNewNodes, "#VcdBlockAddNewNodesHelp", 0 );
void OpenFileFromHistory( int slot );
void OpenSpecificFile( const char *pFileName );
virtual void SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues );
virtual bool OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues );
virtual bool OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues );
virtual void OnFileOperationCompleted( const char *pFileType, bool bWroteFile, vgui::FileOpenStateMachine::CompletionState_t state, KeyValues *pContextKeyValues );
void AttachAllEngineEntities();
// returns the document
CVcdBlockDoc *GetDocument();
// Gets at tool windows
CInfoTargetPropertiesPanel *GetProperties();
CInfoTargetBrowserPanel *GetInfoTargetBrowser();
CDmeHandle< CDmeVMFEntity > GetCurrentEntity( void ) { return m_hCurrentEntity; }
private:
// Loads up a new document
bool LoadDocument( const char *pDocName );
// Updates the menu bar based on the current file
void UpdateMenuBar( );
// Shows element properties
void ShowElementProperties( );
virtual const char *GetLogoTextureName();
// Creates, destroys tools
void CreateTools( CVcdBlockDoc *doc );
void DestroyTools();
// Initializes the tools
void InitTools();
// Shows, toggles tool windows
void ToggleToolWindow( Panel *tool, char const *toolName );
void ShowToolWindow( Panel *tool, char const *toolName, bool visible );
// Kills all tool windows
void DestroyToolContainers();
// Gets the position of the preview object
void GetPlacementInfo( Vector &vecOrigin, QAngle &angles );
private:
// Document
CVcdBlockDoc *m_pDoc;
// The menu bar
CToolFileMenuBar *m_pMenuBar;
// Element properties for editing material
vgui::DHANDLE< CInfoTargetPropertiesPanel > m_hProperties;
// The entity report
vgui::DHANDLE< CInfoTargetBrowserPanel > m_hInfoTargetBrowser;
// The currently viewed entity
CDmeHandle< CDmeVMFEntity > m_hCurrentEntity;
// Separate undo context for the act busy tool
bool m_bInNodeDropMode;
bool m_bInNodeDragMode;
int m_iDragX;
int m_iDragY;
CDmeHandle< CDmeVMFEntity > m_hPreviewTarget;
CToolWindowFactory< ToolWindow > m_ToolWindowFactory;
// remembered player position
bool m_bRememberPlayerPosition;
bool m_bHasPlayerPosition;
Vector m_vecPlayerOrigin;
QAngle m_vecPlayerAngles;
};
extern CVcdBlockTool *g_pVcdBlockTool;
#endif // VCDBLOCKTOOL_H