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.

423 lines
12 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: This is an entity that represents a vgui screen
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "vguiscreen.h"
  9. #include "networkstringtable_gamedll.h"
  10. #include "saverestore_stringtable.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. //-----------------------------------------------------------------------------
  14. // This is an entity that represents a vgui screen
  15. //-----------------------------------------------------------------------------
  16. IMPLEMENT_SERVERCLASS_ST(CVGuiScreen, DT_VGuiScreen)
  17. SendPropFloat(SENDINFO(m_flWidth), 0, SPROP_NOSCALE ),
  18. SendPropFloat(SENDINFO(m_flHeight), 0, SPROP_NOSCALE ),
  19. SendPropIntWithMinusOneFlag(SENDINFO(m_nAttachmentIndex), 6 ),
  20. SendPropInt(SENDINFO(m_nPanelName), MAX_VGUI_SCREEN_STRING_BITS, SPROP_UNSIGNED ),
  21. SendPropInt(SENDINFO(m_fScreenFlags), VGUI_SCREEN_MAX_BITS, SPROP_UNSIGNED ),
  22. SendPropInt(SENDINFO(m_nOverlayMaterial), MAX_MATERIAL_STRING_BITS, SPROP_UNSIGNED ),
  23. SendPropEHandle(SENDINFO(m_hPlayerOwner)),
  24. END_SEND_TABLE();
  25. LINK_ENTITY_TO_CLASS( vgui_screen, CVGuiScreen );
  26. LINK_ENTITY_TO_CLASS( vgui_screen_team, CVGuiScreen );
  27. PRECACHE_REGISTER( vgui_screen );
  28. //-----------------------------------------------------------------------------
  29. // Save/load
  30. //-----------------------------------------------------------------------------
  31. BEGIN_DATADESC( CVGuiScreen )
  32. DEFINE_CUSTOM_FIELD( m_nPanelName, &g_VguiScreenStringOps ),
  33. DEFINE_FIELD( m_nAttachmentIndex, FIELD_INTEGER ),
  34. // DEFINE_FIELD( m_nOverlayMaterial, FIELD_INTEGER ),
  35. DEFINE_FIELD( m_fScreenFlags, FIELD_INTEGER ),
  36. DEFINE_KEYFIELD( m_flWidth, FIELD_FLOAT, "width" ),
  37. DEFINE_KEYFIELD( m_flHeight, FIELD_FLOAT, "height" ),
  38. DEFINE_KEYFIELD( m_bIsTransparent, FIELD_BOOLEAN, "IsTransparent" ),
  39. DEFINE_KEYFIELD( m_strOverlayMaterial, FIELD_STRING, "overlaymaterial" ),
  40. DEFINE_FIELD( m_hPlayerOwner, FIELD_EHANDLE ),
  41. DEFINE_INPUTFUNC( FIELD_VOID, "SetActive", InputSetActive ),
  42. DEFINE_INPUTFUNC( FIELD_VOID, "SetInactive", InputSetInactive ),
  43. END_DATADESC()
  44. //-----------------------------------------------------------------------------
  45. // Constructor
  46. //-----------------------------------------------------------------------------
  47. CVGuiScreen::CVGuiScreen()
  48. {
  49. m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING;
  50. m_hPlayerOwner = INVALID_EHANDLE;
  51. m_bIsTransparent = true;
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Read in worldcraft data...
  55. //-----------------------------------------------------------------------------
  56. bool CVGuiScreen::KeyValue( const char *szKeyName, const char *szValue )
  57. {
  58. //!! temp hack, until worldcraft is fixed
  59. // strip the # tokens from (duplicate) key names
  60. char *s = (char *)strchr( szKeyName, '#' );
  61. if ( s )
  62. {
  63. *s = '\0';
  64. }
  65. if ( FStrEq( szKeyName, "panelname" ))
  66. {
  67. SetPanelName( szValue );
  68. return true;
  69. }
  70. // NOTE: Have to do these separate because they set two values instead of one
  71. if( FStrEq( szKeyName, "angles" ) )
  72. {
  73. Assert( GetMoveParent() == NULL );
  74. QAngle angles;
  75. UTIL_StringToVector( angles.Base(), szValue );
  76. // Because the vgui screen basis is strange (z is front, y is up, x is right)
  77. // we need to rotate the typical basis before applying it
  78. VMatrix mat, rotation, tmp;
  79. MatrixFromAngles( angles, mat );
  80. MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 );
  81. MatrixMultiply( mat, rotation, tmp );
  82. MatrixBuildRotateZ( rotation, 90 );
  83. MatrixMultiply( tmp, rotation, mat );
  84. MatrixToAngles( mat, angles );
  85. SetAbsAngles( angles );
  86. return true;
  87. }
  88. return BaseClass::KeyValue( szKeyName, szValue );
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Precache...
  92. //-----------------------------------------------------------------------------
  93. void CVGuiScreen::Precache()
  94. {
  95. BaseClass::Precache();
  96. if ( m_strOverlayMaterial != NULL_STRING )
  97. {
  98. PrecacheMaterial( STRING(m_strOverlayMaterial) );
  99. }
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Spawn...
  103. //-----------------------------------------------------------------------------
  104. void CVGuiScreen::Spawn()
  105. {
  106. Precache();
  107. // This has no model, but we want it to transmit if it's in the PVS anyways
  108. AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
  109. m_nAttachmentIndex = 0;
  110. SetSolid( SOLID_OBB );
  111. AddSolidFlags( FSOLID_NOT_SOLID );
  112. SetActualSize( m_flWidth, m_flHeight );
  113. m_fScreenFlags.Set( VGUI_SCREEN_ACTIVE );
  114. m_takedamage = DAMAGE_NO;
  115. AddFlag( FL_NOTARGET );
  116. SetTransparency( m_bIsTransparent );
  117. }
  118. //-----------------------------------------------------------------------------
  119. // Spawn...
  120. //-----------------------------------------------------------------------------
  121. void CVGuiScreen::Activate()
  122. {
  123. BaseClass::Activate();
  124. if ( m_nOverlayMaterial == OVERLAY_MATERIAL_INVALID_STRING && m_strOverlayMaterial != NULL_STRING )
  125. {
  126. SetOverlayMaterial( STRING(m_strOverlayMaterial) );
  127. }
  128. }
  129. void CVGuiScreen::OnRestore()
  130. {
  131. DispatchUpdateTransmitState();
  132. BaseClass::OnRestore();
  133. }
  134. void CVGuiScreen::SetAttachmentIndex( int nIndex )
  135. {
  136. m_nAttachmentIndex = nIndex;
  137. }
  138. void CVGuiScreen::SetOverlayMaterial( const char *pMaterial )
  139. {
  140. int iMaterial = GetMaterialIndex( pMaterial );
  141. if ( iMaterial == 0 )
  142. {
  143. m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING;
  144. }
  145. else
  146. {
  147. m_nOverlayMaterial = iMaterial;
  148. }
  149. }
  150. bool CVGuiScreen::IsActive() const
  151. {
  152. return (m_fScreenFlags & VGUI_SCREEN_ACTIVE) != 0;
  153. }
  154. void CVGuiScreen::SetActive( bool bActive )
  155. {
  156. if (bActive != IsActive())
  157. {
  158. if (!bActive)
  159. {
  160. m_fScreenFlags &= ~VGUI_SCREEN_ACTIVE;
  161. }
  162. else
  163. {
  164. m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ACTIVE );
  165. }
  166. }
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Purpose:
  170. // Output : Returns true on success, false on failure.
  171. //-----------------------------------------------------------------------------
  172. bool CVGuiScreen::IsAttachedToViewModel() const
  173. {
  174. return (m_fScreenFlags & VGUI_SCREEN_ATTACHED_TO_VIEWMODEL) != 0;
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Purpose:
  178. // Input : bAttached -
  179. //-----------------------------------------------------------------------------
  180. void CVGuiScreen::SetAttachedToViewModel( bool bAttached )
  181. {
  182. if (bAttached != IsActive())
  183. {
  184. if (!bAttached)
  185. {
  186. m_fScreenFlags &= ~VGUI_SCREEN_ATTACHED_TO_VIEWMODEL;
  187. }
  188. else
  189. {
  190. m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ATTACHED_TO_VIEWMODEL );
  191. // attached screens have different transmit rules
  192. DispatchUpdateTransmitState();
  193. }
  194. // attached screens have different transmit rules
  195. DispatchUpdateTransmitState();
  196. }
  197. }
  198. void CVGuiScreen::SetTransparency( bool bTransparent )
  199. {
  200. if (!bTransparent)
  201. {
  202. m_fScreenFlags &= ~VGUI_SCREEN_TRANSPARENT;
  203. }
  204. else
  205. {
  206. m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_TRANSPARENT );
  207. }
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Purpose:
  211. //-----------------------------------------------------------------------------
  212. void CVGuiScreen::InputSetActive( inputdata_t &inputdata )
  213. {
  214. SetActive( true );
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose:
  218. //-----------------------------------------------------------------------------
  219. void CVGuiScreen::InputSetInactive( inputdata_t &inputdata )
  220. {
  221. SetActive( false );
  222. }
  223. bool CVGuiScreen::IsVisibleOnlyToTeammates() const
  224. {
  225. return (m_fScreenFlags & VGUI_SCREEN_VISIBLE_TO_TEAMMATES) != 0;
  226. }
  227. void CVGuiScreen::MakeVisibleOnlyToTeammates( bool bActive )
  228. {
  229. if (bActive != IsVisibleOnlyToTeammates())
  230. {
  231. if (!bActive)
  232. {
  233. m_fScreenFlags &= ~VGUI_SCREEN_VISIBLE_TO_TEAMMATES;
  234. }
  235. else
  236. {
  237. m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_VISIBLE_TO_TEAMMATES );
  238. }
  239. }
  240. }
  241. bool CVGuiScreen::IsVisibleToTeam( int nTeam )
  242. {
  243. // FIXME: Should this maybe go into a derived class of some sort?
  244. // Don't bother with screens on the wrong team
  245. if ( IsVisibleOnlyToTeammates() && (nTeam > 0) )
  246. {
  247. // Hmmm... sort of a hack...
  248. CBaseEntity *pOwner = GetOwnerEntity();
  249. if ( pOwner && (nTeam != pOwner->GetTeamNumber()) )
  250. return false;
  251. }
  252. return true;
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose: Screens attached to view models only go to client if viewmodel is being sent, too.
  256. // Input : *recipient -
  257. // *pvs -
  258. // clientArea -
  259. // Output : Returns true on success, false on failure.
  260. //-----------------------------------------------------------------------------
  261. int CVGuiScreen::UpdateTransmitState()
  262. {
  263. if ( IsAttachedToViewModel() )
  264. {
  265. // only send to the owner, or someone spectating the owner.
  266. return SetTransmitState( FL_EDICT_FULLCHECK );
  267. }
  268. else if ( GetMoveParent() )
  269. {
  270. // Let the parent object trigger the send. This is more efficient than having it call CBaseEntity::ShouldTransmit
  271. // for all the vgui screens in the map.
  272. return SetTransmitState( FL_EDICT_PVSCHECK );
  273. }
  274. else
  275. {
  276. return BaseClass::UpdateTransmitState();
  277. }
  278. }
  279. int CVGuiScreen::ShouldTransmit( const CCheckTransmitInfo *pInfo )
  280. {
  281. Assert( IsAttachedToViewModel() );
  282. CBaseEntity *pViewModel = GetOwnerEntity();
  283. if ( pViewModel )
  284. {
  285. return pViewModel->ShouldTransmit( pInfo );
  286. }
  287. return BaseClass::ShouldTransmit( pInfo );
  288. }
  289. //-----------------------------------------------------------------------------
  290. // Convert the panel name into an integer
  291. //-----------------------------------------------------------------------------
  292. void CVGuiScreen::SetPanelName( const char *pPanelName )
  293. {
  294. m_nPanelName = g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pPanelName );
  295. }
  296. const char *CVGuiScreen::GetPanelName() const
  297. {
  298. return g_pStringTableVguiScreen->GetString( m_nPanelName );
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Sets the screen size + resolution
  302. //-----------------------------------------------------------------------------
  303. void CVGuiScreen::SetActualSize( float flWidth, float flHeight )
  304. {
  305. m_flWidth = flWidth;
  306. m_flHeight = flHeight;
  307. Vector mins, maxs;
  308. mins.Init( 0.0f, 0.0f, -0.1f );
  309. maxs.Init( 0.0f, 0.0f, 0.1f );
  310. if (flWidth > 0)
  311. maxs.x = flWidth;
  312. else
  313. mins.x = flWidth;
  314. if (flHeight > 0)
  315. maxs.y = flHeight;
  316. else
  317. mins.y = flHeight;
  318. UTIL_SetSize( this, mins, maxs );
  319. }
  320. //-----------------------------------------------------------------------------
  321. //
  322. //-----------------------------------------------------------------------------
  323. void CVGuiScreen::SetPlayerOwner( CBasePlayer *pPlayer, bool bOwnerOnlyInput /* = false */ )
  324. {
  325. m_hPlayerOwner = pPlayer;
  326. if ( bOwnerOnlyInput )
  327. {
  328. m_fScreenFlags.Set( VGUI_SCREEN_ONLY_USABLE_BY_OWNER );
  329. }
  330. }
  331. //-----------------------------------------------------------------------------
  332. // Precaches a vgui screen
  333. //-----------------------------------------------------------------------------
  334. void PrecacheVGuiScreen( const char *pScreenType )
  335. {
  336. g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pScreenType );
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Creates a vgui screen, attaches it to another player
  340. //-----------------------------------------------------------------------------
  341. CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex )
  342. {
  343. Assert( pAttachedTo );
  344. CVGuiScreen *pScreen = (CVGuiScreen *)CBaseEntity::Create( pScreenClassname, vec3_origin, vec3_angle, pAttachedTo );
  345. pScreen->SetPanelName( pScreenType );
  346. pScreen->FollowEntity( pAttachedTo );
  347. pScreen->SetOwnerEntity( pOwner );
  348. pScreen->SetAttachmentIndex( nAttachmentIndex );
  349. return pScreen;
  350. }
  351. void DestroyVGuiScreen( CVGuiScreen *pVGuiScreen )
  352. {
  353. if (pVGuiScreen)
  354. {
  355. UTIL_Remove( pVGuiScreen );
  356. }
  357. }