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.

576 lines
15 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "datamodel/dmelementfactoryhelper.h"
  7. #include "movieobjects/dmeselection.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. //-----------------------------------------------------------------------------
  11. // Expose this class to the scene database
  12. //-----------------------------------------------------------------------------
  13. IMPLEMENT_ELEMENT_FACTORY( DmeComponent, CDmeComponent );
  14. //-----------------------------------------------------------------------------
  15. //
  16. //-----------------------------------------------------------------------------
  17. void CDmeComponent::OnConstruction()
  18. {
  19. m_Type.InitAndSet( this, "componentType", COMP_INVALID );
  20. m_bComplete.InitAndSet( this, "complete", false );
  21. }
  22. //-----------------------------------------------------------------------------
  23. //
  24. //-----------------------------------------------------------------------------
  25. void CDmeComponent::OnDestruction()
  26. {
  27. }
  28. //-----------------------------------------------------------------------------
  29. //
  30. //-----------------------------------------------------------------------------
  31. void CDmeComponent::Resolve()
  32. {
  33. }
  34. //-----------------------------------------------------------------------------
  35. // Expose this class to the scene database
  36. //-----------------------------------------------------------------------------
  37. IMPLEMENT_ELEMENT_FACTORY( DmeSingleIndexedComponent, CDmeSingleIndexedComponent );
  38. //-----------------------------------------------------------------------------
  39. //
  40. //-----------------------------------------------------------------------------
  41. void CDmeSingleIndexedComponent::OnConstruction()
  42. {
  43. m_CompleteCount.InitAndSet( this, "completeCount", 0 );
  44. m_Components.Init( this, "components" );
  45. m_Weights.Init( this, "weights" );
  46. }
  47. //-----------------------------------------------------------------------------
  48. //
  49. //-----------------------------------------------------------------------------
  50. void CDmeSingleIndexedComponent::OnDestruction()
  51. {
  52. }
  53. //-----------------------------------------------------------------------------
  54. //
  55. //-----------------------------------------------------------------------------
  56. void CDmeSingleIndexedComponent::Resolve()
  57. {
  58. }
  59. //-----------------------------------------------------------------------------
  60. //
  61. //-----------------------------------------------------------------------------
  62. int CDmeSingleIndexedComponent::Count() const
  63. {
  64. return IsComplete() ? m_CompleteCount.Get() : m_Components.Count();
  65. }
  66. //-----------------------------------------------------------------------------
  67. //
  68. //-----------------------------------------------------------------------------
  69. bool CDmeSingleIndexedComponent::SetType( Component_t type )
  70. {
  71. switch ( type )
  72. {
  73. case COMP_VTX:
  74. case COMP_FACE:
  75. m_Type.Set( type );
  76. return true;
  77. default:
  78. break;
  79. }
  80. return false;
  81. }
  82. //-----------------------------------------------------------------------------
  83. //
  84. //-----------------------------------------------------------------------------
  85. void CDmeSingleIndexedComponent::AddComponent( int component, float weight /*= 1.0f */ )
  86. {
  87. if ( IsComplete() )
  88. return;
  89. const int index( BinarySearch( component ) );
  90. Assert( index >= 0 );
  91. Assert( index <= m_Components.Count() );
  92. if ( index == m_Components.Count() )
  93. {
  94. m_Components.AddToTail( component );
  95. m_Weights.AddToTail( weight );
  96. }
  97. else if ( component == m_Components.Get( index ) )
  98. {
  99. Assert( index < m_Weights.Count() );
  100. m_Weights.Set( index, weight );
  101. }
  102. else
  103. {
  104. m_Components.InsertBefore( index, component );
  105. m_Weights.InsertBefore( index, weight );
  106. }
  107. }
  108. //-----------------------------------------------------------------------------
  109. //
  110. //-----------------------------------------------------------------------------
  111. void CDmeSingleIndexedComponent::AddComponents( const CUtlVector< int > &components )
  112. {
  113. const int nComponents( components.Count() );
  114. for ( int i( 0 ); i < nComponents; ++i )
  115. {
  116. AddComponent( components[ i ] );
  117. }
  118. }
  119. //-----------------------------------------------------------------------------
  120. //
  121. //-----------------------------------------------------------------------------
  122. void CDmeSingleIndexedComponent::AddComponents(
  123. const CUtlVector< int > &components, const CUtlVector< float > &weights )
  124. {
  125. const int nComponents( min( components.Count(), weights.Count() ) );
  126. for ( int i( 0 ); i < nComponents; ++i )
  127. {
  128. AddComponent( components[ i ], weights[ i ] );
  129. }
  130. }
  131. //-----------------------------------------------------------------------------
  132. //
  133. //-----------------------------------------------------------------------------
  134. void CDmeSingleIndexedComponent::RemoveComponent( int component )
  135. {
  136. Assert( !IsComplete() ); // TODO: Convert from complete to complete - component
  137. const int cIndex = BinarySearch( component );
  138. if ( cIndex >= m_Components.Count() || m_Components[ cIndex ] != component ) // Component not in selection
  139. return;
  140. m_Components.Remove( cIndex );
  141. m_Weights.Remove( cIndex );
  142. }
  143. //-----------------------------------------------------------------------------
  144. //
  145. //-----------------------------------------------------------------------------
  146. bool CDmeSingleIndexedComponent::GetComponent( int index, int &component, float &weight ) const
  147. {
  148. if ( index < Count() )
  149. {
  150. if ( IsComplete() )
  151. {
  152. component = index;
  153. weight = 1.0f;
  154. }
  155. else
  156. {
  157. component = m_Components[ index ];
  158. weight = m_Weights[ index ];
  159. }
  160. return true;
  161. }
  162. return false;
  163. }
  164. //-----------------------------------------------------------------------------
  165. //
  166. //-----------------------------------------------------------------------------
  167. void CDmeSingleIndexedComponent::GetComponents( CUtlVector< int > &components, CUtlVector< float > &weights ) const
  168. {
  169. if ( IsComplete() )
  170. {
  171. const int nComponents = Count();
  172. int *pComponents = reinterpret_cast< int * >( alloca( nComponents * sizeof( int ) ) );
  173. float *pWeights = reinterpret_cast< float * >( alloca( nComponents * sizeof( float ) ) );
  174. for ( int i = 0; i < nComponents; ++i )
  175. {
  176. pComponents[ i ] = i;
  177. pWeights[ i ] = 1.0f;
  178. }
  179. components.CopyArray( pComponents, nComponents );
  180. weights.CopyArray( pWeights, nComponents );
  181. }
  182. else
  183. {
  184. components.RemoveAll();
  185. components.CopyArray( m_Components.Base(), m_Components.Count() );
  186. weights.RemoveAll();
  187. weights.CopyArray( m_Weights.Base(), m_Weights.Count() );
  188. }
  189. }
  190. //-----------------------------------------------------------------------------
  191. //
  192. //-----------------------------------------------------------------------------
  193. void CDmeSingleIndexedComponent::GetComponents( CUtlVector< int > &components ) const
  194. {
  195. if ( IsComplete() )
  196. {
  197. const int nComponents = Count();
  198. int *pComponents = reinterpret_cast< int * >( alloca( nComponents * sizeof( int ) ) );
  199. for ( int i = 0; i < nComponents; ++i )
  200. {
  201. pComponents[ i ] = i;
  202. }
  203. components.CopyArray( pComponents, nComponents );
  204. }
  205. else
  206. {
  207. components.RemoveAll();
  208. components.CopyArray( m_Components.Base(), m_Components.Count() );
  209. }
  210. }
  211. //-----------------------------------------------------------------------------
  212. //
  213. //-----------------------------------------------------------------------------
  214. void CDmeSingleIndexedComponent::SetComplete( int nComplete )
  215. {
  216. m_bComplete.Set( true );
  217. m_CompleteCount.Set( max( 0, nComplete ) );
  218. m_Components.Purge();
  219. m_Weights.Purge();
  220. }
  221. //-----------------------------------------------------------------------------
  222. //
  223. //-----------------------------------------------------------------------------
  224. int CDmeSingleIndexedComponent::GetComplete() const
  225. {
  226. return IsComplete() ? m_CompleteCount.Get() : 0;
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Reset to an empty selection
  230. //-----------------------------------------------------------------------------
  231. inline void CDmeSingleIndexedComponent::Clear()
  232. {
  233. CDmeComponent::Clear();
  234. m_CompleteCount.Set( 0 );
  235. m_Components.RemoveAll();
  236. m_Weights.RemoveAll();
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Searches for the component in the sorted component list and returns the
  240. // index if it's found or if it's not found, returns the index at which it
  241. // should be inserted to maintain the sorted order of the component list
  242. //-----------------------------------------------------------------------------
  243. int CDmeSingleIndexedComponent::BinarySearch( int component ) const
  244. {
  245. const CUtlVector< int > &components( m_Components.Get() );
  246. const int nComponents( components.Count() );
  247. int left( 0 );
  248. int right( nComponents - 1 );
  249. int mid;
  250. while ( left <= right )
  251. {
  252. mid = ( left + right ) >> 1; // floor( ( left + right ) / 2.0 )
  253. if ( component > m_Components[ mid ] )
  254. {
  255. left = mid + 1;
  256. }
  257. else if ( component < m_Components[ mid ] )
  258. {
  259. right = mid - 1;
  260. }
  261. else
  262. {
  263. return mid;
  264. }
  265. }
  266. return left;
  267. }
  268. //-----------------------------------------------------------------------------
  269. //
  270. //-----------------------------------------------------------------------------
  271. bool CDmeSingleIndexedComponent::HasComponent( int component ) const
  272. {
  273. if ( IsComplete() )
  274. return true;
  275. const int cIndex = BinarySearch( component );
  276. if ( cIndex >= m_Components.Count() )
  277. return false;
  278. if ( m_Components[ cIndex ] == component )
  279. return true;
  280. return false;
  281. }
  282. //-----------------------------------------------------------------------------
  283. //
  284. //-----------------------------------------------------------------------------
  285. bool CDmeSingleIndexedComponent::GetWeight( int component, float &weight ) const
  286. {
  287. Assert( !IsComplete() );
  288. const int cIndex = BinarySearch( component );
  289. if ( cIndex >= m_Components.Count() )
  290. return false;
  291. if ( m_Components[ cIndex ] == component )
  292. {
  293. weight = m_Weights[ cIndex ];
  294. return true;
  295. }
  296. return false;
  297. }
  298. //-----------------------------------------------------------------------------
  299. //
  300. //-----------------------------------------------------------------------------
  301. void CDmeSingleIndexedComponent::Subtract( const CDmeSingleIndexedComponent &rhs )
  302. {
  303. const int nLhs = Count();
  304. const int nRhs = rhs.Count();
  305. int l = 0;
  306. int r = 0;
  307. if ( IsComplete() )
  308. {
  309. // TODO
  310. Assert( 0 );
  311. }
  312. else
  313. {
  314. CUtlVector< int > newComponents;
  315. newComponents.EnsureCapacity( nLhs );
  316. CUtlVector< float > newWeights;
  317. newWeights.EnsureCapacity( nLhs );
  318. while ( l < nLhs || r < nRhs )
  319. {
  320. // In LHS but not RHS
  321. while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) )
  322. {
  323. newComponents.AddToTail( m_Components[ l ] );
  324. newWeights.AddToTail( m_Weights[ l ] );
  325. ++l;
  326. }
  327. // In RHS but not LHS
  328. while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) )
  329. {
  330. ++r;
  331. }
  332. // In Both LHS & RHS
  333. while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] )
  334. {
  335. ++l;
  336. ++r;
  337. }
  338. }
  339. m_Components.CopyArray( newComponents.Base(), newComponents.Count() );
  340. m_Weights.CopyArray( newWeights.Base(), newWeights.Count() );
  341. }
  342. m_CompleteCount.Set( 0 );
  343. m_bComplete.Set( false );
  344. }
  345. //-----------------------------------------------------------------------------
  346. //
  347. //-----------------------------------------------------------------------------
  348. void CDmeSingleIndexedComponent::Add( const CDmeSingleIndexedComponent &rhs )
  349. {
  350. int nLhs = Count();
  351. const int nRhs = rhs.Count();
  352. int l = 0;
  353. int r = 0;
  354. if ( IsComplete() )
  355. {
  356. if ( rhs.IsComplete() && nRhs > nLhs )
  357. {
  358. m_CompleteCount.Set( nRhs );
  359. }
  360. else
  361. {
  362. while ( r < nRhs )
  363. {
  364. if ( rhs.m_Components[ r ] >= nLhs )
  365. {
  366. // Got one that's greater than the complete count of this one
  367. CUtlVector< int > newComponents;
  368. newComponents.EnsureCapacity( nLhs + nRhs - r );
  369. CUtlVector< float > newWeights;
  370. newWeights.EnsureCapacity( nLhs + nRhs - r );
  371. GetComponents( newComponents, newWeights );
  372. while ( r < nRhs )
  373. {
  374. newComponents.AddToTail( rhs.m_Components[ r ] );
  375. newWeights.AddToTail( rhs.m_Weights[ r ] );
  376. ++r;
  377. }
  378. m_Components.CopyArray( newComponents.Base(), newComponents.Count() );
  379. m_Weights.CopyArray( newWeights.Base(), newWeights.Count() );
  380. m_CompleteCount.Set( 0 );
  381. m_bComplete.Set( false );
  382. break;
  383. }
  384. ++r;
  385. }
  386. }
  387. }
  388. else
  389. {
  390. CUtlVector< int > newComponents;
  391. newComponents.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate assuming 50% of the components in rhs aren't in lhs
  392. CUtlVector< float > newWeights;
  393. newWeights.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate
  394. while ( l < nLhs || r < nRhs )
  395. {
  396. while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) )
  397. {
  398. newComponents.AddToTail( m_Components[ l ] );
  399. newWeights.AddToTail( m_Weights[ l ] );
  400. ++l;
  401. }
  402. // In RHS but not LHS
  403. while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) )
  404. {
  405. newComponents.AddToTail( rhs.m_Components[ r ] );
  406. newWeights.AddToTail( rhs.m_Weights[ r ] );
  407. ++r;
  408. }
  409. // In Both LHS & RHS
  410. while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] )
  411. {
  412. newComponents.AddToTail( m_Components[ l ] );
  413. newWeights.AddToTail( m_Weights[ l ] );
  414. ++l;
  415. ++r;
  416. }
  417. }
  418. m_Components.CopyArray( newComponents.Base(), newComponents.Count() );
  419. m_Weights.CopyArray( newWeights.Base(), newWeights.Count() );
  420. }
  421. m_CompleteCount.Set( 0 );
  422. m_bComplete.Set( false );
  423. }
  424. //-----------------------------------------------------------------------------
  425. //
  426. //-----------------------------------------------------------------------------
  427. void CDmeSingleIndexedComponent::Intersection( const CDmeSingleIndexedComponent &rhs )
  428. {
  429. const int nLhs = Count();
  430. const int nRhs = rhs.Count();
  431. int l = 0;
  432. int r = 0;
  433. if ( IsComplete() )
  434. {
  435. // TODO
  436. Assert( 0 );
  437. }
  438. else
  439. {
  440. CUtlVector< int > newComponents;
  441. newComponents.EnsureCapacity( nLhs );
  442. CUtlVector< float > newWeights;
  443. newWeights.EnsureCapacity( nLhs );
  444. while ( l < nLhs || r < nRhs )
  445. {
  446. // In LHS but not RHS
  447. while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) )
  448. {
  449. ++l;
  450. }
  451. // In RHS but not LHS
  452. while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) )
  453. {
  454. ++r;
  455. }
  456. // In Both LHS & RHS
  457. while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] )
  458. {
  459. newComponents.AddToTail( m_Components[ l ] );
  460. newWeights.AddToTail( m_Weights[ l ] );
  461. ++l;
  462. ++r;
  463. }
  464. }
  465. m_Components.CopyArray( newComponents.Base(), newComponents.Count() );
  466. m_Weights.CopyArray( newWeights.Base(), newWeights.Count() );
  467. }
  468. m_CompleteCount.Set( 0 );
  469. m_bComplete.Set( false );
  470. }