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.

851 lines
25 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "stdafx.h"
  7. #include "hammer_mathlib.h"
  8. #include "MainFrm.h"
  9. #include "ObjectProperties.h"
  10. #include "Box3D.h"
  11. #include "BSPFile.h"
  12. #include "const.h"
  13. #include "MapDefs.h" // dvs: For COORD_NOTINIT
  14. #include "MapEntity.h"
  15. #include "MapInstance.h"
  16. #include "Manifest.h"
  17. #include "Render2D.h"
  18. #include "Render3D.h"
  19. #include "MapView2D.h"
  20. #include "MapView3D.h"
  21. #include "hammer.h"
  22. #include "Texture.h"
  23. #include "TextureSystem.h"
  24. #include "materialsystem/imesh.h"
  25. #include "Material.h"
  26. #include "Options.h"
  27. #include "camera.h"
  28. #include "MapWorld.h"
  29. #include "mapview.h"
  30. // memdbgon must be the last include file in a .cpp file!!!
  31. #include <tier0/memdbgon.h>
  32. IMPLEMENT_MAPCLASS(CMapInstance)
  33. char CMapInstance::m_InstancePath[ MAX_PATH ] = "";
  34. //-----------------------------------------------------------------------------
  35. // Purpose: Factory function. Used for creating a CMapInstance.
  36. // Input : pHelperInfo - Pointer to helper info class which gives us information
  37. // about how to create the class.
  38. // pParent - the owning entity ( func_instance )
  39. // Output : Returns a pointer to the class, NULL if an error occurs.
  40. //-----------------------------------------------------------------------------
  41. CMapClass *CMapInstance::Create( CHelperInfo *pHelperInfo, CMapEntity *pParent )
  42. {
  43. char FileName[ MAX_PATH ];
  44. const char *FileNameKey = pParent->GetKeyValue( "file" );
  45. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  46. if ( FileNameKey )
  47. {
  48. V_strcpy_safe( FileName, pParent->GetKeyValue( "file" ) );
  49. }
  50. else
  51. {
  52. FileName[ 0 ] = 0;
  53. }
  54. CMapInstance *pInstance = new CMapInstance( pDoc->GetPathName(), FileName );
  55. return pInstance;
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: this function will set a secondary lookup path for instances.
  59. // Input : pszInstancePath - the secondary lookup path
  60. //-----------------------------------------------------------------------------
  61. void CMapInstance::SetInstancePath( const char *pszInstancePath )
  62. {
  63. strcpy( m_InstancePath, pszInstancePath );
  64. V_strlower( m_InstancePath );
  65. V_FixSlashes( m_InstancePath );
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: This function will attempt to find a full path given the base and relative names.
  69. // Input : pszBaseFileName - the base file that referenced this instance
  70. // pszInstanceFileName - the relative file name of this instance
  71. // Output : Returns true if it was able to locate the file
  72. // pszOutFileName - the full path to the file name if located
  73. //-----------------------------------------------------------------------------
  74. bool CMapInstance::DeterminePath( const char *pszBaseFileName, const char *pszInstanceFileName, char *pszOutFileName )
  75. {
  76. char szInstanceFileNameFixed[ MAX_PATH ];
  77. const char *pszMapPath = "\\maps\\";
  78. strcpy( szInstanceFileNameFixed, pszInstanceFileName );
  79. V_SetExtension( szInstanceFileNameFixed, ".vmf", sizeof( szInstanceFileNameFixed ) );
  80. V_FixSlashes( szInstanceFileNameFixed );
  81. // first, try to find a relative location based upon the Base file name
  82. strcpy( pszOutFileName, pszBaseFileName );
  83. V_StripFilename( pszOutFileName );
  84. strcat( pszOutFileName, "\\" );
  85. strcat( pszOutFileName, szInstanceFileNameFixed );
  86. if ( g_pFullFileSystem->FileExists( pszOutFileName ) )
  87. {
  88. return true;
  89. }
  90. // second, try to find the master 'maps' directory and make it relative from that
  91. strcpy( pszOutFileName, pszBaseFileName );
  92. V_StripFilename( pszOutFileName );
  93. V_RemoveDotSlashes( pszOutFileName );
  94. V_FixDoubleSlashes( pszOutFileName );
  95. V_strlower( pszOutFileName );
  96. strcat( pszOutFileName, "\\" );
  97. char *pos = strstr( pszOutFileName, pszMapPath );
  98. if ( pos )
  99. {
  100. pos += strlen( pszMapPath );
  101. *pos = 0;
  102. strcat( pszOutFileName, szInstanceFileNameFixed );
  103. if ( g_pFullFileSystem->FileExists( pszOutFileName ) )
  104. {
  105. return true;
  106. }
  107. }
  108. if ( m_InstancePath[ 0 ] != 0 )
  109. {
  110. sprintf( szInstanceFileNameFixed, "%s%s", m_InstancePath, pszInstanceFileName );
  111. if ( g_pFullFileSystem->FileExists( szInstanceFileNameFixed, "GAME" ) )
  112. {
  113. char FullPath[ MAX_PATH ];
  114. g_pFullFileSystem->RelativePathToFullPath( szInstanceFileNameFixed, "GAME", FullPath, sizeof( FullPath ) );
  115. strcpy( pszOutFileName, FullPath );
  116. return true;
  117. }
  118. }
  119. pszOutFileName[ 0 ] = 0;
  120. return false;
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose: Constructor.
  124. //-----------------------------------------------------------------------------
  125. CMapInstance::CMapInstance( void )
  126. {
  127. Initialize();
  128. }
  129. //-----------------------------------------------------------------------------
  130. // Purpose: Constructor.
  131. // Input : pszBaseFileName - the root path of where the instance will be loaded from.
  132. // pszInstanceFileName - the relative name of the instance to be loaded.
  133. // Output :
  134. //-----------------------------------------------------------------------------
  135. CMapInstance::CMapInstance( const char *pszBaseFileName, const char *pszInstanceFileName )
  136. {
  137. Initialize();
  138. if ( pszInstanceFileName[ 0 ] && DeterminePath( pszBaseFileName, pszInstanceFileName, m_FileName ) )
  139. {
  140. bool bSaveVisible = CHammer::IsNewDocumentVisible();
  141. CMapDoc *activeDoc = CMapDoc::GetActiveMapDoc();
  142. CHammer::SetIsNewDocumentVisible( false );
  143. m_pInstancedMap = ( CMapDoc * )APP()->OpenDocumentFile( m_FileName );
  144. if ( m_pInstancedMap )
  145. {
  146. m_pInstancedMap->AddReference();
  147. m_pInstancedMap->Update();
  148. }
  149. CMapDoc::SetActiveMapDoc( activeDoc );
  150. CHammer::SetIsNewDocumentVisible( bSaveVisible );
  151. }
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose: Destructor.
  155. //-----------------------------------------------------------------------------
  156. CMapInstance::~CMapInstance(void)
  157. {
  158. if ( m_pInstancedMap )
  159. {
  160. m_pInstancedMap->RemoveReference();
  161. m_pInstancedMap = NULL;
  162. }
  163. }
  164. GDIV_TYPE CMapInstance::GetFieldType( const char *pInstanceValue )
  165. {
  166. CMapEntityList entityList;
  167. GDinputvariable TempVar;
  168. m_pInstancedMap->FindEntitiesByClassName( entityList, "func_instance_parms", false );
  169. if ( entityList.Count() != 1 )
  170. {
  171. return ivBadType;
  172. }
  173. CMapEntity *pInstanceParmsEntity = entityList.Element( 0 );
  174. const char *InstancePos = strchr( pInstanceValue, ' ' );
  175. if ( InstancePos == NULL )
  176. {
  177. return ivBadType;
  178. }
  179. int len = InstancePos - pInstanceValue;
  180. for ( int i = pInstanceParmsEntity->GetFirstKeyValue(); i != pInstanceParmsEntity->GetInvalidKeyValue(); i = pInstanceParmsEntity->GetNextKeyValue( i ) )
  181. {
  182. LPCTSTR pKey = pInstanceParmsEntity->GetKey( i );
  183. LPCTSTR pValue = pInstanceParmsEntity->GetKeyValue( i );
  184. if ( strnicmp( pKey, "parm", strlen( "parm" ) ) == 0 )
  185. {
  186. const char *InstanceParmsPos = strchr( pValue, ' ' );
  187. if ( InstanceParmsPos == NULL )
  188. {
  189. continue;
  190. }
  191. if ( strnicmp( pInstanceValue, pValue, len ) == 0 )
  192. {
  193. return TempVar.GetTypeFromToken( InstanceParmsPos + 1 );
  194. }
  195. }
  196. }
  197. return ivBadType;
  198. }
  199. void CMapInstance::FindTargetNames( CUtlVector< const char * > &Names )
  200. {
  201. CMapEntity *pEntity = dynamic_cast< CMapEntity * >( GetParent() );
  202. for ( int j = pEntity->GetFirstKeyValue(); j != pEntity->GetInvalidKeyValue(); j = pEntity->GetNextKeyValue( j ) )
  203. {
  204. LPCTSTR pInstanceKey = pEntity->GetKey( j );
  205. LPCTSTR pInstanceValue = pEntity->GetKeyValue( j );
  206. if ( strnicmp( pInstanceKey, "replace", strlen( "replace" ) ) == 0 )
  207. {
  208. GDIV_TYPE FieldType = GetFieldType( pInstanceValue );
  209. if ( FieldType == ivTargetDest ||
  210. FieldType == ivTargetNameOrClass ||
  211. FieldType == ivTargetSrc )
  212. {
  213. const char *pszInstancePos = strchr( pInstanceValue, ' ' );
  214. if ( pszInstancePos )
  215. {
  216. pszInstancePos++;
  217. char *temp = new char[ strlen( pszInstancePos ) + 1 ];
  218. strcpy( temp, pszInstancePos );
  219. Names.AddToTail( temp );
  220. }
  221. }
  222. }
  223. }
  224. }
  225. void CMapInstance::ReplaceTargetname( const char *szOldName, const char *szNewName )
  226. {
  227. BaseClass::ReplaceTargetname( szOldName, szNewName );
  228. CMapEntity *pEntity = dynamic_cast< CMapEntity * >( GetParent() );
  229. for ( int j = pEntity->GetFirstKeyValue(); j != pEntity->GetInvalidKeyValue(); j = pEntity->GetNextKeyValue( j ) )
  230. {
  231. LPCTSTR pInstanceKey = pEntity->GetKey( j );
  232. LPCTSTR pInstanceValue = pEntity->GetKeyValue( j );
  233. if ( strnicmp( pInstanceKey, "replace", strlen( "replace" ) ) == 0 )
  234. {
  235. const char *InstancePos = strchr( pInstanceValue, ' ' );
  236. if ( InstancePos == NULL )
  237. {
  238. continue;
  239. }
  240. int nLen = InstancePos - pInstanceValue;
  241. if ( strcmp( szOldName, InstancePos + 1 ) == 0 )
  242. {
  243. nLen++;
  244. char *pszResult = ( char * )stackalloc( nLen + strlen( szNewName ) + 1 );
  245. strncpy( pszResult, pInstanceValue, nLen );
  246. strcpy( &pszResult[ nLen ], szNewName );
  247. pEntity->SetKeyValue( pInstanceKey, pszResult );
  248. }
  249. }
  250. }
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose: This function is called when the owning entity's Key/Value pairs have
  254. // been updated. This will attempt to load a new instance if the map has
  255. // been changed.
  256. // Input : none.
  257. // Output : none.
  258. //-----------------------------------------------------------------------------
  259. bool CMapInstance::OnApply( void )
  260. {
  261. CString MapFileName;
  262. char FileName[ MAX_PATH ];
  263. CMapDoc *activeDoc = CMapDoc::GetActiveMapDoc();
  264. MapFileName = activeDoc->GetPathName();
  265. CMapEntity *ent = dynamic_cast< CMapEntity * >( GetParent() );
  266. if ( m_pInstancedMap )
  267. {
  268. m_pInstancedMap->RemoveReference();
  269. }
  270. if ( ent && ent->GetKeyValue( "file" ) )
  271. {
  272. DeterminePath( MapFileName, ent->GetKeyValue( "file" ), FileName );
  273. if ( strcmpi( FileName, m_FileName ) != 0 )
  274. {
  275. bool bSaveVisible = CHammer::IsNewDocumentVisible();
  276. CHammer::SetIsNewDocumentVisible( false );
  277. strcpy( m_FileName, FileName );
  278. m_pInstancedMap = ( CMapDoc * )APP()->OpenDocumentFile( m_FileName );
  279. CHammer::SetIsNewDocumentVisible( bSaveVisible );
  280. }
  281. }
  282. else
  283. {
  284. m_pInstancedMap = NULL;
  285. }
  286. if ( m_pInstancedMap == NULL )
  287. {
  288. m_FileName[ 0 ] = 0;
  289. }
  290. else
  291. {
  292. m_pInstancedMap->AddReference();
  293. m_pInstancedMap->Update();
  294. }
  295. GetMainWnd()->pObjectProperties->MarkDataDirty();
  296. // loading this instance will bring it forward in the MDI - we want to show the original map though
  297. CMapDoc::ActivateMapDoc( activeDoc );
  298. return true;
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: Calculates our bounding box based on instance map's dimensions.
  302. // Input : bFullUpdate - Whether we should recalculate our children's bounds.
  303. // Output : none.
  304. //-----------------------------------------------------------------------------
  305. void CMapInstance::CalcBounds(BOOL bFullUpdate)
  306. {
  307. CMapClass::CalcBounds(bFullUpdate);
  308. //
  309. // Build our bounds for frustum culling in the 3D view.
  310. //
  311. if ( m_pInstancedMap && GetParent() && m_pInstancedMap->GetMapWorld() )
  312. {
  313. Vector vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs;
  314. matrix3x4_t Instance3x4Matrix;
  315. CMapClass *pParent = GetParent();
  316. pParent->GetOrigin( m_Origin );
  317. AngleMatrix( m_Angles, m_Origin, Instance3x4Matrix );
  318. m_pInstancedMap->GetMapWorld()->CalcBounds( true );
  319. #if 0
  320. m_pInstancedMap->GetMapWorld()->GetCullBox( vecMins, vecMaxs );
  321. TransformAABB( Instance3x4Matrix, vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs );
  322. m_CullBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  323. #endif
  324. m_pInstancedMap->GetMapWorld()->GetBoundingBox( vecMins, vecMaxs );
  325. TransformAABB( Instance3x4Matrix, vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs );
  326. m_CullBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  327. m_BoundingBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  328. m_Render2DBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  329. }
  330. else
  331. {
  332. Vector vecExpandedMins, vecExpandedMaxs;
  333. vecExpandedMins.Init( -32.0f, -32.0f, -32.0f );
  334. vecExpandedMins += m_Origin;
  335. vecExpandedMaxs.Init( 32.0f, 32.0f, 32.0f );
  336. vecExpandedMaxs += m_Origin;
  337. m_CullBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  338. m_BoundingBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  339. m_Render2DBox.UpdateBounds( vecExpandedMins, vecExpandedMaxs );
  340. }
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Purpose: Will calculate the bounding box of the instance as a child has changed
  344. // Input : pChild - Pointer to the object that changed.
  345. //-----------------------------------------------------------------------------
  346. void CMapInstance::UpdateChild(CMapClass *pChild)
  347. {
  348. CalcBounds( TRUE );
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose: this function will attempt to find a child inside of the instance. If the bool and matrix
  352. // are supplied, the localized matrix will be built.
  353. // Input : key - the key field to lookup
  354. // value - the value to find
  355. // Output : returns the entity found
  356. // bIsInInstance - optional parameter to indicate if the found entity is inside of an instance
  357. // InstanceMatrix - optional parameter to set the localized matrix of the instance stack
  358. //-----------------------------------------------------------------------------
  359. CMapEntity *CMapInstance::FindChildByKeyValue( const char* key, const char* value, bool *bIsInInstance, VMatrix *InstanceMatrix )
  360. {
  361. if ( m_pInstancedMap && bIsInInstance )
  362. {
  363. CMapEntity *result = m_pInstancedMap->GetMapWorld()->FindChildByKeyValue( key, value );
  364. if ( result )
  365. {
  366. if ( ( *bIsInInstance ) == false )
  367. {
  368. *bIsInInstance = true;
  369. if ( InstanceMatrix )
  370. {
  371. InstanceMatrix->Identity();
  372. }
  373. }
  374. if ( InstanceMatrix )
  375. {
  376. VMatrix LocalInstanceMatrix, Result;
  377. LocalInstanceMatrix.SetupMatrixOrgAngles( m_Origin, m_Angles );
  378. Result = ( *InstanceMatrix ) * LocalInstanceMatrix;
  379. *InstanceMatrix = Result;
  380. }
  381. }
  382. return result;
  383. }
  384. return NULL;
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose: this function is called for when an instance has moved
  388. //-----------------------------------------------------------------------------
  389. void CMapInstance::InstanceMoved( void )
  390. {
  391. if ( m_pInstancedMap )
  392. {
  393. m_pInstancedMap->InstanceMoved();
  394. }
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose: Returns a copy of this object.
  398. // Output : Pointer to the new object.
  399. //-----------------------------------------------------------------------------
  400. CMapClass *CMapInstance::Copy(bool bUpdateDependencies)
  401. {
  402. CMapInstance *pCopy = new CMapInstance;
  403. if (pCopy != NULL)
  404. {
  405. pCopy->CopyFrom(this, bUpdateDependencies);
  406. }
  407. return(pCopy);
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Purpose: Turns this into a duplicate of the given object.
  411. // Input : pObject - Pointer to the object to copy from.
  412. // Output : Returns a pointer to this object.
  413. //-----------------------------------------------------------------------------
  414. CMapClass *CMapInstance::CopyFrom(CMapClass *pObject, bool bUpdateDependencies)
  415. {
  416. CMapInstance *pFrom = dynamic_cast<CMapInstance *>(pObject);
  417. Assert(pObject != NULL);
  418. if (pObject != NULL)
  419. {
  420. CMapClass::CopyFrom(pObject, bUpdateDependencies);
  421. m_Angles = pFrom->m_Angles;
  422. strcpy( m_FileName, pFrom->m_FileName );
  423. m_pInstancedMap = pFrom->m_pInstancedMap;
  424. if ( m_pInstancedMap )
  425. {
  426. m_pInstancedMap->AddReference();
  427. m_pInstancedMap->Update();
  428. }
  429. }
  430. return(this);
  431. }
  432. //-----------------------------------------------------------------------------
  433. // Purpose: Set's the map instance's angles
  434. // Input : Angles - the angles to set to
  435. //-----------------------------------------------------------------------------
  436. void CMapInstance::GetAngles(QAngle &Angles)
  437. {
  438. Angles = m_Angles;
  439. }
  440. //-----------------------------------------------------------------------------
  441. // Purpose: Initialized the map instance
  442. //-----------------------------------------------------------------------------
  443. void CMapInstance::Initialize(void)
  444. {
  445. m_Angles.Init();
  446. m_pInstancedMap = NULL;
  447. m_FileName[ 0 ] = 0;
  448. m_pManifestMap = NULL;
  449. }
  450. //-----------------------------------------------------------------------------
  451. // Purpose: Sets the manifest that loaded this instance
  452. // Input : pManifestMap - the manifest
  453. //-----------------------------------------------------------------------------
  454. void CMapInstance::SetManifest( CManifestMap *pManifestMap )
  455. {
  456. Initialize();
  457. m_pManifestMap = pManifestMap;
  458. m_pInstancedMap = m_pManifestMap->m_Map;
  459. strcpy( m_FileName, m_pManifestMap->m_AbsoluteMapFileName );
  460. }
  461. //-----------------------------------------------------------------------------
  462. // Purpose: This will render the map instance into the 3d view.
  463. // Input : pRender - the 3d render
  464. //-----------------------------------------------------------------------------
  465. void CMapInstance::Render3D(CRender3D *pRender)
  466. {
  467. if ( m_pInstancedMap )
  468. {
  469. pRender->RenderInstanceMapClass( this, m_pInstancedMap->GetMapWorld(), m_Origin, m_Angles );
  470. }
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: this function will display an instance map window. it will also set the
  474. // views to the approx same camera position.
  475. //-----------------------------------------------------------------------------
  476. void CMapInstance::SwitchTo( void )
  477. {
  478. if ( !m_pInstancedMap )
  479. {
  480. return;
  481. }
  482. CMapDoc *pCurrentDoc = CMapDoc::GetActiveMapDoc();
  483. m_pInstancedMap->ShowWindow( true );
  484. CMapDoc::ActivateMapDoc( m_pInstancedMap );
  485. POSITION PositionCurrentView = pCurrentDoc->GetFirstViewPosition();
  486. POSITION PositionNewView = m_pInstancedMap->GetFirstViewPosition();
  487. while ( PositionCurrentView && PositionNewView )
  488. {
  489. CMapView *pViewCurrent = dynamic_cast< CMapView * >( pCurrentDoc->GetNextView( PositionCurrentView ) );
  490. CMapView2D *pViewCurrent2D = dynamic_cast< CMapView2D * >( pViewCurrent );
  491. CMapView3D *pViewCurrent3D = dynamic_cast< CMapView3D * >( pViewCurrent );
  492. CMapView *pViewNew = dynamic_cast< CMapView * >( m_pInstancedMap->GetNextView( PositionNewView ) );
  493. CMapView2D *pViewNew2D = dynamic_cast< CMapView2D * >( pViewNew );
  494. CMapView3D *pViewNew3D = dynamic_cast< CMapView3D * >( pViewNew );
  495. if ( ( !pViewCurrent2D || !pViewNew2D ) && ( !pViewCurrent3D || !pViewNew3D ) )
  496. {
  497. continue;
  498. }
  499. Vector CameraVector;
  500. CCamera *CurrentCamera;
  501. CurrentCamera = pViewCurrent->GetCamera();
  502. CurrentCamera->GetViewPoint( CameraVector );
  503. if ( pViewCurrent2D )
  504. {
  505. CameraVector = CameraVector - m_Origin;
  506. pViewNew2D->GetCamera()->SetViewPoint( CameraVector );
  507. pViewNew2D->GetCamera()->SetZoom( pViewCurrent2D->GetZoom() );
  508. }
  509. else
  510. {
  511. matrix3x4_t Camera3x4Matrix, InstanceMatrix, InstanceInverseMatrix;
  512. matrix3x4_t ResultMatrix;
  513. QAngle InstanceAngles, CameraAngles;
  514. CameraAngles.Init( CurrentCamera->GetPitch(), CurrentCamera->GetYaw(), CurrentCamera->GetRoll() );
  515. InstanceAngles = m_Angles;
  516. InstanceAngles.x = 0;
  517. InstanceAngles.z = 0;
  518. AngleMatrix( InstanceAngles, m_Origin, InstanceMatrix );
  519. MatrixInvert( InstanceMatrix, InstanceInverseMatrix );
  520. AngleMatrix( CameraAngles, CameraVector, Camera3x4Matrix );
  521. MatrixMultiply( InstanceInverseMatrix, Camera3x4Matrix, ResultMatrix );
  522. MatrixPosition( ResultMatrix, CameraVector );
  523. MatrixMultiply( InstanceMatrix, Camera3x4Matrix, ResultMatrix );
  524. MatrixAngles( ResultMatrix, CameraAngles );
  525. pViewNew3D->GetCamera()->SetViewPoint( CameraVector );
  526. pViewNew3D->GetCamera()->SetPitch( CameraAngles.x );
  527. pViewNew3D->GetCamera()->SetYaw( CameraAngles.y );
  528. // pViewNew3D->GetCamera()->SetRoll( CameraAngles.z ); we probably don't want to set this!
  529. }
  530. pViewNew->UpdateView( MAPVIEW_OPTIONS_CHANGED );
  531. }
  532. }
  533. //-----------------------------------------------------------------------------
  534. // Purpose: we do not want to serialize this
  535. // Input : &File -
  536. // bRMF -
  537. // Output : int
  538. //-----------------------------------------------------------------------------
  539. int CMapInstance::SerializeRMF(std::fstream &File, BOOL bRMF)
  540. {
  541. return(0);
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose: we do not want to serialize this
  545. // Input : &File -
  546. // bRMF -
  547. // Output : int
  548. //-----------------------------------------------------------------------------
  549. int CMapInstance::SerializeMAP(std::fstream &File, BOOL bRMF)
  550. {
  551. return(0);
  552. }
  553. //-----------------------------------------------------------------------------
  554. // Purpose: Canculate angles based upon the transform
  555. // Input : pTransBox -
  556. //-----------------------------------------------------------------------------
  557. void CMapInstance::DoTransform(const VMatrix &matrix)
  558. {
  559. CMapClass *pParent = GetParent();
  560. pParent->GetOrigin( m_Origin );
  561. // BaseClass::DoTransform(matrix);
  562. matrix3x4_t fCurrentMatrix,fMatrixNew;
  563. AngleMatrix(m_Angles, fCurrentMatrix);
  564. ConcatTransforms(matrix.As3x4(), fCurrentMatrix, fMatrixNew);
  565. MatrixAngles(fMatrixNew, m_Angles);
  566. CMapEntity *pEntity = dynamic_cast< CMapEntity * >( m_pParent );
  567. if (pEntity != NULL)
  568. {
  569. char szValue[ 80 ];
  570. sprintf( szValue, "%g %g %g", m_Angles[ 0 ], m_Angles[ 1 ], m_Angles[ 2 ] );
  571. pEntity->NotifyChildKeyChanged( this, "angles", szValue );
  572. }
  573. InstanceMoved();
  574. }
  575. //-----------------------------------------------------------------------------
  576. // Purpose: Notifies that this object's parent entity has had a key value change.
  577. // Input : szKey - The key that changed.
  578. // szValue - The new value of the key.
  579. //-----------------------------------------------------------------------------
  580. void CMapInstance::OnParentKeyChanged(const char* szKey, const char* szValue)
  581. {
  582. if (!stricmp(szKey, "angles"))
  583. {
  584. sscanf(szValue, "%f %f %f", &m_Angles[PITCH], &m_Angles[YAW], &m_Angles[ROLL]);
  585. PostUpdate(Notify_Changed);
  586. }
  587. }
  588. //-----------------------------------------------------------------------------
  589. // Purpose: indicates that we should not render last
  590. // Output : returns false.
  591. //-----------------------------------------------------------------------------
  592. bool CMapInstance::ShouldRenderLast(void)
  593. {
  594. return( false );
  595. }
  596. //-----------------------------------------------------------------------------
  597. // Purpose: This will render the map instance into the 2d view as well as a
  598. // bounding box.
  599. // Input : pRender - the 2d render
  600. //-----------------------------------------------------------------------------
  601. void CMapInstance::Render2D(CRender2D *pRender)
  602. {
  603. CMapView2D *pView = ( CMapView2D * )pRender->GetView();
  604. if ( m_pInstancedMap )
  605. {
  606. pView->RenderInstance( this, m_pInstancedMap->GetMapWorld(), m_Origin, m_Angles );
  607. }
  608. if ( m_pManifestMap )
  609. {
  610. return;
  611. }
  612. Vector vecMins;
  613. Vector vecMaxs;
  614. GetRender2DBox(vecMins, vecMaxs);
  615. Vector2D pt,pt2;
  616. pRender->TransformPoint(pt, vecMins);
  617. pRender->TransformPoint(pt2, vecMaxs);
  618. if (!IsSelected())
  619. {
  620. pRender->SetDrawColor( r, g, b );
  621. pRender->SetHandleColor( r, g, b );
  622. }
  623. else
  624. {
  625. pRender->SetDrawColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
  626. pRender->SetHandleColor( GetRValue(Options.colors.clrSelection), GetGValue(Options.colors.clrSelection), GetBValue(Options.colors.clrSelection) );
  627. }
  628. // Draw the bounding box.
  629. pRender->DrawBox( vecMins, vecMaxs );
  630. //
  631. // Draw center handle.
  632. //
  633. if ( pRender->IsActiveView() )
  634. {
  635. int sizex = abs(pt.x - pt2.x)+1;
  636. int sizey = abs(pt.y - pt2.y)+1;
  637. // dont draw handle if object is too small
  638. if ( sizex > 6 && sizey > 6 )
  639. {
  640. pRender->SetHandleStyle( HANDLE_RADIUS, CRender::HANDLE_CROSS );
  641. pRender->DrawHandle( (vecMins+vecMaxs)/2 );
  642. }
  643. }
  644. }
  645. //-----------------------------------------------------------------------------
  646. // Called by entity code to render sprites
  647. //-----------------------------------------------------------------------------
  648. void CMapInstance::RenderLogicalAt(CRender2D *pRender, const Vector2D &vecMins, const Vector2D &vecMaxs )
  649. {
  650. }
  651. //-----------------------------------------------------------------------------
  652. // Purpose: Returns if this instance is editable. A pure instance is not editable.
  653. // If it is part of a manifest, it must be the primary map of the manifest
  654. // in order for it to be editable.
  655. //-----------------------------------------------------------------------------
  656. bool CMapInstance::IsEditable( void )
  657. {
  658. if ( m_pManifestMap )
  659. {
  660. return m_pManifestMap->IsEditable();
  661. }
  662. return false;
  663. }
  664. //-----------------------------------------------------------------------------
  665. // Purpose: this function checks to see if the instance is visible.
  666. // Output : returns true if the instance is visible.
  667. //-----------------------------------------------------------------------------
  668. bool CMapInstance::IsInstanceVisible( void )
  669. {
  670. if ( IsInstance() )
  671. {
  672. if ( CMapDoc::GetActiveMapDoc() && CMapDoc::GetActiveMapDoc()->GetShowInstance() == INSTANCES_HIDE )
  673. {
  674. return false;
  675. }
  676. }
  677. else
  678. {
  679. if ( GetManifestMap() && GetManifestMap()->m_bVisible == false )
  680. {
  681. return false;
  682. }
  683. }
  684. return true;
  685. }
  686. //-----------------------------------------------------------------------------
  687. // Purpose: this function will recalculate its bounds because map has changed
  688. //-----------------------------------------------------------------------------
  689. void CMapInstance::UpdateInstanceMap( void )
  690. {
  691. CalcBounds();
  692. }