Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

436 lines
13 KiB

  1. //===== Copyright Valve Corporation, All rights reserved. ======//
  2. #include "stdafx.h"
  3. #include "hammer_mathlib.h"
  4. #include "Box3D.h"
  5. #include "BSPFile.h"
  6. #include "const.h"
  7. #include "MapDefs.h" // dvs: For COORD_NOTINIT
  8. #include "MapDoc.h"
  9. #include "MapEntity.h"
  10. #include "mapworldtext.h"
  11. #include "Render2D.h"
  12. #include "Render3D.h"
  13. #include "hammer.h"
  14. #include "Texture.h"
  15. #include "TextureSystem.h"
  16. #include "materialsystem/IMesh.h"
  17. #include "Material.h"
  18. #include "Options.h"
  19. #include "camera.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include <tier0/memdbgon.h>
  22. IMPLEMENT_MAPCLASS(CWorldTextHelper)
  23. //-----------------------------------------------------------------------------
  24. // Purpose: Factory function. Used for creating a CWorldTextHelper from a set
  25. // of string parameters from the FGD file.
  26. // Input : *pInfo - Pointer to helper info class which gives us information
  27. // about how to create the class.
  28. // Output : Returns a pointer to the class, NULL if an error occurs.
  29. //-----------------------------------------------------------------------------
  30. CMapClass *CWorldTextHelper::CreateWorldText( CHelperInfo *pHelperInfo, CMapEntity *pParent )
  31. {
  32. const char* pMsg = pParent->GetKeyValue( "message" );
  33. CWorldTextHelper *pWorldText = new CWorldTextHelper;
  34. pWorldText->SetText( pMsg );
  35. pWorldText->SetRenderMode( kRenderTransAlpha );
  36. return pWorldText;
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Purpose: Constructor.
  40. //-----------------------------------------------------------------------------
  41. CWorldTextHelper::CWorldTextHelper()
  42. : m_eRenderMode( kRenderTransAlpha ),
  43. m_flTextSize( 10.f ),
  44. m_pText( nullptr )
  45. {
  46. m_RenderColor.r = 255;
  47. m_RenderColor.g = 255;
  48. m_RenderColor.b = 255;
  49. m_RenderColor.a = 255;
  50. Initialize();
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Destructor.
  54. //-----------------------------------------------------------------------------
  55. CWorldTextHelper::~CWorldTextHelper( void )
  56. {
  57. if ( m_pText )
  58. {
  59. free( m_pText );
  60. }
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Sets the render mode
  64. //-----------------------------------------------------------------------------
  65. void CWorldTextHelper::SetRenderMode( int eRenderMode )
  66. {
  67. m_eRenderMode = eRenderMode;
  68. }
  69. void CWorldTextHelper::ComputeCornerVertices( Vector *pVerts, float flBloat ) const
  70. {
  71. Vector ViewForward( 1.0f, 0.0f, 0.0f );
  72. Vector ViewUp( 0.0f, 1.0f, 0.0f );
  73. Vector ViewRight( 0.0f, 0.0f, -1.0f );
  74. AngleVectors( m_Angles, &ViewForward, &ViewRight, &ViewUp );
  75. float flStrLength = V_strlen( m_pText );
  76. flStrLength = Max( flStrLength, 1.0f );
  77. pVerts[ 0 ] = m_Origin - flBloat * ( ViewRight + ViewUp );
  78. pVerts[ 1 ] = pVerts[ 0 ] + ( m_flTextSize * ( 1.0f + ( flStrLength - 1.0f ) * 0.6f ) + 2.0f * flBloat ) * ViewRight;
  79. pVerts[ 2 ] = pVerts[ 1 ] + ( m_flTextSize + 2.0f * flBloat )* ViewUp;
  80. pVerts[ 3 ] = pVerts[ 0 ] + ( m_flTextSize + 2.0f * flBloat )* ViewUp;
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Calculates our bounding box based on the sprite dimensions.
  84. // Input : bFullUpdate - Whether we should recalculate our childrens' bounds.
  85. //-----------------------------------------------------------------------------
  86. void CWorldTextHelper::CalcBounds( BOOL bFullUpdate )
  87. {
  88. CMapClass::CalcBounds(bFullUpdate);
  89. Vector cornerVerts[ 4 ];
  90. ComputeCornerVertices( cornerVerts );
  91. Vector vMin = VectorMin( VectorMin( cornerVerts[ 0 ], cornerVerts[ 1 ] ), VectorMin( cornerVerts[ 2 ], cornerVerts[ 3 ] ) );
  92. Vector vMax = VectorMax( VectorMax( cornerVerts[ 0 ], cornerVerts[ 1 ] ), VectorMax( cornerVerts[ 2 ], cornerVerts[ 3 ] ) );
  93. m_CullBox.UpdateBounds( vMin, vMax );
  94. m_Render2DBox.UpdateBounds( vMin, vMax );
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Returns a copy of this object.
  98. // Output : Pointer to the new object.
  99. //-----------------------------------------------------------------------------
  100. CMapClass *CWorldTextHelper::Copy( bool bUpdateDependencies )
  101. {
  102. CWorldTextHelper *pCopy = new CWorldTextHelper;
  103. if (pCopy != NULL)
  104. {
  105. pCopy->CopyFrom(this, bUpdateDependencies);
  106. }
  107. return pCopy;
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Purpose: Turns this into a duplicate of the given object.
  111. // Input : pObject - Pointer to the object to copy from.
  112. // Output : Returns a pointer to this object.
  113. //-----------------------------------------------------------------------------
  114. CMapClass *CWorldTextHelper::CopyFrom( CMapClass *pObject, bool bUpdateDependencies )
  115. {
  116. CWorldTextHelper *pFrom = dynamic_cast<CWorldTextHelper*>( pObject );
  117. Assert( pFrom != NULL );
  118. if ( pFrom != NULL )
  119. {
  120. CMapClass::CopyFrom(pObject, bUpdateDependencies);
  121. m_Angles = pFrom->m_Angles;
  122. SetText( pFrom->m_pText );
  123. SetRenderMode( pFrom->m_eRenderMode );
  124. m_RenderColor = pFrom->m_RenderColor;
  125. }
  126. return this;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose:
  130. // Input : Angles -
  131. //-----------------------------------------------------------------------------
  132. void CWorldTextHelper::GetAngles( QAngle &Angles )
  133. {
  134. Angles = m_Angles;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. //-----------------------------------------------------------------------------
  139. void CWorldTextHelper::Initialize( void )
  140. {
  141. SetText( "" );
  142. m_Angles.Init();
  143. //m_eRenderMode = kRenderNormal;
  144. m_RenderColor.r = 255;
  145. m_RenderColor.g = 255;
  146. m_RenderColor.b = 255;
  147. }
  148. #define CHAR_WIDTH 0.0625f // 1/16
  149. #define CHAR_HEIGHT 0.0625f // 1/16
  150. void CWorldTextHelper::Render3DText( CRender3D *pRender, const char* szText, const float flTextSize )
  151. {
  152. if ( !szText )
  153. return;
  154. int nNumChars = strlen( szText );
  155. if ( !nNumChars )
  156. return;
  157. Vector ViewForward( 1.0f, 0.0f, 0.0f );
  158. Vector ViewUp( 0.0f, 1.0f, 0.0f );
  159. Vector ViewRight( 0.0f, 0.0f, -1.0f );
  160. AngleVectors( m_Angles, &ViewForward, &ViewRight, &ViewUp );
  161. Vector vecStartPos;
  162. VectorCopy( m_Origin, vecStartPos );
  163. IMaterial* pDebugText = g_pMaterialSystem->FindMaterial( "editor/worldtext", TEXTURE_GROUP_OTHER, true );
  164. if ( !pDebugText )
  165. return;
  166. pRender->PushRenderMode( RENDER_MODE_EXTERN );
  167. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  168. pRenderContext->Bind( pDebugText );
  169. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  170. CMeshBuilder meshBuilder;
  171. float screenSize = flTextSize;
  172. meshBuilder.Begin( pMesh, MATERIAL_QUADS, nNumChars );
  173. for ( int i=0; i<nNumChars; i++ )
  174. {
  175. int nCharIdx = (int)((char)*szText) - 32;
  176. int nRow = nCharIdx / 16;
  177. int nCol = nCharIdx % 16;
  178. float flU = (nCol * CHAR_WIDTH);
  179. float flV = (nRow * CHAR_HEIGHT);
  180. flV += CHAR_HEIGHT;
  181. meshBuilder.Position3fv( vecStartPos.Base() );
  182. meshBuilder.TexCoord2f( 0, flU, flV );
  183. meshBuilder.Color4ub( m_RenderColor.r, m_RenderColor.g, m_RenderColor.b, 255 );
  184. meshBuilder.AdvanceVertex();
  185. vecStartPos += (ViewUp * screenSize);
  186. flV -= CHAR_HEIGHT;
  187. meshBuilder.Position3fv( vecStartPos.Base() );
  188. meshBuilder.TexCoord2f( 0, flU, flV );
  189. meshBuilder.Color4ub( m_RenderColor.r, m_RenderColor.g, m_RenderColor.b, 255 );
  190. meshBuilder.AdvanceVertex();
  191. vecStartPos += (ViewRight * screenSize);
  192. flU += CHAR_WIDTH;
  193. meshBuilder.Position3fv( vecStartPos.Base() );
  194. meshBuilder.TexCoord2f( 0, flU, flV );
  195. meshBuilder.Color4ub( m_RenderColor.r, m_RenderColor.g, m_RenderColor.b, 255 );
  196. meshBuilder.AdvanceVertex();
  197. vecStartPos -= (ViewUp * screenSize);
  198. flV += CHAR_HEIGHT;
  199. meshBuilder.Position3fv( vecStartPos.Base() );
  200. meshBuilder.TexCoord2f( 0, flU, flV );
  201. meshBuilder.Color4ub( m_RenderColor.r, m_RenderColor.g, m_RenderColor.b, 255 );
  202. meshBuilder.AdvanceVertex();
  203. vecStartPos -= (ViewRight * screenSize * 0.4f);
  204. szText++;
  205. }
  206. meshBuilder.End();
  207. pMesh->Draw();
  208. pRender->PopRenderMode();
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose:
  212. // Input : pRender -
  213. //-----------------------------------------------------------------------------
  214. void CWorldTextHelper::Render3D(CRender3D *pRender)
  215. {
  216. pRender->BeginRenderHitTarget( this );
  217. Render3DText( pRender, m_pText, m_flTextSize );
  218. pRender->EndRenderHitTarget();
  219. if ( GetSelectionState() != SELECT_NONE )
  220. {
  221. // Selection box
  222. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  223. Vector cornerVerts[ 4 ];
  224. ComputeCornerVertices( cornerVerts, 0.2f );
  225. pRender->SetDrawColor( 255, 255, 0 );
  226. pRender->DrawLine( cornerVerts[ 0 ], cornerVerts[ 1 ] );
  227. pRender->DrawLine( cornerVerts[ 1 ], cornerVerts[ 2 ] );
  228. pRender->DrawLine( cornerVerts[ 2 ], cornerVerts[ 3 ] );
  229. pRender->DrawLine( cornerVerts[ 3 ], cornerVerts[ 0 ] );
  230. pRender->PopRenderMode();
  231. }
  232. //pRender->PushRenderMode(RENDER_MODE_NONE);
  233. //pRender->BeginRenderHitTarget( this );
  234. //VMatrix matXform;
  235. //matXform.SetupMatrixOrgAngles( m_Origin, m_Angles );
  236. //pRender->BeginLocalTransfrom( matXform );
  237. //float flStrLength = V_strlen( m_pText );
  238. //pRender->RenderBox( Vector( -1.0f, 0.0f, 0.0f ), Vector( 1.0f, -m_flTextSize * ( 1.0f + ( flStrLength - 1.0f ) * 0.6f ), m_flTextSize ), 0, 255, 0, GetSelectionState() );
  239. //pRender->EndLocalTransfrom();
  240. //pRender->EndRenderHitTarget();
  241. //pRender->PopRenderMode();
  242. }
  243. //-----------------------------------------------------------------------------
  244. int CWorldTextHelper::SerializeRMF(std::fstream &File, BOOL bRMF)
  245. {
  246. return(0);
  247. }
  248. //-----------------------------------------------------------------------------
  249. int CWorldTextHelper::SerializeMAP(std::fstream &File, BOOL bRMF)
  250. {
  251. return(0);
  252. }
  253. //-----------------------------------------------------------------------------
  254. void CWorldTextHelper::DoTransform(const VMatrix &matrix)
  255. {
  256. BaseClass::DoTransform(matrix);
  257. matrix3x4_t fCurrentMatrix,fMatrixNew;
  258. AngleMatrix(m_Angles, fCurrentMatrix);
  259. ConcatTransforms(matrix.As3x4(), fCurrentMatrix, fMatrixNew);
  260. MatrixAngles(fMatrixNew, m_Angles);
  261. //
  262. // Update the angles of our parent entity.
  263. //
  264. CMapEntity *pEntity = dynamic_cast<CMapEntity*>( m_pParent );
  265. if ( pEntity )
  266. {
  267. char szValue[ 80 ];
  268. sprintf( szValue, "%g %g %g", m_Angles[ 0 ], m_Angles[ 1 ], m_Angles[ 2 ] );
  269. pEntity->NotifyChildKeyChanged( this, "angles", szValue );
  270. }
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Purpose: Notifies that this object's parent entity has had a key value change.
  274. // Input : szKey - The key that changed.
  275. // szValue - The new value of the key.
  276. //-----------------------------------------------------------------------------
  277. void CWorldTextHelper::OnParentKeyChanged(const char* szKey, const char* szValue)
  278. {
  279. if (!stricmp(szKey, "message"))
  280. {
  281. SetText( szValue );
  282. PostUpdate(Notify_Changed);
  283. }
  284. else if (!stricmp(szKey, "angles"))
  285. {
  286. sscanf(szValue, "%f %f %f", &m_Angles[PITCH], &m_Angles[YAW], &m_Angles[ROLL]);
  287. PostUpdate(Notify_Changed);
  288. }
  289. else if ( !stricmp( szKey, "textsize" ) )
  290. {
  291. sscanf( szValue, "%f", &m_flTextSize );
  292. PostUpdate( Notify_Changed );
  293. }
  294. else if ( !stricmp( szKey, "color" ) )
  295. {
  296. int r = 0, g = 0, b = 0;
  297. sscanf( szValue, "%d %d %d", &r, &g, &b );
  298. m_RenderColor.r = r;
  299. m_RenderColor.g = g;
  300. m_RenderColor.b = b;
  301. PostUpdate( Notify_Changed );
  302. }
  303. }
  304. //-----------------------------------------------------------------------------
  305. // Purpose:
  306. // Output : Returns true on success, false on failure.
  307. //-----------------------------------------------------------------------------
  308. bool CWorldTextHelper::ShouldRenderLast(void)
  309. {
  310. return false;
  311. }
  312. //-----------------------------------------------------------------------------
  313. void CWorldTextHelper::Render2D(CRender2D *pRender)
  314. {
  315. Vector vecMins;
  316. Vector vecMaxs;
  317. GetRender2DBox(vecMins, vecMaxs);
  318. Vector2D pt,pt2;
  319. pRender->TransformPoint(pt, vecMins);
  320. pRender->TransformPoint(pt2, vecMaxs);
  321. if ( !IsSelected() )
  322. {
  323. pRender->SetDrawColor( r, g, b );
  324. pRender->SetHandleColor( r, g, b );
  325. }
  326. else
  327. {
  328. pRender->SetDrawColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
  329. pRender->SetHandleColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
  330. }
  331. // Draw the bounding box.
  332. pRender->DrawBox( vecMins, vecMaxs );
  333. //
  334. // Draw center handle.
  335. //
  336. if ( pRender->IsActiveView() )
  337. {
  338. int sizex = abs(pt.x - pt2.x)+1;
  339. int sizey = abs(pt.y - pt2.y)+1;
  340. // dont draw handle if object is too small
  341. if ( sizex > 6 && sizey > 6 )
  342. {
  343. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CROSS );
  344. pRender->DrawHandle( (vecMins+vecMaxs)/2 );
  345. }
  346. }
  347. }
  348. void CWorldTextHelper::SetText( const char *pNewText )
  349. {
  350. if ( m_pText )
  351. {
  352. free( m_pText );
  353. }
  354. m_pText = strdup( pNewText ? pNewText : "" );
  355. }