Team Fortress 2 Source Code as on 22/4/2020
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.

198 lines
6.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Mirrors the movement of a camera about a given point.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "baseentity.h"
  8. #include "modelentities.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. //////////////////////////////////////////////////////////////////////////
  12. // CLogicMirrorMovement
  13. // This will record the vector offset of an entity's center from a given reference point
  14. // (most likely the center of a mirror or portal) and place an entity (most likely a point camera)
  15. // at a the same offset, mirrored about the reference point and orientation.
  16. //////////////////////////////////////////////////////////////////////////
  17. class CLogicMirrorMovement : public CLogicalEntity
  18. {
  19. DECLARE_DATADESC();
  20. DECLARE_CLASS( CLogicMirrorMovement, CLogicalEntity );
  21. private:
  22. void SetMirrorTarget( const char *pName ); // Set entity to watch and mirror (ex. the player)
  23. void SetTarget( const char *pName ); // Set entity to move based on the Mirror Target entity (ex. a point_camera)
  24. void SetMirrorRelative( const char* pName ); // Set the point about which to measure an offset to orient based upon (ex. portal 1)
  25. void SetRemoteTarget ( const char *pName ); // Entity's orientation/location from which to offset the movement target (ex. portal 2)
  26. void SetDrawingSurface ( const char *pName );
  27. void InputSetMirrorTarget( inputdata_t &inputdata );
  28. void InputSetTarget( inputdata_t &inputdata );
  29. void InputSetRemoteTarget ( inputdata_t &inputdata );
  30. void InputSetMirrorRelative ( inputdata_t &inputdata );
  31. void Think();
  32. virtual void Activate();
  33. string_t m_strMirrorTarget;
  34. string_t m_strRemoteTarget;
  35. string_t m_strMirrorRelative;
  36. EHANDLE m_hRemoteTarget;
  37. EHANDLE m_hMirrorTarget;
  38. EHANDLE m_hMovementTarget;
  39. EHANDLE m_hMirrorRelative;
  40. };
  41. LINK_ENTITY_TO_CLASS( logic_mirror_movement, CLogicMirrorMovement );
  42. BEGIN_DATADESC( CLogicMirrorMovement )
  43. DEFINE_KEYFIELD( m_strMirrorTarget, FIELD_STRING, "MirrorTarget" ),
  44. DEFINE_KEYFIELD( m_strRemoteTarget, FIELD_STRING, "RemoteTarget" ),
  45. DEFINE_KEYFIELD( m_strMirrorRelative, FIELD_STRING, "MirrorRelative" ),
  46. DEFINE_FIELD( m_hMirrorTarget, FIELD_EHANDLE ),
  47. DEFINE_FIELD( m_hMovementTarget, FIELD_EHANDLE ),
  48. DEFINE_FIELD( m_hRemoteTarget, FIELD_EHANDLE ),
  49. DEFINE_FIELD( m_hMirrorRelative, FIELD_EHANDLE ),
  50. DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorTarget", InputSetMirrorTarget ),
  51. DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ),
  52. DEFINE_INPUTFUNC( FIELD_STRING, "SetRemoteTarget", InputSetRemoteTarget ),
  53. DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorRelative", InputSetMirrorRelative ),
  54. DEFINE_THINKFUNC( Think ),
  55. END_DATADESC()
  56. void CLogicMirrorMovement::Activate()
  57. {
  58. BaseClass::Activate();
  59. SetMirrorTarget( STRING(m_strMirrorTarget) );
  60. SetTarget( STRING(m_target) );
  61. SetRemoteTarget( STRING(m_strRemoteTarget ) );
  62. SetMirrorRelative( STRING( m_strMirrorRelative) );
  63. SetThink( &CLogicMirrorMovement::Think );
  64. SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
  65. }
  66. void CLogicMirrorMovement::SetMirrorTarget( const char *pName )
  67. {
  68. m_hMirrorTarget = gEntList.FindEntityByName( NULL, pName );
  69. if ( !m_hMirrorTarget )
  70. {
  71. if ( Q_strnicmp( STRING(m_strMirrorTarget), "!player", 8 ) )
  72. {
  73. Warning("logic_mirror_movement: Unable to find mirror target entity %s\n", pName );
  74. }
  75. }
  76. }
  77. void CLogicMirrorMovement::SetTarget( const char *pName )
  78. {
  79. m_hMovementTarget = gEntList.FindEntityByName( NULL, pName );
  80. if ( !m_hMovementTarget )
  81. {
  82. Warning("logic_mirror_movement: Unable to find movement target entity %s\n", pName );
  83. }
  84. }
  85. void CLogicMirrorMovement::SetRemoteTarget(const char *pName )
  86. {
  87. m_hRemoteTarget = gEntList.FindEntityByName( NULL, pName );
  88. if ( !m_hRemoteTarget )
  89. {
  90. Warning("logic_mirror_movement: Unable to find remote target entity %s\n", pName );
  91. }
  92. }
  93. void CLogicMirrorMovement::SetMirrorRelative(const char* pName )
  94. {
  95. m_hMirrorRelative = gEntList.FindEntityByName( NULL, pName );
  96. if ( !m_hMirrorRelative )
  97. {
  98. Warning("logic_mirror_movement: Unable to find mirror relative entity %s\n", pName );
  99. }
  100. }
  101. void CLogicMirrorMovement::InputSetMirrorTarget( inputdata_t &inputdata )
  102. {
  103. m_strMirrorTarget = AllocPooledString( inputdata.value.String() );
  104. SetMirrorTarget( inputdata.value.String() );
  105. }
  106. void CLogicMirrorMovement::InputSetTarget( inputdata_t &inputdata )
  107. {
  108. m_target = AllocPooledString( inputdata.value.String() );
  109. SetTarget( inputdata.value.String() );
  110. }
  111. void CLogicMirrorMovement::InputSetRemoteTarget(inputdata_t &inputdata )
  112. {
  113. m_strRemoteTarget = AllocPooledString( inputdata.value.String() );
  114. SetRemoteTarget( inputdata.value.String() );
  115. }
  116. void CLogicMirrorMovement::InputSetMirrorRelative(inputdata_t &inputdata )
  117. {
  118. m_strMirrorRelative = AllocPooledString ( inputdata.value.String() );
  119. SetMirrorRelative( inputdata.value.String() );
  120. }
  121. void CLogicMirrorMovement::Think()
  122. {
  123. // Attempt to get the player's handle because it didn't exist at Activate time
  124. if ( !m_hMirrorTarget.Get() )
  125. {
  126. // If we will never find a target, we don't have a use... shutdown
  127. if ( m_strMirrorTarget == NULL_STRING )
  128. SetNextThink ( NULL );
  129. //BUGBUG: If m_strSetMirrorTarget doesn't exist in ent list, we get per-think searches with no results ever...
  130. SetMirrorTarget ( STRING(m_strMirrorTarget) );
  131. }
  132. // Make sure all entities are valid
  133. if ( m_hMirrorTarget.Get() && m_hMovementTarget.Get() && m_hRemoteTarget.Get() && m_hMirrorRelative.Get() )
  134. {
  135. // Get our two portal's world transforms transforms
  136. VMatrix matPortal1ToWorldInv, matPortal2ToWorld;
  137. MatrixInverseGeneral( m_hMirrorRelative->EntityToWorldTransform(), matPortal1ToWorldInv );
  138. matPortal2ToWorld = m_hRemoteTarget->EntityToWorldTransform();
  139. VMatrix matTransformToRemotePortal = matPortal1ToWorldInv * matPortal2ToWorld;
  140. // Get our scene camera's current orientation
  141. Vector ptCameraPosition, vCameraLook, vCameraRight, vCameraUp;
  142. ptCameraPosition = m_hMirrorTarget->EyePosition();
  143. m_hMirrorTarget->GetVectors ( &vCameraLook, &vCameraRight, &vCameraUp );
  144. // map this position and orientation to the remote portal, mirrored (invert the result)
  145. Vector ptNewPosition, vNewLook;
  146. ptNewPosition = matPortal1ToWorldInv * ptCameraPosition;
  147. ptNewPosition = matPortal2ToWorld*( Vector( -ptNewPosition.x, -ptNewPosition.y, ptNewPosition.z ) );
  148. vNewLook = matPortal1ToWorldInv.ApplyRotation( vCameraLook );
  149. vNewLook = matPortal2ToWorld.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z) );
  150. // Set the point camera to the new location/orientation
  151. QAngle qNewAngles;
  152. VectorAngles( vNewLook, qNewAngles );
  153. m_hMovementTarget->Teleport( &ptNewPosition, &qNewAngles, NULL );
  154. }
  155. SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
  156. }