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.

4965 lines
141 KiB

  1. // SculptOptions.cpp : implementation file
  2. //
  3. #include <stdafx.h>
  4. #include "hammer.h"
  5. #include "CollisionUtils.h"
  6. #include "resource.h"
  7. #include "ToolDisplace.h"
  8. #include "MainFrm.h"
  9. #include "FaceEditSheet.h"
  10. #include "GlobalFunctions.h"
  11. #include "MapAtom.h"
  12. #include "MapSolid.h"
  13. #include "MapView3D.h"
  14. #include "History.h"
  15. #include "Camera.h"
  16. #include "MapDoc.h"
  17. #include "ChunkFile.h"
  18. #include "ToolManager.h"
  19. #include "bitmap/tgaloader.h"
  20. #include "tier1/utlbuffer.h"
  21. #include "Material.h"
  22. #include "materialsystem/imaterial.h"
  23. #include "materialsystem/imaterialsystem.h"
  24. #include "materialsystem/materialsystemutil.h"
  25. #include "materialsystem/itexture.h"
  26. #include "../materialsystem/itextureinternal.h"
  27. #include "pixelwriter.h"
  28. #include "TextureSystem.h"
  29. #include "SculptOptions.h"
  30. #include "tablet.h"
  31. #include "vstdlib/random.h"
  32. // memdbgon must be the last include file in a .cpp file!!!
  33. #include <tier0/memdbgon.h>
  34. extern CToolDisplace* GetDisplacementTool();
  35. extern void FaceListSewEdges( void );
  36. CUtlMap<EditDispHandle_t, CMapDisp *> CSculptTool::m_OrigMapDisp( 3, 3, CSculptTool::MapDispLessFunc );
  37. //-----------------------------------------------------------------------------
  38. // Purpose: constructor
  39. //-----------------------------------------------------------------------------
  40. CSculptTool::CSculptTool()
  41. {
  42. m_PaintOwner = NULL;
  43. m_MousePoint.Init();
  44. m_StartingCollisionNormal.Init();
  45. m_OriginalCollisionPoint.Init();
  46. m_bAltDown = m_bCtrlDown = m_bShiftDown = false;
  47. m_bLMBDown = m_bRMBDown = false;
  48. m_ValidPaintingSpot = false;
  49. m_BrushSize = 50;
  50. m_StartingProjectedRadius = m_OriginalProjectedRadius = 10.0f;
  51. m_OriginalCollisionValid = m_CurrentCollisionValid = false;
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Purpose: destructor
  55. //-----------------------------------------------------------------------------
  56. CSculptTool::~CSculptTool()
  57. {
  58. FOR_EACH_MAP( m_OrigMapDisp, pos )
  59. {
  60. delete m_OrigMapDisp.Element( pos );
  61. }
  62. m_OrigMapDisp.Purge();
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: setup for starting to paint on the displacement
  66. // Input : pView - the 3d view
  67. // vPoint - the initial click point
  68. // Output : returns true if successful
  69. //-----------------------------------------------------------------------------
  70. bool CSculptTool::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  71. {
  72. DuplicateSelectedDisp();
  73. GetStartingSpot( pView, vPoint );
  74. return true;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose: main routine called when mouse move has happened to start painting
  78. // Input : pView - the 3d view
  79. // vPoint - the mouse point
  80. // SpatialData - the spatial data ( mostly ignored )
  81. // Output : returns true if successful
  82. //-----------------------------------------------------------------------------
  83. bool CSculptTool::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &SpatialData )
  84. {
  85. m_SpatialData = SpatialData;
  86. // Successful paint operation.
  87. return true;
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose: determines if any of the special keys ( control, shift, alt ) are pressed
  91. //-----------------------------------------------------------------------------
  92. void CSculptTool::DetermineKeysDown()
  93. {
  94. m_bCtrlDown = ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
  95. m_bShiftDown = ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) != 0 );
  96. m_bAltDown = ( ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) != 0 );
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose: handles the left mouse button up in the 3d view
  100. // Input : pView - the 3d view
  101. // nFlags - the button flags
  102. // vPoint - the mouse point
  103. // Output : returns true if successful
  104. //-----------------------------------------------------------------------------
  105. bool CSculptTool::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  106. {
  107. DetermineKeysDown();
  108. // left button up
  109. m_bLMBDown = false;
  110. m_MousePoint = vPoint;
  111. return true;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose: handles the left mouse button down in the 3d view
  115. // Input : pView - the 3d view
  116. // nFlags - the button flags
  117. // vPoint - the mouse point
  118. // Output : returns true if successful
  119. //-----------------------------------------------------------------------------
  120. bool CSculptTool::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  121. {
  122. DetermineKeysDown();
  123. // left button down
  124. m_bLMBDown = true;
  125. m_MousePoint = vPoint;
  126. return true;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose: handles the right mouse button up in the 3d view
  130. // Input : pView - the 3d view
  131. // nFlags - the button flags
  132. // vPoint - the mouse point
  133. // Output : returns true if successful
  134. //-----------------------------------------------------------------------------
  135. bool CSculptTool::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  136. {
  137. DetermineKeysDown();
  138. // right button up
  139. m_bRMBDown = false;
  140. m_MousePoint = vPoint;
  141. return true;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: handles the right mouse button down in the 3d view
  145. // Input : pView - the 3d view
  146. // nFlags - the button flags
  147. // vPoint - the mouse point
  148. // Output : returns true if successful
  149. //-----------------------------------------------------------------------------
  150. bool CSculptTool::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  151. {
  152. DetermineKeysDown();
  153. // right button down
  154. m_bRMBDown = true;
  155. m_MousePoint = vPoint;
  156. return true;
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Purpose: handles the mouse move in the 3d view
  160. // Input : pView - the 3d view
  161. // nFlags - the button flags
  162. // vPoint - the mouse point
  163. // Output : returns true if successful
  164. //-----------------------------------------------------------------------------
  165. bool CSculptTool::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  166. {
  167. DetermineKeysDown();
  168. m_MousePoint = vPoint;
  169. return true;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Purpose: called just before painting begins to gather reference information
  173. // Input : pView - the 3d view
  174. // vPoint - the mouse point
  175. // Output : returns true if successful
  176. //-----------------------------------------------------------------------------
  177. bool CSculptTool::PrePaint( CMapView3D *pView, const Vector2D &vPoint )
  178. {
  179. Vector2D RadiusPoint = vPoint;
  180. Vector vecStart, vecEnd;
  181. RadiusPoint.x += m_BrushSize;
  182. pView->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  183. m_OriginalCollisionValid = FindCollisionIntercept( pView->GetCamera(), vPoint, true, m_OriginalCollisionPoint, m_OriginalCollisionNormal, m_OriginalCollisionIntercept );
  184. if ( m_OriginalCollisionValid )
  185. {
  186. m_OriginalProjectedRadius = CalcDistanceToLine( m_OriginalCollisionPoint, vecStart, vecEnd );
  187. }
  188. m_CurrentCollisionValid = FindCollisionIntercept( pView->GetCamera(), vPoint, false, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  189. if ( m_CurrentCollisionValid )
  190. {
  191. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  192. }
  193. m_SpatialData.m_flRadius = 128.0f;
  194. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  195. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  196. return true;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Purpose: called after painting finishes to finalize things
  200. // Input : bAutoSew - should we sew the edges
  201. // Output : returns true if successful
  202. //-----------------------------------------------------------------------------
  203. bool CSculptTool::PostPaint( bool bAutoSew )
  204. {
  205. // Get the displacement manager from the active map document.
  206. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  207. if( !pDispMgr )
  208. return false;
  209. // Update the modified displacements.
  210. int nDispCount = pDispMgr->SelectCount();
  211. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  212. {
  213. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  214. if ( pDisp )
  215. {
  216. pDisp->Paint_Update( false );
  217. }
  218. }
  219. // Auto "sew" if necessary.
  220. if ( bAutoSew )
  221. {
  222. FaceListSewEdges();
  223. }
  224. return true;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Purpose: called to dispatch the painting routine across all selected displacements
  228. // Input : pView - the 3d view
  229. // vPoint - the mouse point
  230. // Output : returns true if successful
  231. //-----------------------------------------------------------------------------
  232. bool CSculptTool::DoPaint( CMapView3D *pView, const Vector2D &vPoint )
  233. {
  234. // Get the displacement manager from the active map document.
  235. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  236. if( !pDispMgr )
  237. return false;
  238. // For each displacement surface is the selection list attempt to paint on it.
  239. int nDispCount = pDispMgr->SelectCount();
  240. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  241. {
  242. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  243. if ( pDisp )
  244. {
  245. CMapDisp *OrigDisp = NULL;
  246. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  247. if ( index != m_OrigMapDisp.InvalidIndex() )
  248. {
  249. OrigDisp = m_OrigMapDisp[ index ];
  250. }
  251. DoPaintOperation( pView, vPoint, pDisp, OrigDisp );
  252. }
  253. }
  254. // Successful paint.
  255. return true;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose: checks to see if a given displacement vert lies within the 2d screenspace of the circle
  259. // Input : pView - the 3d view
  260. // pDisp - the displacement the vert belongs to
  261. // pOrigDisp - the displacement prior to any moving
  262. // nVertIndex - the vert index
  263. // bUseOrigDisplacement - should we use the vert from the original displacement
  264. // bUseCurrentPosition - should we use the current collision test point
  265. // Output : returns true if the point is within the circle
  266. //-----------------------------------------------------------------------------
  267. bool CSculptTool::IsPointInScreenCircle( CMapView3D *pView, CMapDisp *pDisp, CMapDisp *pOrigDisp, int nVertIndex, bool bUseOrigDisplacement, bool bUseCurrentPosition, float *pflLengthPercent )
  268. {
  269. Vector vVert, vTestVert;
  270. pDisp->GetVert( nVertIndex, vVert );
  271. if ( pOrigDisp && bUseOrigDisplacement )
  272. {
  273. pOrigDisp->GetVert( nVertIndex, vTestVert );
  274. }
  275. else
  276. {
  277. vTestVert = vVert;
  278. }
  279. #if 0
  280. Vector2D ViewVert;
  281. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  282. Vector2D Offset = ViewVert - m_MousePoint;
  283. float Length = Offset.Length();
  284. return ( Length <= m_BrushSize );
  285. #else
  286. if ( bUseCurrentPosition )
  287. {
  288. if ( !m_CurrentCollisionValid )
  289. {
  290. return false;
  291. }
  292. Vector Offset = m_CurrentCollisionPoint - vTestVert;
  293. float Length = Offset.Length();
  294. if ( pflLengthPercent )
  295. {
  296. *pflLengthPercent = Length / m_CurrentProjectedRadius;
  297. }
  298. return ( Length <= m_CurrentProjectedRadius );
  299. }
  300. else
  301. {
  302. if ( !m_OriginalCollisionValid )
  303. {
  304. return false;
  305. }
  306. Vector Offset = m_OriginalCollisionPoint - vTestVert;
  307. float Length = Offset.Length();
  308. if ( pflLengthPercent )
  309. {
  310. *pflLengthPercent = Length / m_OriginalProjectedRadius;
  311. }
  312. #if 0
  313. if ( Length <= m_OriginalProjectedRadius || vertIndex == 66 )
  314. {
  315. Msg( "%d: ( %g %g %g ) from %g <= %g at ( %g %g %g )\n", vertIndex, vTestVert.x, vTestVert.y, vTestVert.z, Length, m_OriginalProjectedRadius, m_OriginalCollisionPoint.x, m_OriginalCollisionPoint.y, m_OriginalCollisionPoint.z );
  316. }
  317. #endif
  318. return ( Length <= m_OriginalProjectedRadius );
  319. }
  320. #endif
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose: Adds a displacement to the undo manager
  324. // Input : pDisp - the displacement
  325. //-----------------------------------------------------------------------------
  326. void CSculptTool::AddToUndo( CMapDisp **pDisp )
  327. {
  328. CMapDisp *pUndoDisp = *pDisp;
  329. if ( pUndoDisp->Paint_IsDirty() )
  330. return;
  331. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  332. if( pDispMgr )
  333. {
  334. EditDispHandle_t handle = pUndoDisp->GetEditHandle();
  335. pDispMgr->Undo( handle, false );
  336. *pDisp = EditDispMgr()->GetDisp( handle );
  337. }
  338. }
  339. #if 0
  340. //-----------------------------------------------------------------------------
  341. // Purpose:
  342. // Input :
  343. // Output :
  344. //-----------------------------------------------------------------------------
  345. void CSculptTool::DoPaintEqual( SpatialPaintData_t &spatialData, CMapDisp *pDisp )
  346. {
  347. Vector vPaintPos, vVert, vFlatVert;
  348. float flDistance2;
  349. int nVertCount = pDisp->GetSize();
  350. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  351. {
  352. // Get the current vert.
  353. pDisp->GetVert( iVert, vVert );
  354. if ( IsInSphereRadius( spatialData.m_vCenter, spatialData.m_flRadius2, vVert, flDistance2 ) )
  355. {
  356. // Get the base vert.
  357. pDisp->GetFlatVert( iVert, vFlatVert );
  358. // Build the new position (paint value) and set it.
  359. DoPaintOne( spatialData, vFlatVert, vPaintPos );
  360. AddToUndo( &pDisp );
  361. pDisp->Paint_SetValue( iVert, vPaintPos );
  362. }
  363. }
  364. }
  365. #endif
  366. //-----------------------------------------------------------------------------
  367. // Purpose: this routine does the smoothing operation
  368. // Input : pView - the 3d view
  369. // vPoint - the mouse point
  370. // pDisp - the displacement to smooth
  371. // pOrigDisp - the displacement prior to the paint operation
  372. // Output :
  373. //-----------------------------------------------------------------------------
  374. void CSculptTool::DoPaintSmooth( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  375. {
  376. Vector vPaintPos, vVert;
  377. pDisp->GetSurfNormal( m_SpatialData.m_vPaintAxis );
  378. int nVertCount = pDisp->GetSize();
  379. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  380. {
  381. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false, true ) )
  382. {
  383. // Msg( "Checking Vert %d\n", iVert );
  384. // Get the current vert.
  385. pDisp->GetVert( iVert, vVert );
  386. // Build the new smoothed position and set it.
  387. if ( DoPaintSmoothOneOverExp( vVert, vPaintPos ) )
  388. {
  389. AddToUndo( &pDisp );
  390. pDisp->Paint_SetValue( iVert, vPaintPos );
  391. // Msg( "Vert %d Updated: from %g %g %g to %g %g %g\n", iVert, vVert.x, vVert.y, vVert.z, vPaintPos.x, vPaintPos.y, vPaintPos.z );
  392. }
  393. }
  394. }
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose: checks to see if the paint sphere is within the bounding box
  398. // Input : vCenter - center of the sphere
  399. // flRadius - sphere radius
  400. // vBBoxMin - bounding box mins
  401. // vBBoxMax - bounding box maxs
  402. // Output : returns two if the two intersect
  403. //-----------------------------------------------------------------------------
  404. bool CSculptTool::PaintSphereDispBBoxOverlap( const Vector &vCenter, float flRadius, const Vector &vBBoxMin, const Vector &vBBoxMax )
  405. {
  406. return IsBoxIntersectingSphere( vBBoxMin, vBBoxMax, vCenter, flRadius );
  407. }
  408. //-----------------------------------------------------------------------------
  409. // Purpose: checkes to see if the two spheres intersect
  410. // Input : vCenter - center of the sphere
  411. // flRadius2 - sphere radius squared
  412. // vPos - point to test
  413. // flDistance2 - radius of point
  414. // Output : returns true if the two spheres intersect
  415. //-----------------------------------------------------------------------------
  416. bool CSculptTool::IsInSphereRadius( const Vector &vCenter, float flRadius2, const Vector &vPos, float &flDistance2 )
  417. {
  418. Vector vTmp;
  419. VectorSubtract( vPos, vCenter, vTmp );
  420. flDistance2 = ( vTmp.x * vTmp.x ) + ( vTmp.y * vTmp.y ) + ( vTmp.z * vTmp.z );
  421. return ( flDistance2 < flRadius2 );
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Purpose: calculates the smoothing radius squared
  425. // Input : vPoint - the point to be smoothed
  426. // Output : returns the smoothing radius squared
  427. //-----------------------------------------------------------------------------
  428. float CSculptTool::CalcSmoothRadius2( const Vector &vPoint )
  429. {
  430. Vector vTmp;
  431. VectorSubtract( m_SpatialData.m_vCenter, vPoint, vTmp );
  432. float flDistance2 = ( vTmp.x * vTmp.x ) + ( vTmp.y * vTmp.y ) + ( vTmp.z * vTmp.z );
  433. float flRatio = flDistance2 / m_SpatialData.m_flRadius2;
  434. flRatio = 1.0f - flRatio;
  435. float flRadius = flRatio * m_SpatialData.m_flRadius;
  436. return ( flRadius * flRadius );
  437. }
  438. //-----------------------------------------------------------------------------
  439. // Purpose: smooths all displacements
  440. // Input : vNewCenter - calculate the smoothing center
  441. // Output : returns true if successful
  442. // vPaintPos - the new smoothing position
  443. //-----------------------------------------------------------------------------
  444. bool CSculptTool::DoPaintSmoothOneOverExp( const Vector &vNewCenter, Vector &vPaintPos )
  445. {
  446. // Get the displacement manager from the active map document.
  447. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  448. if( !pDispMgr )
  449. return false;
  450. // Calculate the smoothing radius.
  451. float flNewRadius2 = CalcSmoothRadius2( vNewCenter );
  452. flNewRadius2 *= 2.0f;
  453. float flNewRadius = ( float )sqrt( flNewRadius2 );
  454. // Test all selected surfaces for smoothing.
  455. float flWeight = 0.0f;
  456. float flSmoothDist = 0.0f;
  457. // Calculate the plane dist.
  458. float flPaintDist = m_SpatialData.m_vPaintAxis.Dot( vNewCenter );
  459. int nDispCount = pDispMgr->SelectCount();
  460. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  461. {
  462. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  463. if ( pDisp )
  464. {
  465. // Test paint sphere displacement bbox for overlap.
  466. Vector vBBoxMin, vBBoxMax;
  467. pDisp->GetBoundingBox( vBBoxMin, vBBoxMax );
  468. if ( PaintSphereDispBBoxOverlap( vNewCenter, flNewRadius, vBBoxMin, vBBoxMax ) )
  469. {
  470. Vector vVert;
  471. int nVertCount = pDisp->GetSize();
  472. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  473. {
  474. // Get the current vert.
  475. pDisp->GetVert( iVert, vVert );
  476. float flDistance2 = 0.0f;
  477. if ( IsInSphereRadius( vNewCenter, flNewRadius2, vVert, flDistance2 ) )
  478. {
  479. float flRatio = flDistance2 / flNewRadius2;
  480. float flFactor = 1.0f / exp( flRatio );
  481. if ( flFactor != 1.0f )
  482. {
  483. flFactor *= 1.0f / ( m_SpatialData.m_flScalar * 2.0f );
  484. }
  485. Vector vProjectVert;
  486. float flProjectDist = DotProduct( vVert, m_SpatialData.m_vPaintAxis ) - flPaintDist;
  487. flSmoothDist += ( flProjectDist * flFactor );
  488. flWeight += flFactor;
  489. // Msg( "Factoring %d: %g %g %g at %g\n", iVert, vVert.x, vVert.y, vVert.z, flNewRadius2 );
  490. }
  491. }
  492. }
  493. }
  494. }
  495. if ( flWeight == 0.0f )
  496. {
  497. return false;
  498. }
  499. // Re-normalize the smoothing position.
  500. flSmoothDist /= flWeight;
  501. vPaintPos = vNewCenter + ( m_SpatialData.m_vPaintAxis * flSmoothDist );
  502. return true;
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Purpose: gets the starting position when the paint operation begins
  506. // Input : pView - the 3d view
  507. // vPoint - the mouse point
  508. // Output : returns the starting position
  509. //-----------------------------------------------------------------------------
  510. bool CSculptTool::GetStartingSpot( CMapView3D *pView, const Vector2D &vPoint )
  511. {
  512. m_ValidPaintingSpot = FindCollisionIntercept( pView->GetCamera(), vPoint, false, m_StartingCollisionPoint, m_StartingCollisionNormal, m_StartingCollisionIntercept );
  513. if ( m_ValidPaintingSpot )
  514. {
  515. Vector2D RadiusPoint = vPoint;
  516. Vector vecStart, vecEnd;
  517. RadiusPoint.x += m_BrushSize;
  518. pView->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  519. m_StartingProjectedRadius = CalcDistanceToLine( m_StartingCollisionPoint, vecStart, vecEnd );
  520. }
  521. return m_ValidPaintingSpot;
  522. }
  523. //-----------------------------------------------------------------------------
  524. // Purpose: Draws a 2d line to represent the direction
  525. // Input : pRender - the renderer
  526. // Direction - direction / normal
  527. // Towards - the color to be used if the direction is towards the viewer
  528. // Away - the color to be used if the direction is away from the view
  529. //-----------------------------------------------------------------------------
  530. void CSculptTool::DrawDirection( CRender3D *pRender, Vector Direction, Color Towards, Color Away )
  531. {
  532. Vector ViewPoint, ViewDir;
  533. Vector2D ViewVert;
  534. VMatrix Matrix;
  535. pRender->GetCamera()->GetViewProjMatrix( Matrix );
  536. Matrix.SetTranslation( Vector( 0.0f, 0.0f, 0.0f ) );
  537. Vector3DMultiply( Matrix, Direction, ViewDir );
  538. VectorNormalize( ViewDir );
  539. ViewVert = m_MousePoint + ( Vector2D( ViewDir.x, -ViewDir.y ) * m_BrushSize );
  540. if ( ViewDir.z > 0.0f )
  541. {
  542. pRender->SetDrawColor( Away.r(), Away.g(), Away.b() );
  543. }
  544. else
  545. {
  546. pRender->SetDrawColor( Towards.r(), Towards.g(), Towards.b() );
  547. }
  548. bool bPopMode = pRender->BeginClientSpace();
  549. pRender->DrawLine( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( ViewVert.x, ViewVert.y, 0.0f ) );
  550. if ( bPopMode )
  551. {
  552. pRender->EndClientSpace();
  553. }
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Purpose: this function will copy all the selected displacements
  557. //-----------------------------------------------------------------------------
  558. void CSculptTool::DuplicateSelectedDisp( )
  559. {
  560. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  561. if( !pDispMgr )
  562. {
  563. return;
  564. }
  565. FOR_EACH_MAP( m_OrigMapDisp, pos )
  566. {
  567. delete m_OrigMapDisp.Element( pos );
  568. }
  569. m_OrigMapDisp.Purge();
  570. int nDispCount = pDispMgr->SelectCount();
  571. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  572. {
  573. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  574. if ( pDisp )
  575. {
  576. CMapDisp *pCopy = new CMapDisp();
  577. pCopy->CopyFrom( pDisp, false );
  578. m_OrigMapDisp.Insert( pDisp->GetEditHandle(), pCopy );
  579. }
  580. }
  581. }
  582. //-----------------------------------------------------------------------------
  583. // Purpose: this function will initialize all selected displacements for updating
  584. //-----------------------------------------------------------------------------
  585. void CSculptTool::PrepareDispForPainting( )
  586. {
  587. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  588. if( !pDispMgr )
  589. {
  590. return;
  591. }
  592. int nDispCount = pDispMgr->SelectCount();
  593. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  594. {
  595. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  596. if ( pDisp )
  597. {
  598. pDisp->Paint_Init( DISPPAINT_CHANNEL_POSITION );
  599. }
  600. }
  601. }
  602. //-----------------------------------------------------------------------------
  603. // Purpose: this function will find the collision location within the selected displacements
  604. // Input : pCamera - the camera
  605. // vPoint - the 2d point on screen
  606. // bUseOrigPosition - should we use the original displacements prior to updating
  607. // Output : returns true if the point intercepted one of the selected displacements
  608. // vCollisionPoint the 3d interception point
  609. // vCollisionNormal - the normal of the tri hit
  610. // flCollisionIntercept - the intercept
  611. //-----------------------------------------------------------------------------
  612. bool CSculptTool::FindCollisionIntercept( CCamera *pCamera, const Vector2D &vPoint, bool bUseOrigPosition, Vector &vCollisionPoint, Vector &vCollisionNormal, float &flCollisionIntercept,
  613. int *pnCollideDisplacement, int *pnCollideTri )
  614. {
  615. Vector vecStart, vecEnd;
  616. float flFraction, flLeastFraction;
  617. flLeastFraction = -1.0f;
  618. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  619. if( !pDispMgr )
  620. {
  621. return false;
  622. }
  623. int nDispCount = pDispMgr->SelectCount();
  624. pCamera->BuildRay( vPoint, vecStart, vecEnd );
  625. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  626. {
  627. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  628. if ( pDisp )
  629. {
  630. if ( bUseOrigPosition )
  631. {
  632. CMapDisp *OrigDisp = NULL;
  633. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  634. if ( index != m_OrigMapDisp.InvalidIndex() )
  635. {
  636. OrigDisp = m_OrigMapDisp[ index ];
  637. }
  638. if ( OrigDisp )
  639. {
  640. pDisp = OrigDisp;
  641. }
  642. }
  643. int iTri = pDisp->CollideWithDispTri( vecStart, vecEnd, flFraction, false );
  644. if ( iTri != -1 && ( flLeastFraction == -1.0f || flFraction < flLeastFraction ) )
  645. {
  646. flLeastFraction = flFraction;
  647. vCollisionPoint = vecStart + ( ( vecEnd - vecStart ) * flFraction );
  648. unsigned short v1, v2, v3;
  649. Vector vec1, vec2, vec3;
  650. pDisp->GetTriIndices( iTri, v1, v2, v3 );
  651. pDisp->GetVert( v1, vec1 );
  652. pDisp->GetVert( v2, vec2 );
  653. pDisp->GetVert( v3, vec3 );
  654. ComputeTrianglePlane( vec1, vec2, vec3, vCollisionNormal, flCollisionIntercept );
  655. if ( pnCollideDisplacement != NULL )
  656. {
  657. *pnCollideDisplacement = iDisp;
  658. }
  659. if ( pnCollideTri != NULL )
  660. {
  661. *pnCollideTri = iTri;
  662. }
  663. }
  664. }
  665. }
  666. return ( flLeastFraction != -1.0f );
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Purpose: constructor
  670. //-----------------------------------------------------------------------------
  671. CSculptPainter::CSculptPainter() :
  672. CSculptTool()
  673. {
  674. m_InSizingMode = m_InPaintingMode = false;
  675. m_OrigBrushSize = m_BrushSize;
  676. }
  677. //-----------------------------------------------------------------------------
  678. // Purpose: destructor
  679. //-----------------------------------------------------------------------------
  680. CSculptPainter::~CSculptPainter( )
  681. {
  682. }
  683. //-----------------------------------------------------------------------------
  684. // Purpose: setup for starting to paint on the displacement
  685. // Input : pView - the 3d view
  686. // vPoint - the initial click point
  687. // Output : returns true if successful
  688. //-----------------------------------------------------------------------------
  689. bool CSculptPainter::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  690. {
  691. CSculptTool::BeginPaint( pView, vPoint );
  692. PrepareDispForPainting();
  693. return true;
  694. }
  695. //-----------------------------------------------------------------------------
  696. // Purpose: main routine called when mouse move has happened to start painting
  697. // Input : pView - the 3d view
  698. // vPoint - the mouse point
  699. // SpatialData - the spatial data ( mostly ignored )
  700. // Output : returns true if successful
  701. //-----------------------------------------------------------------------------
  702. bool CSculptPainter::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &SpatialData )
  703. {
  704. __super::Paint( pView, vPoint, SpatialData );
  705. if ( m_bRMBDown )
  706. {
  707. if ( !m_bAltDown )
  708. {
  709. DoSizing( vPoint );
  710. }
  711. }
  712. else if ( m_bLMBDown )
  713. {
  714. if ( !m_ValidPaintingSpot )
  715. {
  716. if ( !GetStartingSpot( pView, vPoint ) )
  717. {
  718. return false;
  719. }
  720. }
  721. // Setup painting.
  722. if ( !PrePaint( pView, vPoint ) )
  723. {
  724. return false;
  725. }
  726. // Handle painting.
  727. if ( !DoPaint( pView, vPoint ) )
  728. {
  729. return false;
  730. }
  731. // Finish painting.
  732. if ( !PostPaint( m_PaintOwner->GetAutoSew() ) )
  733. {
  734. return false;
  735. }
  736. }
  737. // Successful paint operation.
  738. return true;
  739. }
  740. //-----------------------------------------------------------------------------
  741. // Purpose: handles the left mouse button up in the 3d view
  742. // Input : pView - the 3d view
  743. // nFlags - the button flags
  744. // vPoint - the mouse point
  745. // Output : returns true if successful
  746. //-----------------------------------------------------------------------------
  747. bool CSculptPainter::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  748. {
  749. CSculptTool::OnLMouseUp3D( pView, nFlags, vPoint );
  750. m_InPaintingMode = false;
  751. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  752. if( pDispMgr )
  753. {
  754. pDispMgr->PostUndo();
  755. }
  756. return true;
  757. }
  758. //-----------------------------------------------------------------------------
  759. // Purpose: handles the left mouse button down in the 3d view
  760. // Input : pView - the 3d view
  761. // nFlags - the button flags
  762. // vPoint - the mouse point
  763. // Output : returns true if successful
  764. //-----------------------------------------------------------------------------
  765. bool CSculptPainter::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  766. {
  767. CSculptTool::OnLMouseDown3D( pView, nFlags, vPoint );
  768. m_InPaintingMode = true;
  769. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  770. if( pDispMgr )
  771. {
  772. pDispMgr->PreUndo( "Displacement Modifier" );
  773. }
  774. return true;
  775. }
  776. //-----------------------------------------------------------------------------
  777. // Purpose: handles the right mouse button up in the 3d view
  778. // Input : pView - the 3d view
  779. // nFlags - the button flags
  780. // vPoint - the mouse point
  781. // Output : returns true if successful
  782. //-----------------------------------------------------------------------------
  783. bool CSculptPainter::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  784. {
  785. CSculptTool::OnRMouseUp3D( pView, nFlags, vPoint );
  786. m_InSizingMode = false;
  787. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  788. if( pDispMgr )
  789. {
  790. pDispMgr->PostUndo();
  791. }
  792. return true;
  793. }
  794. //-----------------------------------------------------------------------------
  795. // Purpose: handles the right mouse button down in the 3d view
  796. // Input : pView - the 3d view
  797. // nFlags - the button flags
  798. // vPoint - the mouse point
  799. // Output : returns true if successful
  800. //-----------------------------------------------------------------------------
  801. bool CSculptPainter::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  802. {
  803. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  804. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  805. if( pDispMgr )
  806. {
  807. pDispMgr->PreUndo( "Displacement Modifier" );
  808. }
  809. return true;
  810. }
  811. //-----------------------------------------------------------------------------
  812. // Purpose: handles the mouse move in the 3d view
  813. // Input : pView - the 3d view
  814. // nFlags - the button flags
  815. // vPoint - the mouse point
  816. // Output : returns true if successful
  817. //-----------------------------------------------------------------------------
  818. bool CSculptPainter::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  819. {
  820. return CSculptTool::OnMouseMove3D( pView, nFlags, vPoint );
  821. }
  822. //-----------------------------------------------------------------------------
  823. // Purpose: toggles the sizing mode
  824. // Input : vPoint - the mouse point
  825. // Output : returns true if successful
  826. //-----------------------------------------------------------------------------
  827. bool CSculptPainter::DoSizing( const Vector2D &vPoint )
  828. {
  829. if ( !m_InSizingMode )
  830. {
  831. m_InSizingMode = true;
  832. m_StartSizingPoint = vPoint;
  833. m_OrigBrushSize = m_BrushSize;
  834. }
  835. else
  836. {
  837. m_BrushSize = m_OrigBrushSize + ( vPoint.x - m_StartSizingPoint.x );
  838. if ( m_BrushSize < 1.0f )
  839. {
  840. m_BrushSize = 1.0f;
  841. }
  842. }
  843. return true;
  844. }
  845. // CSculptPushOptions dialog
  846. IMPLEMENT_DYNAMIC(CSculptPushOptions, CDialog)
  847. //-----------------------------------------------------------------------------
  848. // Purpose: constructor
  849. //-----------------------------------------------------------------------------
  850. CSculptPushOptions::CSculptPushOptions(CWnd* pParent /*=NULL*/) :
  851. CDialog(CSculptPushOptions::IDD, pParent),
  852. CSculptPainter()
  853. {
  854. m_OffsetMode = OFFSET_MODE_ABSOLUTE;
  855. m_NormalMode = NORMAL_MODE_Z;
  856. m_DensityMode = DENSITY_MODE_ADDITIVE;
  857. m_OffsetDistance = 10.0f;
  858. m_OffsetAmount = 1.0f;
  859. m_SmoothAmount = 0.2f;
  860. m_Direction = 1.0f;
  861. m_SelectedNormal.Init( 0.0f, 0.0f, 0.0f );
  862. m_flFalloffSpot = 0.5f;
  863. m_flFalloffEndingValue = 0.0f;
  864. }
  865. //-----------------------------------------------------------------------------
  866. // Purpose: destructor
  867. //-----------------------------------------------------------------------------
  868. CSculptPushOptions::~CSculptPushOptions()
  869. {
  870. }
  871. //-----------------------------------------------------------------------------
  872. // Purpose: initializes the dialog
  873. // Output : returns true if successful
  874. //-----------------------------------------------------------------------------
  875. BOOL CSculptPushOptions::OnInitDialog( void )
  876. {
  877. char temp[ 1024 ];
  878. CDialog::OnInitDialog();
  879. m_OffsetModeControl.InsertString( -1, "Adaptive" );
  880. m_OffsetModeControl.InsertString( -1, "Absolute" );
  881. m_OffsetModeControl.SetCurSel( m_OffsetMode );
  882. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  883. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  884. sprintf( temp, "%g", m_OffsetDistance );
  885. m_OffsetDistanceControl.SetWindowText( temp );
  886. sprintf( temp, "%g%%", m_OffsetAmount * 100.0f );
  887. m_OffsetAmountControl.SetWindowText( temp );
  888. sprintf( temp, "%g%%", m_SmoothAmount * 100.0f );
  889. m_SmoothAmountControl.SetWindowText( temp );
  890. sprintf( temp, "%g%%", m_flFalloffSpot * 100.0f );
  891. m_FalloffPositionControl.SetWindowText( temp );
  892. sprintf( temp, "%g%%", m_flFalloffEndingValue * 100.0f );
  893. m_FalloffFinalControl.SetWindowText( temp );
  894. m_NormalModeControl.InsertString( -1, "Brush Center" );
  895. m_NormalModeControl.InsertString( -1, "Screen" );
  896. m_NormalModeControl.InsertString( -1, "X" );
  897. m_NormalModeControl.InsertString( -1, "Y" );
  898. m_NormalModeControl.InsertString( -1, "Z" );
  899. m_NormalModeControl.InsertString( -1, "Selected" );
  900. m_NormalModeControl.SetCurSel( m_NormalMode );
  901. m_DensityModeControl.InsertString( -1, "Additive" );
  902. m_DensityModeControl.InsertString( -1, "Attenuated" );
  903. m_DensityModeControl.SetCurSel( m_DensityMode );
  904. return TRUE;
  905. }
  906. //-----------------------------------------------------------------------------
  907. // Purpose: prevent the dialog from closing
  908. //-----------------------------------------------------------------------------
  909. void CSculptPushOptions::OnOK()
  910. {
  911. }
  912. //-----------------------------------------------------------------------------
  913. // Purpose: prevent the dialog from closing
  914. //-----------------------------------------------------------------------------
  915. void CSculptPushOptions::OnCancel()
  916. {
  917. }
  918. //-----------------------------------------------------------------------------
  919. // Purpose: set up the data exchange for the variables
  920. // Input : pDX - the data exchange object
  921. //-----------------------------------------------------------------------------
  922. void CSculptPushOptions::DoDataExchange(CDataExchange* pDX)
  923. {
  924. CDialog::DoDataExchange(pDX);
  925. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, m_OffsetModeControl);
  926. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, m_OffsetDistanceControl);
  927. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, m_OffsetAmountControl);
  928. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, m_SmoothAmountControl);
  929. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, m_DensityModeControl);
  930. DDX_Control(pDX, IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, m_NormalModeControl);
  931. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_POSITION, m_FalloffPositionControl);
  932. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_FINAL, m_FalloffFinalControl);
  933. }
  934. BEGIN_MESSAGE_MAP(CSculptPushOptions, CDialog)
  935. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, &CSculptPushOptions::OnCbnSelchangeSculptPushOptionOffsetMode)
  936. ON_EN_CHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, &CSculptPushOptions::OnEnChangeSculptPushOptionOffsetDistance)
  937. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, &CSculptPushOptions::OnCbnSelchangeSculptPushOptionDensityMode)
  938. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, &CSculptPushOptions::OnEnKillfocusSculptPushOptionSmoothAmount)
  939. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, &CSculptPushOptions::OnEnKillfocusSculptPushOptionOffsetAmount)
  940. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_FALLOFF_POSITION, &CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffPosition)
  941. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_FALLOFF_FINAL, &CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffFinal)
  942. END_MESSAGE_MAP()
  943. //-----------------------------------------------------------------------------
  944. // Purpose: sets the offset mode of the sculpt operation
  945. //-----------------------------------------------------------------------------
  946. void CSculptPushOptions::OnCbnSelchangeSculptPushOptionOffsetMode()
  947. {
  948. m_OffsetMode = ( OffsetMode )m_OffsetModeControl.GetCurSel();
  949. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  950. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  951. }
  952. //-----------------------------------------------------------------------------
  953. // Purpose: setup for starting to paint on the displacement
  954. // Input : pView - the 3d view
  955. // vPoint - the initial click point
  956. // Output : returns true if successful
  957. //-----------------------------------------------------------------------------
  958. bool CSculptPushOptions::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  959. {
  960. __super::BeginPaint( pView, vPoint );
  961. if ( m_bCtrlDown )
  962. {
  963. m_Direction = -1.0f;
  964. }
  965. else
  966. {
  967. m_Direction = 1.0f;
  968. }
  969. return true;
  970. }
  971. //-----------------------------------------------------------------------------
  972. // Purpose: draws the tool in the 3d view
  973. // Input : pRender - the 3d renderer
  974. //-----------------------------------------------------------------------------
  975. void CSculptPushOptions::RenderTool3D( CRender3D *pRender )
  976. {
  977. // pRender->DrawText( "mouse", m_MousePoint.x, m_MousePoint.y, 0 );
  978. // Msg( "%g %g\n", m_MousePoint.x, m_MousePoint.y );
  979. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  980. if ( m_InSizingMode )
  981. { // yellow for sizing mode
  982. pRender->BeginClientSpace();
  983. pRender->SetDrawColor( 255, 255, 0 );
  984. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  985. if ( m_flFalloffSpot > 0.0f )
  986. {
  987. pRender->SetDrawColor( 192, 192, 0 );
  988. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  989. }
  990. pRender->EndClientSpace();
  991. }
  992. else if ( m_bShiftDown )
  993. { // purple for smoothing
  994. pRender->SetDrawColor( 255, 0, 255 );
  995. pRender->BeginClientSpace();
  996. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  997. pRender->EndClientSpace();
  998. }
  999. else if ( m_bCtrlDown )
  1000. { // red for negative sculpting
  1001. pRender->BeginClientSpace();
  1002. pRender->SetDrawColor( 255, 0, 0 );
  1003. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  1004. if ( m_flFalloffSpot > 0.0f )
  1005. {
  1006. pRender->SetDrawColor( 192, 0, 0 );
  1007. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  1008. }
  1009. pRender->EndClientSpace();
  1010. Vector vPaintAxis;
  1011. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  1012. DrawDirection( pRender, -vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  1013. }
  1014. else
  1015. { // green for positive sculpting
  1016. pRender->BeginClientSpace();
  1017. pRender->SetDrawColor( 0, 255, 0 );
  1018. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  1019. if ( m_flFalloffSpot > 0.0f )
  1020. {
  1021. pRender->SetDrawColor( 0, 192, 0 );
  1022. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  1023. }
  1024. pRender->EndClientSpace();
  1025. Vector vPaintAxis;
  1026. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  1027. DrawDirection( pRender, vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  1028. }
  1029. #if 0
  1030. FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  1031. Vector2D RadiusPoint = m_MousePoint;
  1032. Vector vecStart, vecEnd;
  1033. RadiusPoint.x += m_BrushSize;
  1034. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  1035. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  1036. pRender->RenderWireframeSphere( m_CurrentCollisionPoint, m_CurrentProjectedRadius, 12, 12, 0, 255, 255 );
  1037. #endif
  1038. #if 0
  1039. // Get the displacement manager from the active map document.
  1040. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  1041. // For each displacement surface is the selection list attempt to paint on it.
  1042. int nDispCount = pDispMgr->SelectCount();
  1043. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  1044. {
  1045. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  1046. if ( pDisp )
  1047. {
  1048. CMapDisp *OrigDisp = NULL;
  1049. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  1050. if ( index != m_OrigMapDisp.InvalidIndex() )
  1051. {
  1052. OrigDisp = m_OrigMapDisp[ index ];
  1053. }
  1054. Vector vPaintPos, vVert;
  1055. int nVertCount = pDisp->GetSize();
  1056. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  1057. {
  1058. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false ) )
  1059. {
  1060. // Get the current vert.
  1061. pDisp->GetVert( iVert, vVert );
  1062. }
  1063. }
  1064. }
  1065. }
  1066. #endif
  1067. pRender->PopRenderMode();
  1068. #if 0
  1069. if ( !FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept ) )
  1070. {
  1071. return;
  1072. }
  1073. Vector2D RadiusPoint = m_MousePoint;
  1074. Vector vecStart, vecEnd;
  1075. RadiusPoint.x += m_BrushSize;
  1076. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  1077. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  1078. Msg( "Dist = %g at %g,%g,%g\n", m_CurrentProjectedRadius, m_CurrentCollisionPoint.x, m_CurrentCollisionPoint.y, m_CurrentCollisionPoint.z );
  1079. #endif
  1080. }
  1081. //-----------------------------------------------------------------------------
  1082. // Purpose: handles the right mouse button down in the 3d view
  1083. // Input : pView - the 3d view
  1084. // nFlags - the button flags
  1085. // vPoint - the mouse point
  1086. // Output : returns true if successful
  1087. //-----------------------------------------------------------------------------
  1088. bool CSculptPushOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  1089. {
  1090. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  1091. if ( m_bAltDown )
  1092. {
  1093. m_NormalMode = NORMAL_MODE_Z;
  1094. m_NormalModeControl.SetCurSel( m_NormalMode );
  1095. #if 0
  1096. //
  1097. // check for closest solid object
  1098. //
  1099. ULONG ulFace;
  1100. CMapClass *pObject;
  1101. if( ( ( pObject = pView->NearestObjectAt( vPoint, ulFace ) ) != NULL ) )
  1102. {
  1103. if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) )
  1104. {
  1105. // get the solid
  1106. CMapSolid *pSolid = ( CMapSolid* )pObject;
  1107. if( !pSolid )
  1108. {
  1109. return true;
  1110. }
  1111. // trace a line and get the normal -- will get a displacement normal
  1112. // if one exists
  1113. CMapFace *pFace = pSolid->GetFace( ulFace );
  1114. if( !pFace )
  1115. {
  1116. return true;
  1117. }
  1118. Vector vRayStart, vRayEnd;
  1119. pView->GetCamera()->BuildRay( vPoint, vRayStart, vRayEnd );
  1120. Vector vHitPos, vHitNormal;
  1121. if( pFace->TraceLine( vHitPos, vHitNormal, vRayStart, vRayEnd ) )
  1122. {
  1123. // set the paint direction
  1124. m_SelectedNormal = vHitNormal;
  1125. m_NormalMode = NORMAL_MODE_SELECTED;
  1126. m_NormalModeControl.SetCurSel( m_NormalMode );
  1127. }
  1128. }
  1129. }
  1130. #else
  1131. Vector CollisionPoint, CollisionNormal;
  1132. float CollisionIntercept;
  1133. if ( FindCollisionIntercept( pView->GetCamera(), vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept ) )
  1134. {
  1135. // set the paint direction
  1136. m_SelectedNormal = -CollisionNormal;
  1137. m_NormalMode = NORMAL_MODE_SELECTED;
  1138. m_NormalModeControl.SetCurSel( m_NormalMode );
  1139. }
  1140. #endif
  1141. }
  1142. return true;
  1143. }
  1144. //-----------------------------------------------------------------------------
  1145. // Purpose: returns the painting direction
  1146. // Input : pCamera - the 3d camera
  1147. // vPoint - the 2d mouse point
  1148. // Output : vPaintAxis - the direction the painting should go
  1149. //-----------------------------------------------------------------------------
  1150. void CSculptPushOptions::GetPaintAxis( CCamera *pCamera, const Vector2D &vPoint, Vector &vPaintAxis )
  1151. {
  1152. switch( m_NormalMode )
  1153. {
  1154. case NORMAL_MODE_SCREEN:
  1155. pCamera->GetViewForward( vPaintAxis );
  1156. vPaintAxis = -vPaintAxis;
  1157. break;
  1158. case NORMAL_MODE_BRUSH_CENTER:
  1159. if ( !m_InPaintingMode )
  1160. {
  1161. Vector CollisionPoint, CollisionNormal;
  1162. float CollisionIntercept;
  1163. FindCollisionIntercept( pCamera, vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept );
  1164. vPaintAxis = -CollisionNormal;
  1165. }
  1166. else
  1167. {
  1168. vPaintAxis = -m_StartingCollisionNormal;
  1169. }
  1170. break;
  1171. case NORMAL_MODE_X:
  1172. vPaintAxis.Init( 1.0f, 0.0f, 0.0f );
  1173. break;
  1174. case NORMAL_MODE_Y:
  1175. vPaintAxis.Init( 0.0f, 1.0f, 0.0f );
  1176. break;
  1177. case NORMAL_MODE_Z:
  1178. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  1179. break;
  1180. case NORMAL_MODE_SELECTED:
  1181. vPaintAxis = m_SelectedNormal;
  1182. break;
  1183. default:
  1184. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  1185. }
  1186. }
  1187. //-----------------------------------------------------------------------------
  1188. // Purpose: applies the specific push operation onto the displacement
  1189. // Input : pView - the 3d view
  1190. // vPoint - the mouse point
  1191. // pDisp - the displacement to apply the push to
  1192. // pOrigDisp - the original displacement prior to any adjustments
  1193. //-----------------------------------------------------------------------------
  1194. void CSculptPushOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  1195. {
  1196. Vector vPaintPos, vVert, vDirection;
  1197. float flMaxDistance = 0.0f;
  1198. float flDistance;
  1199. float flLengthPercent;
  1200. Vector vPaintAxis;
  1201. if ( m_bShiftDown )
  1202. {
  1203. // DoSmoothOperation( pView, vPoint, pDisp, pOrigDisp );
  1204. // m_SpatialData.m_flRadius = 256.0f;
  1205. // m_SpatialData.m_flScalar = 5.0f / m_SmoothAmount;
  1206. // m_SpatialData.m_flRadius = m_StartingProjectedRadius * 1.5f;
  1207. m_SpatialData.m_flRadius = m_CurrentProjectedRadius * 2.0f;
  1208. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  1209. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  1210. m_SpatialData.m_flScalar = 10.0f / m_SmoothAmount;
  1211. m_SpatialData.m_vCenter = m_CurrentCollisionPoint;
  1212. DoPaintSmooth( pView, vPoint, pDisp, pOrigDisp );
  1213. return;
  1214. }
  1215. GetPaintAxis( pView->GetCamera(), vPoint, vPaintAxis );
  1216. vDirection = vPaintAxis * m_Direction;
  1217. switch( m_OffsetMode )
  1218. {
  1219. case OFFSET_MODE_ADAPTIVE:
  1220. flMaxDistance = m_StartingProjectedRadius * m_OffsetAmount;
  1221. break;
  1222. case OFFSET_MODE_ABSOLUTE:
  1223. flMaxDistance = m_OffsetDistance;
  1224. break;
  1225. }
  1226. int nVertCount = pDisp->GetSize();
  1227. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  1228. {
  1229. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, true, false, &flLengthPercent ) )
  1230. {
  1231. pDisp->GetVert( iVert, vVert );
  1232. if ( flLengthPercent > m_flFalloffSpot )
  1233. {
  1234. flLengthPercent = ( flLengthPercent - m_flFalloffSpot ) / ( 1.0f - m_flFalloffSpot );
  1235. flLengthPercent = 1.0 - flLengthPercent;
  1236. flDistance = ( ( 1.0f - m_flFalloffEndingValue ) * flLengthPercent * flMaxDistance ) + ( m_flFalloffEndingValue * flMaxDistance );
  1237. }
  1238. else
  1239. {
  1240. flDistance = flMaxDistance;
  1241. }
  1242. if ( flDistance == 0.0f )
  1243. {
  1244. continue;
  1245. }
  1246. switch( m_DensityMode )
  1247. {
  1248. case DENSITY_MODE_ADDITIVE:
  1249. VectorScale( vDirection, flDistance, vPaintPos );
  1250. VectorAdd( vPaintPos, vVert, vPaintPos );
  1251. break;
  1252. case DENSITY_MODE_ATTENUATED:
  1253. VectorScale( vDirection, flDistance, vPaintPos );
  1254. VectorAdd( vPaintPos, vVert, vPaintPos );
  1255. if ( pOrigDisp )
  1256. {
  1257. Vector vOrigVert, vDiff;
  1258. float Length;
  1259. pOrigDisp->GetVert( iVert, vOrigVert );
  1260. vDiff = ( vPaintPos - vOrigVert );
  1261. Length = vDiff.Length() / flMaxDistance;
  1262. if ( Length > 1.0f )
  1263. {
  1264. Length = 1.0f;
  1265. }
  1266. vPaintPos = vOrigVert + ( Length * vDirection * flMaxDistance );
  1267. }
  1268. break;
  1269. }
  1270. AddToUndo( &pDisp );
  1271. pDisp->Paint_SetValue( iVert, vPaintPos );
  1272. }
  1273. }
  1274. }
  1275. #if 0
  1276. typedef enum
  1277. {
  1278. DISP_DIR_LEFT_TO_RIGHT = 0, // adjoining displacement is to the left
  1279. DISP_DIR_TOP_TO_BOTTOM = 1, // adjoining displacement is to the top
  1280. DISP_DIR_RIGHT_TO_LEFT = 2, // adjoining displacement is to the right
  1281. DISP_DIR_BOTTOM_TO_TOP = 3, // adjoining displacement is to the bottom
  1282. } DispDirections;
  1283. typedef enum
  1284. {
  1285. MOVE_DIR_RIGHT = 0,
  1286. MOVE_DIR_UP,
  1287. MOVE_DIR_LEFT,
  1288. MOVE_DIR_DOWN,
  1289. MOVE_DIR_MAX
  1290. } MoveDirections;
  1291. class CDispGrid
  1292. {
  1293. public:
  1294. CDispGrid( CMapDisp *pDisp, bool DoPopulate = false, int GridExpand = 2 );
  1295. ~CDispGrid( );
  1296. void Populate( CMapDisp *pDisp );
  1297. bool GetPosition( int x, int y, int OffsetX, int OffsetY, Vector &Position );
  1298. bool GetFlatPosition( int x, int y, int OffsetX, int OffsetY, Vector &FlatPosition );
  1299. void SetPosition( int x, int y, Vector &NewPosition );
  1300. void UpdatePositions( void );
  1301. void CalcSpringForce( int x, int y, int OffsetX, int OffsetY, float Ks, Vector &SpringForce );
  1302. private:
  1303. typedef struct SDispPoint
  1304. {
  1305. bool m_IsSet;
  1306. int m_DispPos;
  1307. Vector m_Position, m_UpdatePosition;
  1308. Vector m_FlatPosition;
  1309. } TDispPoint;
  1310. int m_Width, m_Height;
  1311. int m_GridWidth, m_GridHeight;
  1312. int m_GridExpand;
  1313. TDispPoint *m_Grid;
  1314. void PopulateUp( CMapDisp *pDisp );
  1315. void PopulateDown( CMapDisp *pDisp );
  1316. void PopulateRight( CMapDisp *pDisp );
  1317. void PopulateLeft( CMapDisp *pDisp );
  1318. };
  1319. CDispGrid::CDispGrid( CMapDisp *pDisp, bool DoPopulate, int GridExpand )
  1320. {
  1321. m_GridExpand = GridExpand;
  1322. m_Width = pDisp->GetWidth();
  1323. m_Height = pDisp->GetHeight();
  1324. m_GridWidth = m_Width + ( GridExpand * 2 );
  1325. m_GridHeight = m_Height + ( GridExpand * 2 );
  1326. m_Grid = new TDispPoint[ m_GridWidth * m_GridHeight ];
  1327. for( int i = 0; i < m_GridWidth * m_GridHeight; i++ )
  1328. {
  1329. m_Grid[ i ].m_IsSet = false;
  1330. }
  1331. if ( DoPopulate )
  1332. {
  1333. Populate( pDisp );
  1334. }
  1335. }
  1336. CDispGrid::~CDispGrid( )
  1337. {
  1338. delete [] m_Grid;
  1339. }
  1340. void CDispGrid::PopulateUp( CMapDisp *pDisp )
  1341. {
  1342. EditDispHandle_t handle;
  1343. int orient;
  1344. pDisp->GetEdgeNeighbor( DISP_DIR_TOP_TO_BOTTOM, handle, orient );
  1345. if ( handle == EDITDISPHANDLE_INVALID )
  1346. {
  1347. return;
  1348. }
  1349. pDisp = EditDispMgr()->GetDisp( handle );
  1350. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1351. { // don't support ones which aren't of the same subdivision
  1352. return;
  1353. }
  1354. if ( orient != MOVE_DIR_DOWN )
  1355. { // don't support rotation for now
  1356. return;
  1357. }
  1358. for( int x = 0; x < m_Width; x++ )
  1359. {
  1360. for( int y = 0; y < m_GridExpand; y++ )
  1361. {
  1362. int GridPos = ( ( m_GridHeight - y - 1 ) * m_GridWidth ) + ( x + m_GridExpand );
  1363. m_Grid[ GridPos ].m_DispPos = ( ( m_GridExpand - y ) * m_Width ) + x; // don't do inner row, as that is sewed
  1364. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1365. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1366. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1367. m_Grid[ GridPos ].m_IsSet = true;
  1368. }
  1369. }
  1370. }
  1371. void CDispGrid::PopulateDown( CMapDisp *pDisp )
  1372. {
  1373. EditDispHandle_t handle;
  1374. int orient;
  1375. pDisp->GetEdgeNeighbor( DISP_DIR_BOTTOM_TO_TOP, handle, orient );
  1376. if ( handle == EDITDISPHANDLE_INVALID )
  1377. {
  1378. return;
  1379. }
  1380. pDisp = EditDispMgr()->GetDisp( handle );
  1381. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1382. { // don't support ones which aren't of the same subdivision
  1383. return;
  1384. }
  1385. if ( orient != MOVE_DIR_UP )
  1386. { // don't support rotation for now
  1387. return;
  1388. }
  1389. for( int x = 0; x < m_Width; x++ )
  1390. {
  1391. for( int y = 0; y < m_GridExpand; y++ )
  1392. {
  1393. int GridPos = ( ( y ) * m_GridWidth ) + ( x + m_GridExpand );
  1394. m_Grid[ GridPos ].m_DispPos = ( ( m_Height - m_GridExpand + y - 1 ) * m_Width ) + x; // don't do inner row, as that is sewed
  1395. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1396. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1397. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1398. m_Grid[ GridPos ].m_IsSet = true;
  1399. }
  1400. }
  1401. }
  1402. void CDispGrid::PopulateRight( CMapDisp *pDisp )
  1403. {
  1404. EditDispHandle_t handle;
  1405. int orient;
  1406. pDisp->GetEdgeNeighbor( DISP_DIR_RIGHT_TO_LEFT, handle, orient );
  1407. if ( handle == EDITDISPHANDLE_INVALID )
  1408. {
  1409. return;
  1410. }
  1411. pDisp = EditDispMgr()->GetDisp( handle );
  1412. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1413. { // don't support ones which aren't of the same subdivision
  1414. return;
  1415. }
  1416. if ( orient != MOVE_DIR_RIGHT )
  1417. { // don't support rotation for now
  1418. return;
  1419. }
  1420. for( int x = 0; x < m_GridExpand; x++ )
  1421. {
  1422. for( int y = 0; y < m_Height; y++ )
  1423. {
  1424. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand + m_Width );
  1425. m_Grid[ GridPos ].m_DispPos = ( ( y ) * m_Width ) + x + 1; // don't do inner row, as that is sewed
  1426. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1427. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1428. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1429. m_Grid[ GridPos ].m_IsSet = true;
  1430. }
  1431. }
  1432. }
  1433. void CDispGrid::PopulateLeft( CMapDisp *pDisp )
  1434. {
  1435. EditDispHandle_t handle;
  1436. int orient;
  1437. pDisp->GetEdgeNeighbor( DISP_DIR_LEFT_TO_RIGHT, handle, orient );
  1438. if ( handle == EDITDISPHANDLE_INVALID )
  1439. {
  1440. return;
  1441. }
  1442. pDisp = EditDispMgr()->GetDisp( handle );
  1443. if ( pDisp->GetWidth() != m_Width || pDisp->GetHeight() != m_Height )
  1444. { // don't support ones which aren't of the same subdivision
  1445. return;
  1446. }
  1447. if ( orient != MOVE_DIR_LEFT )
  1448. { // don't support rotation for now
  1449. return;
  1450. }
  1451. for( int x = 0; x < m_GridExpand; x++ )
  1452. {
  1453. for( int y = 0; y < m_Height; y++ )
  1454. {
  1455. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x );
  1456. m_Grid[ GridPos ].m_DispPos = ( ( y ) * m_Width ) + ( m_Width - m_GridExpand + x - 1 ); // don't do inner row, as that is sewed
  1457. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1458. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1459. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1460. m_Grid[ GridPos ].m_IsSet = true;
  1461. }
  1462. }
  1463. }
  1464. void CDispGrid::Populate( CMapDisp *pDisp )
  1465. {
  1466. for( int x = 0; x < m_Width; x++ )
  1467. {
  1468. for( int y = 0; y < m_Height; y++ )
  1469. {
  1470. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1471. m_Grid[ GridPos ].m_DispPos = ( y * m_Width ) + x;
  1472. pDisp->GetVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_Position );
  1473. m_Grid[ GridPos ].m_UpdatePosition = m_Grid[ GridPos ].m_Position;
  1474. pDisp->GetFlatVert( m_Grid[ GridPos ].m_DispPos, m_Grid[ GridPos ].m_FlatPosition );
  1475. m_Grid[ GridPos ].m_IsSet = true;
  1476. }
  1477. }
  1478. PopulateUp( pDisp );
  1479. PopulateDown( pDisp );
  1480. PopulateRight( pDisp );
  1481. PopulateLeft( pDisp );
  1482. }
  1483. bool CDispGrid::GetPosition( int x, int y, int OffsetX, int OffsetY, Vector &Position )
  1484. {
  1485. x += OffsetX;
  1486. y += OffsetY;
  1487. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1488. if ( !m_Grid[ GridPos ].m_IsSet )
  1489. {
  1490. return false;
  1491. }
  1492. Position = m_Grid[ GridPos ].m_Position;
  1493. return true;
  1494. }
  1495. bool CDispGrid::GetFlatPosition( int x, int y, int OffsetX, int OffsetY, Vector &FlatPosition )
  1496. {
  1497. x += OffsetX;
  1498. y += OffsetY;
  1499. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1500. if ( !m_Grid[ GridPos ].m_IsSet )
  1501. {
  1502. return false;
  1503. }
  1504. FlatPosition = m_Grid[ GridPos ].m_FlatPosition;
  1505. return true;
  1506. }
  1507. void CDispGrid::SetPosition( int x, int y, Vector &NewPosition )
  1508. {
  1509. int GridPos = ( ( y + m_GridExpand ) * m_GridWidth ) + ( x + m_GridExpand );
  1510. if ( !m_Grid[ GridPos ].m_IsSet )
  1511. {
  1512. return;
  1513. }
  1514. m_Grid[ GridPos ].m_UpdatePosition = NewPosition;
  1515. }
  1516. void CDispGrid::UpdatePositions( void )
  1517. {
  1518. for( int i = 0; i < m_GridWidth * m_GridHeight; i++ )
  1519. {
  1520. m_Grid[ i ].m_Position = m_Grid[ i ].m_UpdatePosition ;
  1521. }
  1522. }
  1523. void CDispGrid::CalcSpringForce( int x, int y, int OffsetX, int OffsetY, float Ks, Vector &SpringForce )
  1524. {
  1525. Vector currentP1, currentP2;
  1526. Vector restP1, restP2;
  1527. Vector currentDelta, restDelta;
  1528. float currentDistance, restDistance;
  1529. SpringForce.Init();
  1530. if ( !GetPosition( x, y, 0, 0, currentP1 ) )
  1531. {
  1532. return;
  1533. }
  1534. if ( !GetPosition( x, y, OffsetX, OffsetY, currentP2 ) )
  1535. {
  1536. return;
  1537. }
  1538. if ( !GetFlatPosition( x, y, 0, 0, restP1 ) )
  1539. {
  1540. return;
  1541. }
  1542. if ( !GetFlatPosition( x, y, OffsetX, OffsetY, restP2 ) )
  1543. {
  1544. return;
  1545. }
  1546. currentDelta = currentP1 - currentP2;
  1547. currentDistance = currentDelta.Length();
  1548. if ( currentDistance == 0.0f )
  1549. {
  1550. return;
  1551. }
  1552. restDelta = restP1 - restP2;
  1553. restDistance = restDelta.Length();
  1554. float Hterm = (currentDistance - restDistance) * Ks;
  1555. // VectorDifference(&p1->v,&p2->v,&deltaV); // Delta Velocity Vector
  1556. // Dterm = (DotProduct(&deltaV,&deltaP) * spring->Kd) / dist; // Damping Term
  1557. float Dterm = 0.0f;
  1558. SpringForce = currentDelta * ( 1.0f / currentDistance );
  1559. SpringForce = SpringForce * -(Hterm + Dterm);
  1560. //VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
  1561. //VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2
  1562. }
  1563. void CSculptPushOptions::DoSmoothOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  1564. {
  1565. Vector SpringForce;
  1566. int width = pDisp->GetWidth();
  1567. int height = pDisp->GetHeight();
  1568. Vector *Forces = ( Vector * )_alloca( sizeof( *Forces ) * width * height );
  1569. bool *DoCalc = ( bool * )_alloca( sizeof( *DoCalc ) * width * height );
  1570. const float SPRING_CONSTANT = 0.02f;
  1571. const float SPRING_CONSTANT_TO_NORMAL = 0.4f;
  1572. Vector SurfaceNormal;
  1573. pDisp->GetSurfNormal( SurfaceNormal );
  1574. for( int x = 0; x < width; x++ )
  1575. {
  1576. for( int y = 0; y < height; y++ )
  1577. {
  1578. int pVert = ( x * width ) + y;
  1579. Vector pos, vTestVert;
  1580. pDisp->GetVert( pVert, pos );
  1581. if ( pOrigDisp && 0 )
  1582. {
  1583. pOrigDisp->GetVert( pVert, vTestVert );
  1584. }
  1585. else
  1586. {
  1587. vTestVert = pos;
  1588. }
  1589. Vector2D ViewVert;
  1590. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  1591. Vector2D Offset = ViewVert - m_MousePoint;
  1592. float Length = Offset.Length();
  1593. if ( Length <= m_BrushSize || 0 )
  1594. {
  1595. DoCalc[ pVert ] = true;
  1596. }
  1597. else
  1598. {
  1599. DoCalc[ pVert ] = false;
  1600. }
  1601. }
  1602. }
  1603. #if 0
  1604. EditDispHandle_t handle;
  1605. int orient;
  1606. for( int i = 0; i < 4; i++ )
  1607. {
  1608. pDisp->GetEdgeNeighbor( i, handle, orient );
  1609. if ( handle != EDITDISPHANDLE_INVALID )
  1610. {
  1611. Msg( "Handle at %d orient %d\n", i, orient );
  1612. }
  1613. }
  1614. int x = 0;
  1615. int y = 0;
  1616. CMapDisp *pNextDisp = pDisp;
  1617. Vector Vert;
  1618. Vector FlatVert;
  1619. while( 1 )
  1620. {
  1621. if ( !GetAdjoiningPoint( x, y, MOVE_DIR_UP, 1, pNextDisp, Vert, FlatVert ) || pDisp != pNextDisp )
  1622. {
  1623. break;
  1624. }
  1625. y++;
  1626. }
  1627. return;
  1628. #endif
  1629. CDispGrid DispGrid( pDisp, true );
  1630. const float StepAmount = 1.0f;
  1631. float CurrentSmooth = m_SmoothAmount;
  1632. while( CurrentSmooth > 0.0f )
  1633. {
  1634. float SpringAmount;
  1635. float SpringToNormalAmount;
  1636. if ( CurrentSmooth > StepAmount )
  1637. {
  1638. SpringAmount = SPRING_CONSTANT * StepAmount;
  1639. SpringToNormalAmount = SPRING_CONSTANT_TO_NORMAL * StepAmount;
  1640. }
  1641. else
  1642. {
  1643. SpringAmount = SPRING_CONSTANT * CurrentSmooth;
  1644. SpringToNormalAmount = SPRING_CONSTANT_TO_NORMAL * CurrentSmooth;
  1645. }
  1646. CurrentSmooth -= StepAmount;
  1647. for( int x = 0; x < width; x++ )
  1648. {
  1649. for( int y = 0; y < height; y++ )
  1650. {
  1651. int pVert = ( y * width ) + x;
  1652. if ( !DoCalc[ pVert ] )
  1653. {
  1654. continue;
  1655. }
  1656. Forces[ pVert ].Init();
  1657. // structural springs
  1658. DispGrid.CalcSpringForce( x, y, 1, 0, SpringAmount, SpringForce );
  1659. Forces[ pVert ] += SpringForce;
  1660. DispGrid.CalcSpringForce( x, y, -1, 0, SpringAmount, SpringForce );
  1661. Forces[ pVert ] += SpringForce;
  1662. DispGrid.CalcSpringForce( x, y, 0, 1, SpringAmount, SpringForce );
  1663. Forces[ pVert ] += SpringForce;
  1664. DispGrid.CalcSpringForce( x, y, 0, -1, SpringAmount, SpringForce );
  1665. Forces[ pVert ] += SpringForce;
  1666. // shear springs
  1667. DispGrid.CalcSpringForce( x, y, 1, 1, SpringAmount, SpringForce );
  1668. Forces[ pVert ] += SpringForce;
  1669. DispGrid.CalcSpringForce( x, y, -1, 1, SpringAmount, SpringForce );
  1670. Forces[ pVert ] += SpringForce;
  1671. DispGrid.CalcSpringForce( x, y, 1, -1, SpringAmount, SpringForce );
  1672. Forces[ pVert ] += SpringForce;
  1673. DispGrid.CalcSpringForce( x, y, -1, -1, SpringAmount, SpringForce );
  1674. Forces[ pVert ] += SpringForce;
  1675. // bend springs
  1676. DispGrid.CalcSpringForce( x, y, 2, 0, SpringAmount, SpringForce );
  1677. Forces[ pVert ] += SpringForce;
  1678. DispGrid.CalcSpringForce( x, y, -2, 0, SpringAmount, SpringForce );
  1679. Forces[ pVert ] += SpringForce;
  1680. DispGrid.CalcSpringForce( x, y, 0, 2, SpringAmount, SpringForce );
  1681. Forces[ pVert ] += SpringForce;
  1682. DispGrid.CalcSpringForce( x, y, 0, -2, SpringAmount, SpringForce );
  1683. Forces[ pVert ] += SpringForce;
  1684. Vector Vert, FlatVert, FlatVertExtended, ClosestPoint;
  1685. DispGrid.GetPosition( x, y, 0, 0, Vert );
  1686. DispGrid.GetFlatPosition( x, y, 0, 0, FlatVert );
  1687. FlatVertExtended = FlatVert + ( SurfaceNormal * 10.0f );
  1688. CalcClosestPointOnLine( Vert, FlatVert, FlatVertExtended, ClosestPoint );
  1689. Vector Difference = ( Vert - ClosestPoint );
  1690. float Distance = Difference.Length();
  1691. if ( Distance > 0.0f )
  1692. {
  1693. float Hterm = Distance * SpringToNormalAmount;
  1694. float Dterm = 0.0f;
  1695. SpringForce = ( Difference ) * ( 1.0f / Distance );
  1696. SpringForce = SpringForce * -(Hterm + Dterm);
  1697. Forces[ pVert ] += SpringForce;
  1698. }
  1699. Vector pos;
  1700. DispGrid.GetPosition( x, y, 0, 0, pos );
  1701. pos += Forces[ pVert ];
  1702. AddToUndo( &pDisp );
  1703. pDisp->Paint_SetValue( pVert, pos );
  1704. DispGrid.SetPosition( x, y, pos );
  1705. }
  1706. }
  1707. DispGrid.UpdatePositions();
  1708. }
  1709. }
  1710. #endif
  1711. //-----------------------------------------------------------------------------
  1712. // Purpose: sets the offset distance
  1713. //-----------------------------------------------------------------------------
  1714. void CSculptPushOptions::OnEnChangeSculptPushOptionOffsetDistance()
  1715. {
  1716. char temp[ 1024 ];
  1717. m_OffsetDistanceControl.GetWindowText( temp, sizeof( temp ) );
  1718. m_OffsetDistance = atof( temp );
  1719. }
  1720. //-----------------------------------------------------------------------------
  1721. // Purpose: sets the density mode
  1722. //-----------------------------------------------------------------------------
  1723. void CSculptPushOptions::OnCbnSelchangeSculptPushOptionDensityMode()
  1724. {
  1725. m_DensityMode = ( DensityMode )m_DensityModeControl.GetCurSel();
  1726. }
  1727. //-----------------------------------------------------------------------------
  1728. // Purpose: sets the smooth amount
  1729. //-----------------------------------------------------------------------------
  1730. void CSculptPushOptions::OnEnKillfocusSculptPushOptionSmoothAmount()
  1731. {
  1732. char temp[ 1024 ], t2[ 1024 ];
  1733. m_SmoothAmountControl.GetWindowText( temp, sizeof( temp ) );
  1734. sscanf( temp, "%f%%", &m_SmoothAmount );
  1735. m_SmoothAmount /= 100.0f;
  1736. if ( m_SmoothAmount <= 0.0f )
  1737. {
  1738. m_SmoothAmount = 0.2f;
  1739. }
  1740. sprintf( t2, "%g%%", m_SmoothAmount * 100.0f );
  1741. if ( strcmpi( temp, t2 ) != 0 )
  1742. {
  1743. m_SmoothAmountControl.SetWindowText( t2 );
  1744. }
  1745. }
  1746. //-----------------------------------------------------------------------------
  1747. // Purpose: sets the offset amount
  1748. //-----------------------------------------------------------------------------
  1749. void CSculptPushOptions::OnEnKillfocusSculptPushOptionOffsetAmount()
  1750. {
  1751. char temp[ 1024 ], t2[ 1024 ];
  1752. m_OffsetAmountControl.GetWindowText( temp, sizeof( temp ) );
  1753. sscanf( temp, "%f%%", &m_OffsetAmount );
  1754. m_OffsetAmount /= 100.0f;
  1755. if ( m_OffsetAmount <= 0.0f )
  1756. {
  1757. m_OffsetAmount = 1.0f;
  1758. }
  1759. sprintf( t2, "%g%%", m_OffsetAmount * 100.0f );
  1760. if ( strcmpi( temp, t2 ) != 0 )
  1761. {
  1762. m_OffsetAmountControl.SetWindowText( t2 );
  1763. }
  1764. }
  1765. void CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffPosition()
  1766. {
  1767. char temp[ 1024 ], t2[ 1024 ];
  1768. m_FalloffPositionControl.GetWindowText( temp, sizeof( temp ) );
  1769. sscanf( temp, "%f%%", &m_flFalloffSpot );
  1770. m_flFalloffSpot /= 100.0f;
  1771. if ( m_flFalloffSpot <= 0.0f )
  1772. {
  1773. m_flFalloffSpot = 0.0f;
  1774. }
  1775. if ( m_flFalloffSpot > 1.0f )
  1776. {
  1777. m_flFalloffSpot = 1.0f;
  1778. }
  1779. sprintf( t2, "%g%%", m_flFalloffSpot * 100.0f );
  1780. if ( strcmpi( temp, t2 ) != 0 )
  1781. {
  1782. m_FalloffPositionControl.SetWindowText( t2 );
  1783. }
  1784. }
  1785. void CSculptPushOptions::OnEnKillfocusSculptPushOptionFalloffFinal()
  1786. {
  1787. char temp[ 1024 ], t2[ 1024 ];
  1788. m_FalloffFinalControl.GetWindowText( temp, sizeof( temp ) );
  1789. sscanf( temp, "%f%%", &m_flFalloffEndingValue);
  1790. m_flFalloffEndingValue /= 100.0f;
  1791. if ( m_flFalloffEndingValue <= 0.0f )
  1792. {
  1793. m_flFalloffEndingValue = 0.0f;
  1794. }
  1795. if ( m_flFalloffEndingValue > 1.0f )
  1796. {
  1797. m_flFalloffEndingValue = 1.0f;
  1798. }
  1799. sprintf( t2, "%g%%", m_flFalloffEndingValue * 100.0f );
  1800. if ( strcmpi( temp, t2 ) != 0 )
  1801. {
  1802. m_FalloffFinalControl.SetWindowText( t2 );
  1803. }
  1804. }
  1805. // CSculptCarveOptions dialog
  1806. IMPLEMENT_DYNAMIC(CSculptCarveOptions, CDialog)
  1807. //-----------------------------------------------------------------------------
  1808. // Purpose: constructor
  1809. //-----------------------------------------------------------------------------
  1810. CSculptCarveOptions::CSculptCarveOptions(CWnd* pParent /*=NULL*/) :
  1811. CDialog(CSculptCarveOptions::IDD, pParent),
  1812. CSculptPainter()
  1813. {
  1814. m_OffsetMode = OFFSET_MODE_ABSOLUTE;
  1815. m_NormalMode = NORMAL_MODE_Z;
  1816. m_DensityMode = DENSITY_MODE_ADDITIVE;
  1817. m_OffsetDistance = 10.0f;
  1818. m_OffsetAmount = 1.0f;
  1819. m_SmoothAmount = 0.2f;
  1820. m_Direction = 1.0f;
  1821. m_SelectedNormal.Init( 0.0f, 0.0f, 0.0f );
  1822. m_BrushLocation = -1;
  1823. m_StartLine.Init( -1.0f, -1.0f );
  1824. m_EndLine.Init( -1.0f, -1.0f );
  1825. for( int i = 0; i < MAX_SCULPT_SIZE; i++ )
  1826. {
  1827. m_BrushPoints[ i ] = ( i / ( float )MAX_SCULPT_SIZE ); // 0.0f;
  1828. }
  1829. }
  1830. //-----------------------------------------------------------------------------
  1831. // Purpose: destructor
  1832. //-----------------------------------------------------------------------------
  1833. CSculptCarveOptions::~CSculptCarveOptions()
  1834. {
  1835. }
  1836. //-----------------------------------------------------------------------------
  1837. // Purpose: initializes the dialog
  1838. // Output : returns true if successful
  1839. //-----------------------------------------------------------------------------
  1840. BOOL CSculptCarveOptions::OnInitDialog( )
  1841. {
  1842. char temp[ 1024 ];
  1843. CDialog::OnInitDialog();
  1844. m_OffsetModeControl.InsertString( -1, "Adaptive" );
  1845. m_OffsetModeControl.InsertString( -1, "Absolute" );
  1846. m_OffsetModeControl.SetCurSel( m_OffsetMode );
  1847. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  1848. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  1849. sprintf( temp, "%g", m_OffsetDistance );
  1850. m_OffsetDistanceControl.SetWindowText( temp );
  1851. sprintf( temp, "%g%%", m_OffsetAmount * 100.0f );
  1852. m_OffsetAmountControl.SetWindowText( temp );
  1853. sprintf( temp, "%g%%", m_SmoothAmount * 100.0f );
  1854. m_SmoothAmountControl.SetWindowText( temp );
  1855. m_NormalModeControl.InsertString( -1, "Brush Center" );
  1856. m_NormalModeControl.InsertString( -1, "Screen" );
  1857. m_NormalModeControl.InsertString( -1, "X" );
  1858. m_NormalModeControl.InsertString( -1, "Y" );
  1859. m_NormalModeControl.InsertString( -1, "Z" );
  1860. m_NormalModeControl.InsertString( -1, "Selected" );
  1861. m_NormalModeControl.SetCurSel( m_NormalMode );
  1862. m_DensityModeControl.InsertString( -1, "Additive" );
  1863. m_DensityModeControl.InsertString( -1, "Attenuated" );
  1864. m_DensityModeControl.SetCurSel( m_DensityMode );
  1865. return TRUE;
  1866. }
  1867. //-----------------------------------------------------------------------------
  1868. // Purpose: prevent the dialog from closing
  1869. //-----------------------------------------------------------------------------
  1870. void CSculptCarveOptions::OnOK( )
  1871. {
  1872. }
  1873. //-----------------------------------------------------------------------------
  1874. // Purpose: prevent the dialog from closing
  1875. //-----------------------------------------------------------------------------
  1876. void CSculptCarveOptions::OnCancel( )
  1877. {
  1878. }
  1879. //-----------------------------------------------------------------------------
  1880. // Purpose: set up the data exchange for the variables
  1881. // Input : pDX - the data exchange object
  1882. //-----------------------------------------------------------------------------
  1883. void CSculptCarveOptions::DoDataExchange(CDataExchange* pDX)
  1884. {
  1885. CDialog::DoDataExchange(pDX);
  1886. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, m_OffsetModeControl);
  1887. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, m_OffsetDistanceControl);
  1888. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, m_OffsetAmountControl);
  1889. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, m_SmoothAmountControl);
  1890. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, m_DensityModeControl);
  1891. DDX_Control(pDX, IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, m_NormalModeControl);
  1892. DDX_Control(pDX, IDC_CARVE_BRUSH, m_CarveBrushControl);
  1893. }
  1894. BEGIN_MESSAGE_MAP(CSculptCarveOptions, CDialog)
  1895. ON_CBN_SELCHANGE(IDC_IDC_SCULPT_PUSH_OPTION_NORMAL_MODE, &CSculptCarveOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode)
  1896. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_MODE, &CSculptCarveOptions::OnCbnSelchangeSculptPushOptionOffsetMode)
  1897. ON_EN_CHANGE(IDC_SCULPT_PUSH_OPTION_OFFSET_DISTANCE, &CSculptCarveOptions::OnEnChangeSculptPushOptionOffsetDistance)
  1898. ON_CBN_SELCHANGE(IDC_SCULPT_PUSH_OPTION_DENSITY_MODE, &CSculptCarveOptions::OnCbnSelchangeSculptPushOptionDensityMode)
  1899. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_SMOOTH_AMOUNT, &CSculptCarveOptions::OnEnKillfocusSculptPushOptionSmoothAmount)
  1900. ON_EN_KILLFOCUS(IDC_SCULPT_PUSH_OPTION_OFFSET_AMOUNT, &CSculptCarveOptions::OnEnKillfocusSculptPushOptionOffsetAmount)
  1901. ON_WM_PAINT()
  1902. ON_WM_LBUTTONDOWN()
  1903. ON_WM_LBUTTONUP()
  1904. ON_WM_MOUSEMOVE()
  1905. END_MESSAGE_MAP()
  1906. //-----------------------------------------------------------------------------
  1907. // Purpose: sets the normal mode
  1908. //-----------------------------------------------------------------------------
  1909. void CSculptCarveOptions::OnCbnSelchangeIdcSculptPushOptionNormalMode()
  1910. {
  1911. m_NormalMode = ( NormalMode )m_NormalModeControl.GetCurSel();
  1912. }
  1913. //-----------------------------------------------------------------------------
  1914. // Purpose: sets the offset mode
  1915. //-----------------------------------------------------------------------------
  1916. void CSculptCarveOptions::OnCbnSelchangeSculptPushOptionOffsetMode()
  1917. {
  1918. m_OffsetMode = ( OffsetMode )m_OffsetModeControl.GetCurSel();
  1919. m_OffsetDistanceControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ABSOLUTE ) );
  1920. m_OffsetAmountControl.EnableWindow( ( m_OffsetMode == OFFSET_MODE_ADAPTIVE ) );
  1921. }
  1922. //-----------------------------------------------------------------------------
  1923. // Purpose: setup for starting to paint on the displacement
  1924. // Input : pView - the 3d view
  1925. // vPoint - the initial click point
  1926. // Output : returns true if successful
  1927. //-----------------------------------------------------------------------------
  1928. bool CSculptCarveOptions::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  1929. {
  1930. __super::BeginPaint( pView, vPoint );
  1931. if ( m_bCtrlDown )
  1932. {
  1933. m_Direction = -1.0f;
  1934. }
  1935. else
  1936. {
  1937. m_Direction = 1.0f;
  1938. }
  1939. return true;
  1940. }
  1941. //-----------------------------------------------------------------------------
  1942. // Purpose: calculates the normal / direction of the drawing line
  1943. // Input : nPointIndex - which point to factor from
  1944. // Output : returns true if we found a valid normal
  1945. // vNormal - the normal we found
  1946. //-----------------------------------------------------------------------------
  1947. #if 0
  1948. bool CSculptCarveOptions::CalculatePointNormal( int nPointIndex, Vector2D &vNormal )
  1949. {
  1950. float count = 0.0;
  1951. Vector2D vAverage( 0.0f, 0.0f );
  1952. const int max_backsize = 3;
  1953. // keep going back from the current point until you get a total distance
  1954. for( int j = 0; j < max_backsize; j++ )
  1955. {
  1956. int index = ( nPointIndex - max_backsize + j );
  1957. if ( index < 0 )
  1958. {
  1959. continue;
  1960. }
  1961. int index2 = nPointIndex;
  1962. Vector2D vDiff( m_DrawPoints[ index2 ].x - m_DrawPoints[ index ].x, m_DrawPoints[ index2 ].y - m_DrawPoints[ index ].y );
  1963. float Length = Vector2DNormalize( vDiff );
  1964. if ( Length == 0.0f )
  1965. {
  1966. continue;
  1967. }
  1968. float factor = ( ( j + 1 ) * 100 ); // * Length; // * 8 * Length;
  1969. vAverage += ( vDiff * factor );
  1970. count += factor;
  1971. }
  1972. if ( count > 0.0f )
  1973. {
  1974. vAverage /= count;
  1975. Vector2DNormalize( vAverage );
  1976. vNormal = vAverage;
  1977. return true;
  1978. }
  1979. return false;
  1980. }
  1981. #endif
  1982. //-----------------------------------------------------------------------------
  1983. // Purpose: calculates the normal / direction of the drawing line
  1984. // Input : nPointIndex - which point to factor from
  1985. // Output : returns true if we found a valid normal
  1986. // vNormal - the normal we found
  1987. //-----------------------------------------------------------------------------
  1988. bool CSculptCarveOptions::CalculateQueuePoint( Vector2D &vPoint, Vector2D &vNormal )
  1989. {
  1990. float count = 0.0;
  1991. Vector2D vAverage( 0.0f, 0.0f );
  1992. const float fMaxLength = 40.0f;
  1993. float fTotalLength = 0.0f;
  1994. Vector2D vInitialDir;
  1995. bool bInitialDirSet = false;
  1996. int PointIndex = m_PointQueue.Count() - 1;
  1997. if ( PointIndex <= 1 )
  1998. {
  1999. return false;
  2000. }
  2001. vPoint = m_PointQueue[ PointIndex ];
  2002. // keep going back from the current point until you get a total distance
  2003. for( int j = PointIndex - 1; j >= 0; j-- )
  2004. {
  2005. int index = j;
  2006. int index2 = PointIndex;
  2007. Vector2D vDiff( m_PointQueue[ index2 ].x - m_PointQueue[ index ].x, m_PointQueue[ index2 ].y - m_PointQueue[ index ].y );
  2008. float Length = Vector2DNormalize( vDiff );
  2009. if ( Length == 0.0f )
  2010. {
  2011. continue;
  2012. }
  2013. if ( bInitialDirSet == false )
  2014. {
  2015. vInitialDir = vDiff;
  2016. bInitialDirSet = true;
  2017. }
  2018. if ( DotProduct2D( vInitialDir, vDiff ) <= 0.5f )
  2019. {
  2020. break;
  2021. }
  2022. fTotalLength += Length;
  2023. float factor;
  2024. #if 0
  2025. factor = 1.0f - ( fTotalLength / fMaxLength );
  2026. if ( factor <= 0.0f )
  2027. {
  2028. factor = 0.01;
  2029. }
  2030. factor *= 20.0f;
  2031. #endif
  2032. factor = Length;
  2033. //= Length; // ( ( j + 1 ) * 100 ); // * Length; // * 8 * Length;
  2034. vAverage += ( vDiff * factor );
  2035. count += factor;
  2036. if ( fTotalLength >= fMaxLength )
  2037. {
  2038. break;
  2039. }
  2040. }
  2041. if ( count > 0.0f )
  2042. {
  2043. vAverage /= count;
  2044. Vector2DNormalize( vAverage );
  2045. vNormal = vAverage;
  2046. return true;
  2047. }
  2048. return false;
  2049. }
  2050. //-----------------------------------------------------------------------------
  2051. // Purpose: adds the point and normal to the queue
  2052. // Input : vPoint - the point to be added
  2053. // bDrawIt - if we should add this point to the draw / normal lists
  2054. //-----------------------------------------------------------------------------
  2055. void CSculptCarveOptions::AddQueuePoint( const Vector2D &vPoint, bool bDrawIt )
  2056. {
  2057. m_PointQueue.AddToTail( vPoint );
  2058. if ( m_PointQueue.Count() > MAX_QUEUE_SIZE )
  2059. {
  2060. m_PointQueue.Remove( 0 );
  2061. }
  2062. Vector2D vNewPoint, vNewNormal;
  2063. if ( bDrawIt && CalculateQueuePoint( vNewPoint, vNewNormal ) )
  2064. {
  2065. m_DrawPoints.AddToTail( vNewPoint );
  2066. m_DrawNormal.AddToTail( vNewNormal );
  2067. }
  2068. }
  2069. //-----------------------------------------------------------------------------
  2070. // Purpose: draws the tool in the 3d view
  2071. // Input : pRender - the 3d renderer
  2072. //-----------------------------------------------------------------------------
  2073. void CSculptCarveOptions::RenderTool3D( CRender3D *pRender )
  2074. {
  2075. // pRender->DrawText( "mouse", m_MousePoint.x, m_MousePoint.y, 0 );
  2076. // Msg( "%g %g\n", m_MousePoint.x, m_MousePoint.y );
  2077. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  2078. pRender->BeginClientSpace();
  2079. Vector2D vMousePoint, vMouseNormal;
  2080. if ( CalculateQueuePoint( vMousePoint, vMouseNormal ) )
  2081. {
  2082. Vector2D vRight( -vMouseNormal.y, vMouseNormal.x );
  2083. pRender->SetDrawColor( 255, 255, 0 );
  2084. pRender->DrawLine( Vector( vMousePoint.x, vMousePoint.y, 0.0f ), Vector( vMousePoint.x + vRight.x * m_BrushSize, vMousePoint.y + vRight.y * m_BrushSize, 0.0f ) );
  2085. pRender->DrawLine( Vector( vMousePoint.x, vMousePoint.y, 0.0f ), Vector( vMousePoint.x - ( vRight.x * m_BrushSize ), vMousePoint.y - ( vRight.y * m_BrushSize ), 0.0f ) );
  2086. }
  2087. #if 0
  2088. for( int i = 2; i < m_DrawPoints.Count(); i++ )
  2089. {
  2090. Vector2D vPoint = m_DrawPoints[ i ];
  2091. Vector2D vPreviousPoint = m_DrawPoints[ i - 1];
  2092. Vector2D vNormal = m_DrawNormal[ i ];
  2093. Vector2D vRight( -m_DrawNormal[ i ].y, m_DrawNormal[ i ].x );
  2094. Vector2D vDelta = vPoint - vPreviousPoint;
  2095. float Length = Vector2DLength( vDelta );
  2096. pRender->SetDrawColor( 255, 255, 0 );
  2097. pRender->DrawLine( Vector( vPreviousPoint.x, vPreviousPoint.y, 0.0f ), Vector( vPoint.x, vPoint.y, 0.0f ) );
  2098. pRender->SetDrawColor( 255, 0, 0 );
  2099. pRender->DrawLine( Vector( vPoint.x, vPoint.y, 0.0f ), Vector( vPoint.x + vRight.x * m_BrushSize, vPoint.y + vRight.y * m_BrushSize, 0.0f ) );
  2100. // pRender->DrawLine( Vector( vPoint.x, vPoint.y, 0.0f ), Vector( vPoint.x - ( vRight.x * m_BrushSize ), vPoint.y - ( vRight.y * m_BrushSize ), 0.0f ) );
  2101. vNormal *= Length;
  2102. pRender->SetDrawColor( 0, 255, 0 );
  2103. pRender->DrawLine( Vector( vPoint.x - vNormal.x, vPoint.y - vNormal.y, 0.0f ), Vector( vPoint.x, vPoint.y, 0.0f ) );
  2104. }
  2105. pRender->SetDrawColor( 255, 0, 255 );
  2106. pRender->SetHandleStyle( 6, CRender::HANDLE_SQUARE );
  2107. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2108. if( pDispMgr )
  2109. {
  2110. int nDispCount = pDispMgr->SelectCount();
  2111. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  2112. {
  2113. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  2114. if ( pDisp )
  2115. {
  2116. int nVertCount = pDisp->GetSize();
  2117. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2118. {
  2119. Vector vVert;
  2120. Vector2D vViewVert;
  2121. pDisp->GetVert( iVert, vVert );
  2122. pRender->GetCamera()->WorldToView( vVert, vViewVert );
  2123. for( int i = 2; i < m_DrawPoints.Count(); i++ )
  2124. {
  2125. float distance;
  2126. float tolerance = DotProduct2D( m_DrawNormal[ i ], m_DrawNormal[ i - 1 ] );
  2127. if ( tolerance <= 0.5f )
  2128. {
  2129. continue;
  2130. }
  2131. distance = DotProduct2D( m_DrawNormal[ i ], m_DrawPoints[ i ] );
  2132. if ( DotProduct2D( m_DrawNormal[ i ], vViewVert ) > distance )
  2133. {
  2134. continue;
  2135. }
  2136. distance = DotProduct2D( m_DrawNormal[ i - 1 ], m_DrawPoints[ i - 1 ] );
  2137. if ( DotProduct2D( m_DrawNormal[ i - 1 ], vViewVert ) < distance )
  2138. {
  2139. continue;
  2140. }
  2141. Vector2D vRight( -m_DrawNormal[ i ].y, m_DrawNormal[ i ].x );
  2142. Vector2D vPoint;
  2143. vPoint = m_DrawPoints[ i ] + ( vRight * m_BrushSize );
  2144. distance = DotProduct2D( vRight, vPoint );
  2145. if ( DotProduct2D( vRight, vViewVert ) > distance )
  2146. {
  2147. continue;
  2148. }
  2149. vPoint = m_DrawPoints[ i ] - ( vRight * m_BrushSize );
  2150. distance = DotProduct2D( vRight, vPoint );
  2151. if ( DotProduct2D( vRight, vViewVert ) < distance )
  2152. {
  2153. continue;
  2154. }
  2155. // pRender->DrawHandle( Vector( vViewVert.x, vViewVert.y, 0.0f ) );
  2156. pRender->DrawHandle( vVert );
  2157. break;
  2158. }
  2159. }
  2160. }
  2161. }
  2162. }
  2163. #endif
  2164. pRender->EndClientSpace();
  2165. #if 0
  2166. if ( m_InSizingMode )
  2167. { // yellow for sizing mode
  2168. pRender->SetDrawColor( 255, 255, 0 );
  2169. pRender->BeginClientSpace();
  2170. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2171. pRender->EndClientSpace();
  2172. }
  2173. else if ( m_bShiftDown )
  2174. { // purple for smoothing
  2175. pRender->SetDrawColor( 255, 0, 255 );
  2176. pRender->BeginClientSpace();
  2177. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2178. pRender->EndClientSpace();
  2179. }
  2180. else if ( m_bCtrlDown )
  2181. { // red for negative sculpting
  2182. pRender->SetDrawColor( 255, 0, 0 );
  2183. pRender->BeginClientSpace();
  2184. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2185. pRender->EndClientSpace();
  2186. Vector vPaintAxis;
  2187. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  2188. DrawDirection( pRender, -vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  2189. }
  2190. else
  2191. { // green for positive sculpting
  2192. pRender->SetDrawColor( 0, 255, 0 );
  2193. pRender->BeginClientSpace();
  2194. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  2195. pRender->EndClientSpace();
  2196. Vector vPaintAxis;
  2197. GetPaintAxis( pRender->GetCamera(), m_MousePoint, vPaintAxis );
  2198. DrawDirection( pRender, vPaintAxis, Color( 255, 255, 255 ), Color( 255, 128, 128 ) );
  2199. }
  2200. #endif
  2201. #if 0
  2202. FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept );
  2203. Vector2D RadiusPoint = m_MousePoint;
  2204. Vector vecStart, vecEnd;
  2205. RadiusPoint.x += m_BrushSize;
  2206. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  2207. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  2208. pRender->RenderWireframeSphere( m_CurrentCollisionPoint, m_CurrentProjectedRadius, 12, 12, 0, 255, 255 );
  2209. #endif
  2210. #if 0
  2211. // Get the displacement manager from the active map document.
  2212. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2213. // For each displacement surface is the selection list attempt to paint on it.
  2214. int nDispCount = pDispMgr->SelectCount();
  2215. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  2216. {
  2217. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  2218. if ( pDisp )
  2219. {
  2220. CMapDisp *OrigDisp = NULL;
  2221. int index = m_OrigMapDisp.Find( pDisp->GetEditHandle() );
  2222. if ( index != m_OrigMapDisp.InvalidIndex() )
  2223. {
  2224. OrigDisp = m_OrigMapDisp[ index ];
  2225. }
  2226. Vector vPaintPos, vVert;
  2227. int nVertCount = pDisp->GetSize();
  2228. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2229. {
  2230. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, false ) )
  2231. {
  2232. // Get the current vert.
  2233. pDisp->GetVert( iVert, vVert );
  2234. }
  2235. }
  2236. }
  2237. }
  2238. #endif
  2239. pRender->PopRenderMode();
  2240. #if 0
  2241. if ( !FindColissionIntercept( pRender->GetCamera(), m_MousePoint, true, m_CurrentCollisionPoint, m_CurrentCollisionNormal, m_CurrentCollisionIntercept ) )
  2242. {
  2243. return;
  2244. }
  2245. Vector2D RadiusPoint = m_MousePoint;
  2246. Vector vecStart, vecEnd;
  2247. RadiusPoint.x += m_BrushSize;
  2248. pRender->GetCamera()->BuildRay( RadiusPoint, vecStart, vecEnd );
  2249. m_CurrentProjectedRadius = CalcDistanceToLine( m_CurrentCollisionPoint, vecStart, vecEnd );
  2250. Msg( "Dist = %g at %g,%g,%g\n", m_CurrentProjectedRadius, m_CurrentCollisionPoint.x, m_CurrentCollisionPoint.y, m_CurrentCollisionPoint.z );
  2251. #endif
  2252. }
  2253. //-----------------------------------------------------------------------------
  2254. // Purpose: handles the left mouse button up in the 3d view
  2255. // Input : pView - the 3d view
  2256. // nFlags - the button flags
  2257. // vPoint - the mouse point
  2258. // Output : returns true if successful
  2259. //-----------------------------------------------------------------------------
  2260. bool CSculptCarveOptions::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2261. {
  2262. __super::OnLMouseUp3D( pView, nFlags, vPoint );
  2263. AddQueuePoint( vPoint, true );
  2264. return true;
  2265. }
  2266. //-----------------------------------------------------------------------------
  2267. // Purpose: handles the left mouse button down in the 3d view
  2268. // Input : pView - the 3d view
  2269. // nFlags - the button flags
  2270. // vPoint - the mouse point
  2271. // Output : returns true if successful
  2272. //-----------------------------------------------------------------------------
  2273. bool CSculptCarveOptions::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2274. {
  2275. __super::OnLMouseDown3D( pView, nFlags, vPoint );
  2276. m_DrawPoints.Purge();
  2277. m_DrawNormal.Purge();
  2278. AddQueuePoint( vPoint, true );
  2279. return true;
  2280. }
  2281. //-----------------------------------------------------------------------------
  2282. // Purpose: handles the right mouse button down in the 3d view
  2283. // Input : pView - the 3d view
  2284. // nFlags - the button flags
  2285. // vPoint - the mouse point
  2286. // Output : returns true if successful
  2287. //-----------------------------------------------------------------------------
  2288. bool CSculptCarveOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2289. {
  2290. __super::OnRMouseDown3D( pView, nFlags, vPoint );
  2291. if ( m_bAltDown )
  2292. {
  2293. m_NormalMode = NORMAL_MODE_Z;
  2294. m_NormalModeControl.SetCurSel( m_NormalMode );
  2295. #if 0
  2296. //
  2297. // check for closest solid object
  2298. //
  2299. ULONG ulFace;
  2300. CMapClass *pObject;
  2301. if( ( ( pObject = pView->NearestObjectAt( vPoint, ulFace ) ) != NULL ) )
  2302. {
  2303. if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) )
  2304. {
  2305. // get the solid
  2306. CMapSolid *pSolid = ( CMapSolid* )pObject;
  2307. if( !pSolid )
  2308. {
  2309. return true;
  2310. }
  2311. // trace a line and get the normal -- will get a displacement normal
  2312. // if one exists
  2313. CMapFace *pFace = pSolid->GetFace( ulFace );
  2314. if( !pFace )
  2315. {
  2316. return true;
  2317. }
  2318. Vector vRayStart, vRayEnd;
  2319. pView->GetCamera()->BuildRay( vPoint, vRayStart, vRayEnd );
  2320. Vector vHitPos, vHitNormal;
  2321. if( pFace->TraceLine( vHitPos, vHitNormal, vRayStart, vRayEnd ) )
  2322. {
  2323. // set the paint direction
  2324. m_SelectedNormal = vHitNormal;
  2325. m_NormalMode = NORMAL_MODE_SELECTED;
  2326. m_NormalModeControl.SetCurSel( m_NormalMode );
  2327. }
  2328. }
  2329. }
  2330. #else
  2331. Vector CollisionPoint, CollisionNormal;
  2332. float CollisionIntercept;
  2333. if ( FindCollisionIntercept( pView->GetCamera(), vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept ) )
  2334. {
  2335. // set the paint direction
  2336. m_SelectedNormal = -CollisionNormal;
  2337. m_NormalMode = NORMAL_MODE_SELECTED;
  2338. m_NormalModeControl.SetCurSel( m_NormalMode );
  2339. }
  2340. #endif
  2341. }
  2342. return true;
  2343. }
  2344. //-----------------------------------------------------------------------------
  2345. // Purpose: handles the mouse move in the 3d view
  2346. // Input : pView - the 3d view
  2347. // nFlags - the button flags
  2348. // vPoint - the mouse point
  2349. // Output : returns true if successful
  2350. //-----------------------------------------------------------------------------
  2351. bool CSculptCarveOptions::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2352. {
  2353. __super::OnMouseMove3D( pView, nFlags, vPoint );
  2354. AddQueuePoint( vPoint, m_bLMBDown );
  2355. return true;
  2356. }
  2357. //-----------------------------------------------------------------------------
  2358. // Purpose: returns the painting direction
  2359. // Input : pCamera - the 3d camera
  2360. // vPoint - the 2d mouse point
  2361. // Output : vPaintAxis - the direction the painting should go
  2362. //-----------------------------------------------------------------------------
  2363. void CSculptCarveOptions::GetPaintAxis( CCamera *pCamera, const Vector2D &vPoint, Vector &vPaintAxis )
  2364. {
  2365. switch( m_NormalMode )
  2366. {
  2367. case NORMAL_MODE_SCREEN:
  2368. pCamera->GetViewForward( vPaintAxis );
  2369. vPaintAxis = -vPaintAxis;
  2370. break;
  2371. case NORMAL_MODE_BRUSH_CENTER:
  2372. if ( !m_InPaintingMode )
  2373. {
  2374. Vector CollisionPoint, CollisionNormal;
  2375. float CollisionIntercept;
  2376. FindCollisionIntercept( pCamera, vPoint, false, CollisionPoint, CollisionNormal, CollisionIntercept );
  2377. vPaintAxis = -CollisionNormal;
  2378. }
  2379. else
  2380. {
  2381. vPaintAxis = -m_StartingCollisionNormal;
  2382. }
  2383. break;
  2384. case NORMAL_MODE_X:
  2385. vPaintAxis.Init( 1.0f, 0.0f, 0.0f );
  2386. break;
  2387. case NORMAL_MODE_Y:
  2388. vPaintAxis.Init( 0.0f, 1.0f, 0.0f );
  2389. break;
  2390. case NORMAL_MODE_Z:
  2391. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  2392. break;
  2393. case NORMAL_MODE_SELECTED:
  2394. vPaintAxis = m_SelectedNormal;
  2395. break;
  2396. default:
  2397. vPaintAxis.Init( 0.0f, 0.0f, 1.0f );
  2398. }
  2399. }
  2400. //-----------------------------------------------------------------------------
  2401. // Purpose: determines if a displacement point is affected by the carve
  2402. // Input : pView - the 3d view
  2403. // pDisp - the displacement
  2404. // pOrigDisp - the displacement prior to any updates
  2405. // nVertIndex - the vertex to look at
  2406. // nBrushPoint - which list point to check against
  2407. // bUseOrigDisplacement - should we use the vert from the original displacement
  2408. // bUseCurrentPosition - should we use the current collision test point
  2409. // Output : returns true if the point is affected
  2410. // vViewVert - the 2d view vert location
  2411. //-----------------------------------------------------------------------------
  2412. bool CSculptCarveOptions::IsPointAffected( CMapView3D *pView, CMapDisp *pDisp, CMapDisp *pOrigDisp, int vertIndex, int nBrushPoint, Vector2D &vViewVert, bool bUseOrigDisplacement, bool bUseCurrentPosition )
  2413. {
  2414. Vector vVert, vTestVert;
  2415. pDisp->GetVert( vertIndex, vVert );
  2416. if ( pOrigDisp && bUseOrigDisplacement )
  2417. {
  2418. pOrigDisp->GetVert( vertIndex, vTestVert );
  2419. }
  2420. else
  2421. {
  2422. vTestVert = vVert;
  2423. }
  2424. pView->GetCamera()->WorldToView( vTestVert, vViewVert );
  2425. float distance;
  2426. float tolerance = DotProduct2D( m_DrawNormal[ nBrushPoint ], m_DrawNormal[ nBrushPoint - 1 ] );
  2427. if ( tolerance <= 0.5f )
  2428. {
  2429. return false;
  2430. }
  2431. distance = DotProduct2D( m_DrawNormal[ nBrushPoint ], m_DrawPoints[ nBrushPoint ] );
  2432. if ( DotProduct2D( m_DrawNormal[ nBrushPoint ], vViewVert ) > distance )
  2433. {
  2434. return false;
  2435. }
  2436. distance = DotProduct2D( m_DrawNormal[ nBrushPoint - 1 ], m_DrawPoints[ nBrushPoint - 1 ] );
  2437. if ( DotProduct2D( m_DrawNormal[ nBrushPoint - 1 ], vViewVert ) < distance )
  2438. {
  2439. return false;
  2440. }
  2441. Vector2D vRight( -m_DrawNormal[ nBrushPoint ].y, m_DrawNormal[ nBrushPoint ].x );
  2442. Vector2D vPoint;
  2443. vPoint = m_DrawPoints[ nBrushPoint ] + ( vRight * m_BrushSize );
  2444. distance = DotProduct2D( vRight, vPoint );
  2445. if ( DotProduct2D( vRight, vViewVert ) > distance )
  2446. {
  2447. return false;
  2448. }
  2449. vPoint = m_DrawPoints[ nBrushPoint ] - ( vRight * m_BrushSize );
  2450. distance = DotProduct2D( vRight, vPoint );
  2451. if ( DotProduct2D( vRight, vViewVert ) < distance )
  2452. {
  2453. return false;
  2454. }
  2455. return true;
  2456. }
  2457. //-----------------------------------------------------------------------------
  2458. // Purpose: applies the specific push operation onto the displacement
  2459. // Input : pView - the 3d view
  2460. // vPoint - the mouse point
  2461. // pDisp - the displacement to apply the push to
  2462. // pOrigDisp - the original displacement prior to any adjustments
  2463. //-----------------------------------------------------------------------------
  2464. void CSculptCarveOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  2465. {
  2466. Vector vPaintPos, vVert, vDirection;
  2467. Vector2D vViewVert;
  2468. float flDistance = 0.0f;
  2469. Vector vPaintAxis;
  2470. int nTestPoint = m_DrawPoints.Count() - 1;
  2471. if ( nTestPoint < 2 )
  2472. {
  2473. return;
  2474. }
  2475. if ( m_bShiftDown )
  2476. {
  2477. // DoSmoothOperation( pView, vPoint, pDisp, pOrigDisp );
  2478. // m_SpatialData.m_flRadius = 256.0f;
  2479. // m_SpatialData.m_flScalar = 5.0f / m_SmoothAmount;
  2480. // m_SpatialData.m_flRadius = m_StartingProjectedRadius * 1.5f;
  2481. m_SpatialData.m_flRadius = m_CurrentProjectedRadius * 2.0f;
  2482. m_SpatialData.m_flRadius2 = ( m_SpatialData.m_flRadius * m_SpatialData.m_flRadius );
  2483. m_SpatialData.m_flOORadius2 = 1.0f / m_SpatialData.m_flRadius2;
  2484. m_SpatialData.m_flScalar = 10.0f / m_SmoothAmount;
  2485. m_SpatialData.m_vCenter = m_CurrentCollisionPoint;
  2486. DoPaintSmooth( pView, vPoint, pDisp, pOrigDisp );
  2487. return;
  2488. }
  2489. GetPaintAxis( pView->GetCamera(), vPoint, vPaintAxis );
  2490. vDirection = vPaintAxis * m_Direction;
  2491. switch( m_OffsetMode )
  2492. {
  2493. case OFFSET_MODE_ADAPTIVE:
  2494. flDistance = m_StartingProjectedRadius * m_OffsetAmount;
  2495. break;
  2496. case OFFSET_MODE_ABSOLUTE:
  2497. flDistance = m_OffsetDistance;
  2498. break;
  2499. }
  2500. int nVertCount = pDisp->GetSize();
  2501. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  2502. {
  2503. if ( IsPointAffected( pView, pDisp, pOrigDisp, iVert, nTestPoint, vViewVert ) )
  2504. {
  2505. pDisp->GetVert( iVert, vVert );
  2506. Vector2D vRight( -m_DrawNormal[ nTestPoint ].y, m_DrawNormal[ nTestPoint ].x );
  2507. float fLineDistance = DotProduct2D( vRight, m_DrawPoints[ nTestPoint ] ) - DotProduct2D( vRight, vViewVert );
  2508. fLineDistance = ( fLineDistance + m_BrushSize ) / ( m_BrushSize * 2.0f );
  2509. int index = ( int )( fLineDistance * MAX_SCULPT_SIZE );
  2510. index = clamp( index, 0, MAX_SCULPT_SIZE - 1 );
  2511. index = MAX_SCULPT_SIZE - index - 1;
  2512. float flScaledDistance = m_BrushPoints[ index ] * flDistance;
  2513. if ( flScaledDistance == 0.0f )
  2514. {
  2515. continue;
  2516. }
  2517. switch( m_DensityMode )
  2518. {
  2519. case DENSITY_MODE_ADDITIVE:
  2520. VectorScale( vDirection, flScaledDistance, vPaintPos );
  2521. VectorAdd( vPaintPos, vVert, vPaintPos );
  2522. break;
  2523. case DENSITY_MODE_ATTENUATED:
  2524. VectorScale( vDirection, flScaledDistance, vPaintPos );
  2525. VectorAdd( vPaintPos, vVert, vPaintPos );
  2526. if ( pOrigDisp )
  2527. {
  2528. Vector vOrigVert, vDiff;
  2529. float Length;
  2530. pOrigDisp->GetVert( iVert, vOrigVert );
  2531. vDiff = ( vPaintPos - vOrigVert );
  2532. Length = vDiff.Length() / flDistance;
  2533. if ( Length > 1.0f )
  2534. {
  2535. Length = 1.0f;
  2536. }
  2537. vPaintPos = vOrigVert + ( Length * vDirection * flDistance );
  2538. }
  2539. break;
  2540. }
  2541. AddToUndo( &pDisp );
  2542. pDisp->Paint_SetValue( iVert, vPaintPos );
  2543. }
  2544. }
  2545. }
  2546. //-----------------------------------------------------------------------------
  2547. // Purpose: sets the offset distance
  2548. //-----------------------------------------------------------------------------
  2549. void CSculptCarveOptions::OnEnChangeSculptPushOptionOffsetDistance()
  2550. {
  2551. char temp[ 1024 ];
  2552. m_OffsetDistanceControl.GetWindowText( temp, sizeof( temp ) );
  2553. m_OffsetDistance = atof( temp );
  2554. }
  2555. //-----------------------------------------------------------------------------
  2556. // Purpose: sets the density mode
  2557. //-----------------------------------------------------------------------------
  2558. void CSculptCarveOptions::OnCbnSelchangeSculptPushOptionDensityMode()
  2559. {
  2560. m_DensityMode = ( DensityMode )m_DensityModeControl.GetCurSel();
  2561. }
  2562. //-----------------------------------------------------------------------------
  2563. // Purpose: sets the smooth amount
  2564. //-----------------------------------------------------------------------------
  2565. void CSculptCarveOptions::OnEnKillfocusSculptPushOptionSmoothAmount()
  2566. {
  2567. char temp[ 1024 ], t2[ 1024 ];
  2568. m_SmoothAmountControl.GetWindowText( temp, sizeof( temp ) );
  2569. sscanf( temp, "%f%%", &m_SmoothAmount );
  2570. m_SmoothAmount /= 100.0f;
  2571. if ( m_SmoothAmount <= 0.0f )
  2572. {
  2573. m_SmoothAmount = 0.2f;
  2574. }
  2575. sprintf( t2, "%g%%", m_SmoothAmount * 100.0f );
  2576. if ( strcmpi( temp, t2 ) != 0 )
  2577. {
  2578. m_SmoothAmountControl.SetWindowText( t2 );
  2579. }
  2580. }
  2581. //-----------------------------------------------------------------------------
  2582. // Purpose: sets the offset amount
  2583. //-----------------------------------------------------------------------------
  2584. void CSculptCarveOptions::OnEnKillfocusSculptPushOptionOffsetAmount()
  2585. {
  2586. char temp[ 1024 ], t2[ 1024 ];
  2587. m_OffsetAmountControl.GetWindowText( temp, sizeof( temp ) );
  2588. sscanf( temp, "%f%%", &m_OffsetAmount );
  2589. m_OffsetAmount /= 100.0f;
  2590. if ( m_OffsetAmount <= 0.0f )
  2591. {
  2592. m_OffsetAmount = 1.0f;
  2593. }
  2594. sprintf( t2, "%g%%", m_OffsetAmount * 100.0f );
  2595. if ( strcmpi( temp, t2 ) != 0 )
  2596. {
  2597. m_OffsetAmountControl.SetWindowText( t2 );
  2598. }
  2599. }
  2600. //-----------------------------------------------------------------------------
  2601. // Purpose: paints the carve brush
  2602. //-----------------------------------------------------------------------------
  2603. void CSculptCarveOptions::OnPaint()
  2604. {
  2605. CPaintDC dc(this); // device context for painting
  2606. CBrush black( RGB( 0, 0, 0 ) );
  2607. CBrush red( RGB( 255, 0, 0 ) );
  2608. CBrush green( RGB( 0, 255, 0 ) );
  2609. CBrush blue_red( RGB( 64, 0, 128 ) );
  2610. CBrush blue_green( RGB( 0, 64, 128 ) );
  2611. CBrush blue( RGB( 0, 0, 255 ) );
  2612. CRect WindowRect;
  2613. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2614. ScreenToClient( &WindowRect );
  2615. dc.FillRect( WindowRect, &black );
  2616. float center = ( WindowRect.bottom + WindowRect.top ) / 2;
  2617. float height = ( WindowRect.bottom - WindowRect.top ) - 1;
  2618. if ( m_BrushLocation != -1 )
  2619. {
  2620. CRect rect;
  2621. rect.left = ( m_BrushLocation * 2 ) + WindowRect.left;
  2622. rect.right = rect.left + 2;
  2623. rect.bottom = WindowRect.bottom;
  2624. rect.top = WindowRect.top;
  2625. dc.FillRect( rect, &blue );
  2626. }
  2627. for( int i = 0; i < MAX_SCULPT_SIZE; i++ )
  2628. {
  2629. float size = height / 2.0f * m_BrushPoints[ i ];
  2630. CRect rect;
  2631. CBrush *pBrush;
  2632. rect.left = ( i * 2 ) + WindowRect.left;
  2633. rect.right = rect.left + 2;
  2634. rect.bottom = center - size;
  2635. rect.top = center;
  2636. if ( m_BrushPoints[ i ] >= 0.0f )
  2637. {
  2638. if ( m_BrushLocation == i )
  2639. {
  2640. pBrush = &blue_green;
  2641. }
  2642. else
  2643. {
  2644. pBrush = &green;
  2645. }
  2646. }
  2647. else
  2648. {
  2649. if ( m_BrushLocation == i )
  2650. {
  2651. pBrush = &blue_red;
  2652. }
  2653. else
  2654. {
  2655. pBrush = &red;
  2656. }
  2657. }
  2658. dc.FillRect( rect, pBrush );
  2659. }
  2660. }
  2661. //-----------------------------------------------------------------------------
  2662. // Purpose: adjusts the carve brush
  2663. // Input : x - location to set the height to
  2664. // y - offset into the brush
  2665. //-----------------------------------------------------------------------------
  2666. void CSculptCarveOptions::AdjustBrush( int x, int y )
  2667. {
  2668. CRect WindowRect;
  2669. CPoint MousePoint( x, y );
  2670. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2671. ClientToScreen( &MousePoint );
  2672. if ( MousePoint.x >= WindowRect.left && MousePoint.x < WindowRect.right &&
  2673. MousePoint.y >= WindowRect.top && MousePoint.y < WindowRect.bottom )
  2674. {
  2675. int pos = ( MousePoint.x - WindowRect.left ) / 2;
  2676. float center = ( WindowRect.bottom + WindowRect.top ) / 2;
  2677. float value = ( center - MousePoint.y ) / ( WindowRect.bottom - WindowRect.top ) * 2.0f;
  2678. value = clamp( value, -1.0f, 1.0f );
  2679. if ( pos >= 0 && pos < MAX_SCULPT_SIZE )
  2680. {
  2681. m_BrushPoints[ pos ] = value;
  2682. Invalidate();
  2683. }
  2684. }
  2685. }
  2686. //-----------------------------------------------------------------------------
  2687. // Purpose: sets the brush cursor location
  2688. // Input : x - x location of mouse
  2689. // y - y location of mouse
  2690. //-----------------------------------------------------------------------------
  2691. void CSculptCarveOptions::AdjustBrushCursor( int x, int y )
  2692. {
  2693. CRect WindowRect;
  2694. int OldBrushLocation = m_BrushLocation;
  2695. CPoint MousePoint( x, y );
  2696. m_CarveBrushControl.GetWindowRect( &WindowRect );
  2697. ClientToScreen( &MousePoint );
  2698. if ( MousePoint.x >= WindowRect.left && MousePoint.x < WindowRect.right &&
  2699. MousePoint.y >= WindowRect.top && MousePoint.y < WindowRect.bottom )
  2700. {
  2701. m_BrushLocation = ( MousePoint.x - WindowRect.left ) / 2;
  2702. }
  2703. else
  2704. {
  2705. m_BrushLocation = -1;
  2706. }
  2707. if ( OldBrushLocation != m_BrushLocation )
  2708. {
  2709. Invalidate();
  2710. }
  2711. }
  2712. //-----------------------------------------------------------------------------
  2713. // Purpose: handles adjusting the brush
  2714. // Input : nFlags - mouse buttons
  2715. // point - mouse point
  2716. //-----------------------------------------------------------------------------
  2717. void CSculptCarveOptions::OnLButtonDown(UINT nFlags, CPoint point)
  2718. {
  2719. AdjustBrush( point.x, point.y );
  2720. AdjustBrushCursor( point.x, point.y );
  2721. __super::OnLButtonDown(nFlags, point);
  2722. }
  2723. //-----------------------------------------------------------------------------
  2724. // Purpose: handles adjusting the brush
  2725. // Input : nFlags - mouse buttons
  2726. // point - mouse point
  2727. //-----------------------------------------------------------------------------
  2728. void CSculptCarveOptions::OnLButtonUp(UINT nFlags, CPoint point)
  2729. {
  2730. AdjustBrush( point.x, point.y );
  2731. AdjustBrushCursor( point.x, point.y );
  2732. __super::OnLButtonUp(nFlags, point);
  2733. }
  2734. //-----------------------------------------------------------------------------
  2735. // Purpose: handles adjusting the brush
  2736. // Input : nFlags - mouse buttons
  2737. // point - mouse point
  2738. //-----------------------------------------------------------------------------
  2739. void CSculptCarveOptions::OnMouseMove(UINT nFlags, CPoint point)
  2740. {
  2741. if ( nFlags & MK_LBUTTON )
  2742. {
  2743. AdjustBrush( point.x, point.y );
  2744. }
  2745. AdjustBrushCursor( point.x, point.y );
  2746. __super::OnMouseMove(nFlags, point);
  2747. }
  2748. //-----------------------------------------------------------------------------
  2749. // Purpose: we want to handle the messages for mouse events
  2750. //-----------------------------------------------------------------------------
  2751. BOOL CSculptCarveOptions::PreTranslateMessage( MSG* pMsg )
  2752. {
  2753. if ( pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_MOUSEMOVE )
  2754. {
  2755. return FALSE;
  2756. }
  2757. return __super::PreTranslateMessage( pMsg );
  2758. }
  2759. #if 0
  2760. class CSculptRegenerator : public ITextureRegenerator
  2761. {
  2762. public:
  2763. CSculptRegenerator( unsigned char *ImageData, int Width, int Height, enum ImageFormat Format ) :
  2764. m_ImageData( ImageData ),
  2765. m_Width( Width ),
  2766. m_Height( Height ),
  2767. m_Format( Format )
  2768. {
  2769. }
  2770. virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect )
  2771. {
  2772. for (int iFrame = 0; iFrame < pVTFTexture->FrameCount(); ++iFrame )
  2773. {
  2774. for (int iFace = 0; iFace < pVTFTexture->FaceCount(); ++iFace )
  2775. {
  2776. int nWidth = pVTFTexture->Width();
  2777. int nHeight = pVTFTexture->Height();
  2778. int nDepth = pVTFTexture->Depth();
  2779. for (int z = 0; z < nDepth; ++z)
  2780. {
  2781. // Fill mip 0 with a checkerboard
  2782. CPixelWriter pixelWriter;
  2783. pixelWriter.SetPixelMemory( pVTFTexture->Format(), pVTFTexture->ImageData( iFrame, iFace, 0, 0, 0, z ), pVTFTexture->RowSizeInBytes( 0 ) );
  2784. switch( m_Format )
  2785. {
  2786. case IMAGE_FORMAT_BGR888:
  2787. {
  2788. unsigned char *data = m_ImageData;
  2789. for (int y = 0; y < nHeight; ++y)
  2790. {
  2791. pixelWriter.Seek( 0, y );
  2792. for (int x = 0; x < nWidth; ++x)
  2793. {
  2794. pixelWriter.WritePixel( *( data + 2 ), *( data + 1 ), *( data ), 255 );
  2795. data += 3;
  2796. }
  2797. }
  2798. }
  2799. break;
  2800. }
  2801. }
  2802. }
  2803. }
  2804. }
  2805. virtual void Release()
  2806. {
  2807. delete this;
  2808. }
  2809. private:
  2810. unsigned char *m_ImageData;
  2811. int m_Width;
  2812. int m_Height;
  2813. enum ImageFormat m_Format;
  2814. };
  2815. // CSculptProjectOptions dialog
  2816. IMPLEMENT_DYNAMIC(CSculptProjectOptions, CDialog)
  2817. CSculptProjectOptions::CSculptProjectOptions(CWnd* pParent /*=NULL*/) :
  2818. CDialog(CSculptProjectOptions::IDD, pParent),
  2819. CSculptTool()
  2820. {
  2821. m_FileDialog = new CFileDialog(TRUE, NULL, NULL, OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST, "Image Files (*.tga)|*.tga||");
  2822. m_FileDialog->m_ofn.lpstrInitialDir = "";
  2823. m_ImagePixels = NULL;
  2824. m_pTexture = NULL;
  2825. m_pMaterial = NULL;
  2826. m_ProjectX = 100;
  2827. m_ProjectY = 100;
  2828. m_ProjectWidth = 100;
  2829. m_ProjectHeight = 100;
  2830. m_TileWidth = m_TileHeight = 1.0;
  2831. m_OriginalTileWidth = m_TileWidth;
  2832. m_OriginalTileHeight = m_TileHeight;
  2833. m_ProjectLocation.Init( 100.0f, 100.0f, 0.0f );
  2834. m_OriginalProjectLocation = m_ProjectLocation;
  2835. m_ProjectSize.Init( 100.0f, 100.0f, 0.0f );
  2836. m_OriginalProjectSize = m_ProjectSize;
  2837. m_ToolMode = PROJECT_MODE_NONE;
  2838. }
  2839. CSculptProjectOptions::~CSculptProjectOptions()
  2840. {
  2841. delete m_FileDialog;
  2842. if ( m_ImagePixels )
  2843. {
  2844. delete [] m_ImagePixels;
  2845. }
  2846. if ( m_pTexture )
  2847. {
  2848. m_pTexture->DecrementReferenceCount();
  2849. m_pTexture = NULL;
  2850. }
  2851. }
  2852. //-----------------------------------------------------------------------------
  2853. // Purpose: set up the data exchange for the variables
  2854. // Input : pDX - the data exchange object
  2855. //-----------------------------------------------------------------------------
  2856. void CSculptProjectOptions::DoDataExchange(CDataExchange* pDX)
  2857. {
  2858. CDialog::DoDataExchange(pDX);
  2859. DDX_Control(pDX, IDC_PROJECT_SIZE, m_ProjectSizeControl);
  2860. DDX_Control(pDX, IDC_PROJECT_SIZE_NUM, m_ProjectSizeNumControl);
  2861. }
  2862. BEGIN_MESSAGE_MAP(CSculptProjectOptions, CDialog)
  2863. ON_BN_CLICKED(IDC_LOAD_IMAGE, &CSculptProjectOptions::OnBnClickedLoadImage)
  2864. ON_NOTIFY(NM_CUSTOMDRAW, IDC_PROJECT_SIZE, &CSculptProjectOptions::OnNMCustomdrawProjectSize)
  2865. END_MESSAGE_MAP()
  2866. bool CSculptProjectOptions::Paint( CMapView3D *pView, const Vector2D &vPoint, SpatialPaintData_t &spatialData )
  2867. {
  2868. CSculptTool::Paint( pView, vPoint, spatialData );
  2869. switch( m_ToolMode )
  2870. {
  2871. case PROJECT_MODE_SIZE:
  2872. DoSizing( vPoint );
  2873. break;
  2874. case PROJECT_MODE_POSITION:
  2875. DoPosition( vPoint );
  2876. break;
  2877. case PROJECT_MODE_TILE:
  2878. DoTiling( vPoint );
  2879. break;
  2880. }
  2881. return true;
  2882. }
  2883. //-----------------------------------------------------------------------------
  2884. // Purpose: draws the tool in the 3d view
  2885. // Input : pRender - the 3d renderer
  2886. //-----------------------------------------------------------------------------
  2887. void CSculptProjectOptions::RenderTool3D(CRender3D *pRender)
  2888. {
  2889. if ( !m_pMaterial )
  2890. {
  2891. return;
  2892. }
  2893. pRender->PushRenderMode( RENDER_MODE_TEXTURED );
  2894. bool bPopMode = pRender->BeginClientSpace();
  2895. CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
  2896. pRender->BindMaterial( m_pMaterial );
  2897. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  2898. CMeshBuilder meshBuilder;
  2899. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 4 );
  2900. meshBuilder.Position3f( m_ProjectLocation.x, m_ProjectLocation.y, m_ProjectLocation.z );
  2901. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2902. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2903. meshBuilder.AdvanceVertex();
  2904. meshBuilder.Position3f( m_ProjectLocation.x + m_ProjectSize.x, m_ProjectLocation.y, m_ProjectLocation.z );
  2905. meshBuilder.TexCoord2f( 0, m_TileWidth, 0.0f );
  2906. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2907. meshBuilder.AdvanceVertex();
  2908. meshBuilder.Position3f( m_ProjectLocation.x + m_ProjectSize.x, m_ProjectLocation.y + m_ProjectSize.y, m_ProjectLocation.z );
  2909. meshBuilder.TexCoord2f( 0, m_TileWidth, m_TileHeight );
  2910. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2911. meshBuilder.AdvanceVertex();
  2912. meshBuilder.Position3f( m_ProjectLocation.x, m_ProjectLocation.y + m_ProjectSize.y, m_ProjectLocation.z );
  2913. meshBuilder.TexCoord2f( 0, 0.0f, m_TileHeight );
  2914. meshBuilder.Color4ub( 255, 255, 255, 128 );
  2915. meshBuilder.AdvanceVertex();
  2916. meshBuilder.End();
  2917. pMesh->Draw();
  2918. if ( bPopMode )
  2919. {
  2920. pRender->EndClientSpace();
  2921. }
  2922. pRender->PopRenderMode();
  2923. }
  2924. //-----------------------------------------------------------------------------
  2925. // Purpose: handles the left mouse button up in the 3d view
  2926. // Input : pView - the 3d view
  2927. // nFlags - the button flags
  2928. // vPoint - the mouse point
  2929. // Output : returns true if successful
  2930. //-----------------------------------------------------------------------------
  2931. bool CSculptProjectOptions::OnLMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2932. {
  2933. CSculptTool::OnLMouseUp3D( pView, nFlags, vPoint );
  2934. return true;
  2935. }
  2936. //-----------------------------------------------------------------------------
  2937. // Purpose: handles the left mouse button down in the 3d view
  2938. // Input : pView - the 3d view
  2939. // nFlags - the button flags
  2940. // vPoint - the mouse point
  2941. // Output : returns true if successful
  2942. //-----------------------------------------------------------------------------
  2943. bool CSculptProjectOptions::OnLMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2944. {
  2945. CSculptTool::OnLMouseDown3D( pView, nFlags, vPoint );
  2946. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  2947. if( pDispMgr )
  2948. {
  2949. pDispMgr->PreUndo( "Displacement Modifier" );
  2950. }
  2951. PrepareDispForPainting();
  2952. // Handle painting.
  2953. if ( !DoPaint( pView, vPoint ) )
  2954. {
  2955. return false;
  2956. }
  2957. // Finish painting.
  2958. if ( !PostPaint( m_PaintOwner->GetAutoSew() ) )
  2959. {
  2960. return false;
  2961. }
  2962. if( pDispMgr )
  2963. {
  2964. pDispMgr->PostUndo();
  2965. }
  2966. return true;
  2967. }
  2968. bool CSculptProjectOptions::OnRMouseUp3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2969. {
  2970. CSculptTool::OnRMouseUp3D( pView, nFlags, vPoint );
  2971. m_ToolMode = PROJECT_MODE_NONE;
  2972. return true;
  2973. }
  2974. //-----------------------------------------------------------------------------
  2975. // Purpose: handles the right mouse button down in the 3d view
  2976. // Input : pView - the 3d view
  2977. // nFlags - the button flags
  2978. // vPoint - the mouse point
  2979. // Output : returns true if successful
  2980. //-----------------------------------------------------------------------------
  2981. bool CSculptProjectOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  2982. {
  2983. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  2984. m_OriginalProjectSize = m_ProjectSize;
  2985. m_OriginalProjectLocation = m_ProjectLocation;
  2986. m_StartSizingPoint = vPoint;
  2987. if ( m_bCtrlDown )
  2988. {
  2989. m_ToolMode = PROJECT_MODE_SIZE;
  2990. }
  2991. else if ( m_bShiftDown )
  2992. {
  2993. m_ToolMode = PROJECT_MODE_TILE;
  2994. }
  2995. else
  2996. {
  2997. m_ToolMode = PROJECT_MODE_POSITION;
  2998. }
  2999. m_StartSizingPoint = vPoint;
  3000. return true;
  3001. }
  3002. //-----------------------------------------------------------------------------
  3003. // Purpose: handles the mouse move in the 3d view
  3004. // Input : pView - the 3d view
  3005. // nFlags - the button flags
  3006. // vPoint - the mouse point
  3007. // Output : returns true if successful
  3008. //-----------------------------------------------------------------------------
  3009. bool CSculptProjectOptions::OnMouseMove3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  3010. {
  3011. CSculptTool::OnMouseMove3D( pView, nFlags, vPoint );
  3012. return true;
  3013. }
  3014. //-----------------------------------------------------------------------------
  3015. // Purpose: applies the specific push operation onto the displacement
  3016. // Input : pView - the 3d view
  3017. // vPoint - the mouse point
  3018. // pDisp - the displacement to apply the push to
  3019. // pOrigDisp - the original displacement prior to any adjustments
  3020. //-----------------------------------------------------------------------------
  3021. void CSculptProjectOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  3022. {
  3023. Vector vPaintPos, vVert;
  3024. Vector vPaintAxis;
  3025. pView->GetCamera()->GetViewForward( vPaintAxis );
  3026. vPaintAxis = -vPaintAxis;
  3027. vPaintAxis *= ( m_ProjectSizeControl.GetPos() * 16.0f );
  3028. int nVertCount = pDisp->GetSize();
  3029. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  3030. {
  3031. Vector2D ViewVert;
  3032. Vector vTestVert;
  3033. pDisp->GetVert( iVert, vTestVert );
  3034. pView->GetCamera()->WorldToView( vTestVert, ViewVert );
  3035. if ( ViewVert.x >= m_ProjectLocation.x &&
  3036. ViewVert.y >= m_ProjectLocation.y &&
  3037. ViewVert.x <= m_ProjectLocation.x + m_ProjectSize.x &&
  3038. ViewVert.y <= m_ProjectLocation.y + m_ProjectSize.y )
  3039. {
  3040. pDisp->GetVert( iVert, vVert );
  3041. float sCoord = ( ViewVert.x - m_ProjectLocation.x ) / m_ProjectSize.x;
  3042. float tCoord = ( ViewVert.y - m_ProjectLocation.y ) / m_ProjectSize.y;
  3043. sCoord *= m_TileWidth;
  3044. tCoord *= m_TileHeight;
  3045. sCoord -= ( int )sCoord;
  3046. tCoord -= ( int )tCoord;
  3047. int x = ( sCoord * m_Width );
  3048. int y = ( tCoord * m_Height );
  3049. unsigned char *pos = &m_ImagePixels[ ( y * m_Width * 3 ) + ( x * 3 ) ];
  3050. float gray = ( 0.3f * pos[ 2 ] ) + ( 0.59f * pos[ 1 ] ) + ( 0.11f * pos[ 0 ] );
  3051. gray /= 255.0f;
  3052. vPaintPos = vVert + ( vPaintAxis * gray );
  3053. AddToUndo( &pDisp );
  3054. pDisp->Paint_SetValue( iVert, vPaintPos );
  3055. }
  3056. }
  3057. }
  3058. void CSculptProjectOptions::OnBnClickedLoadImage()
  3059. {
  3060. if ( m_FileDialog->DoModal() == IDCANCEL )
  3061. {
  3062. return;
  3063. }
  3064. ReadImage( m_FileDialog->GetPathName() );
  3065. }
  3066. bool CSculptProjectOptions::ReadImage( CString &FileName )
  3067. {
  3068. enum ImageFormat imageFormat;
  3069. float sourceGamma;
  3070. CUtlBuffer buf;
  3071. if ( !g_pFullFileSystem->ReadFile( FileName, NULL, buf ) )
  3072. {
  3073. return false;
  3074. }
  3075. if ( !TGALoader::GetInfo( buf, &m_Width, &m_Height, &imageFormat, &sourceGamma ) )
  3076. {
  3077. return false;
  3078. }
  3079. if ( m_ImagePixels )
  3080. {
  3081. delete [] m_ImagePixels;
  3082. }
  3083. int memRequired = ImageLoader::GetMemRequired( m_Width, m_Height, 1, imageFormat, false );
  3084. m_ImagePixels = new unsigned char[ memRequired ];
  3085. buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
  3086. TGALoader::Load( m_ImagePixels, buf, m_Width, m_Height, imageFormat, sourceGamma, false );
  3087. m_pTexture = dynamic_cast< ITextureInternal * >( g_pMaterialSystem->CreateProceduralTexture( "SculptProject", TEXTURE_GROUP_OTHER, m_Width, m_Height, imageFormat,
  3088. TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL ) );
  3089. ITextureRegenerator *pRegen = new CSculptRegenerator( m_ImagePixels, m_Width, m_Height, imageFormat );
  3090. m_pTexture->SetTextureRegenerator( pRegen );
  3091. m_pTexture->Download();
  3092. m_pMaterial = MaterialSystemInterface()->FindMaterial( "editor/sculpt", TEXTURE_GROUP_OTHER );
  3093. return true;
  3094. }
  3095. bool CSculptProjectOptions::DoSizing( const Vector2D &vPoint )
  3096. {
  3097. m_ProjectSize.x = m_OriginalProjectSize.x + ( vPoint.x - m_StartSizingPoint.x );
  3098. if ( m_ProjectSize.x < 1.0f )
  3099. {
  3100. m_ProjectSize.x = 1.0f;
  3101. }
  3102. m_ProjectSize.y = m_OriginalProjectSize.y + ( vPoint.y - m_StartSizingPoint.y );
  3103. if ( m_ProjectSize.y < 1.0f )
  3104. {
  3105. m_ProjectSize.y = 1.0f;
  3106. }
  3107. return true;
  3108. }
  3109. bool CSculptProjectOptions::DoPosition( const Vector2D &vPoint )
  3110. {
  3111. m_ProjectLocation.x = m_OriginalProjectLocation.x + ( vPoint.x - m_StartSizingPoint.x );
  3112. m_ProjectLocation.y = m_OriginalProjectLocation.y + ( vPoint.y - m_StartSizingPoint.y );
  3113. return true;
  3114. }
  3115. bool CSculptProjectOptions::DoTiling( const Vector2D &vPoint )
  3116. {
  3117. m_TileWidth += ( vPoint.x - m_StartSizingPoint.x ) / m_ProjectSize.x;
  3118. m_TileHeight += ( vPoint.y - m_StartSizingPoint.y ) / m_ProjectSize.y;
  3119. m_StartSizingPoint = vPoint;
  3120. return true;
  3121. }
  3122. void CSculptProjectOptions::OnNMCustomdrawProjectSize(NMHDR *pNMHDR, LRESULT *pResult)
  3123. {
  3124. // LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  3125. char temp[ 128 ];
  3126. sprintf( temp, "%d", m_ProjectSizeControl.GetPos() * 16 );
  3127. m_ProjectSizeNumControl.SetWindowText( temp );
  3128. *pResult = 0;
  3129. }
  3130. //-----------------------------------------------------------------------------
  3131. // Purpose: initializes the dialog
  3132. // Output : returns true if successful
  3133. //-----------------------------------------------------------------------------
  3134. BOOL CSculptProjectOptions::OnInitDialog()
  3135. {
  3136. __super::OnInitDialog();
  3137. m_ProjectSizeControl.SetRange( 1, 32 );
  3138. m_ProjectSizeControl.SetTicFreq( 1 );
  3139. m_ProjectSizeControl.SetPageSize( 4 );
  3140. m_ProjectSizeControl.SetLineSize( 4 );
  3141. return TRUE;
  3142. }
  3143. #endif
  3144. // current mouse position updates location of rectangle
  3145. // then rmb = size
  3146. // +control = st adjust
  3147. CTextureButton::CTextureButton( ) :
  3148. CButton()
  3149. {
  3150. m_pTexure = NULL;
  3151. m_bSelected = false;
  3152. }
  3153. void CTextureButton::SetTexture( IEditorTexture *pTexture )
  3154. {
  3155. m_pTexure = pTexture;
  3156. }
  3157. void CTextureButton::SetSelected( bool bSelected )
  3158. {
  3159. m_bSelected = bSelected;
  3160. Invalidate();
  3161. }
  3162. BOOL CTextureButton::PreCreateWindow(CREATESTRUCT& cs)
  3163. {
  3164. cs.style |= BS_OWNERDRAW;
  3165. return __super::PreCreateWindow( cs );
  3166. }
  3167. void CTextureButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  3168. {
  3169. #if 0
  3170. UINT uStyle = DFCS_BUTTONPUSH;
  3171. // This code only works with buttons.
  3172. ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
  3173. // If drawing selected, add the pushed style to DrawFrameControl.
  3174. if (lpDrawItemStruct->itemState & ODS_SELECTED)
  3175. uStyle |= DFCS_PUSHED;
  3176. // Draw the button frame.
  3177. ::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem,
  3178. DFC_BUTTON, uStyle);
  3179. // Get the button's text.
  3180. CString strText;
  3181. GetWindowText(strText);
  3182. // Draw the button text using the text color red.
  3183. COLORREF crOldColor = ::SetTextColor(lpDrawItemStruct->hDC, RGB(255,0,0));
  3184. ::DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),
  3185. &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  3186. ::SetTextColor(lpDrawItemStruct->hDC, crOldColor);
  3187. #endif
  3188. UINT uStyle = DFCS_BUTTONPUSH;
  3189. COLORREF dwForeColor = GetSysColor( COLOR_BTNTEXT );
  3190. // If drawing selected, add the pushed style to DrawFrameControl.
  3191. if (lpDrawItemStruct->itemState & ODS_SELECTED)
  3192. {
  3193. dwForeColor = GetSysColor( COLOR_BTNTEXT );
  3194. uStyle |= DFCS_PUSHED;
  3195. }
  3196. if ( m_bSelected == true )
  3197. {
  3198. dwForeColor = RGB( 200, 0, 0 );
  3199. }
  3200. ::DrawFrameControl( lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle );
  3201. CDC dc;
  3202. dc.Attach( lpDrawItemStruct->hDC );
  3203. dc.SaveDC();
  3204. RECT& r = lpDrawItemStruct->rcItem;
  3205. int iFontHeight = dc.GetTextExtent( "J", 1 ).cy;
  3206. dc.SetROP2( R2_COPYPEN );
  3207. CPalette *pOldPalette = NULL;
  3208. if (m_pTexure != NULL)
  3209. {
  3210. m_pTexure->Load();
  3211. pOldPalette = dc.SelectPalette( m_pTexure->HasPalette() ? m_pTexure->GetPalette() : g_pGameConfig->Palette, FALSE );
  3212. dc.RealizePalette();
  3213. }
  3214. if ( m_pTexure != NULL )
  3215. {
  3216. char szName[ MAX_PATH ];
  3217. int iLen = m_pTexure->GetShortName( szName );
  3218. // crop to just the name without path
  3219. const char *pszTextureName = V_UnqualifiedFileName( szName );
  3220. iLen = strlen( pszTextureName );
  3221. DrawTexData_t DrawTexData;
  3222. DrawTexData.nFlags = 0;
  3223. int nWidth = m_pTexure->GetPreviewImageWidth();
  3224. int nHeight = m_pTexure->GetPreviewImageHeight();
  3225. CRect r2(r);
  3226. r2.InflateRect( -4, -4 );
  3227. if ( m_pTexure->IsLoaded() && nWidth > 0 && nHeight > 0 )
  3228. {
  3229. // draw graphic
  3230. int nDrawWidth = 64;
  3231. int nDrawHeight = nDrawWidth * nHeight / nWidth;
  3232. if ( nDrawHeight > r2.bottom - r2.top )
  3233. {
  3234. nDrawHeight = r2.bottom - r2.top;
  3235. nDrawWidth = nDrawHeight * nWidth / nHeight;
  3236. }
  3237. r2.right = r2.left + nDrawWidth;
  3238. r2.bottom = r2.top + nDrawHeight;
  3239. m_pTexure->Draw( &dc, r2, 0, 0, DrawTexData );
  3240. }
  3241. else
  3242. {
  3243. int nDrawSize = r2.bottom - r2.top;
  3244. r2.right = r2.left + nDrawSize;
  3245. r2.bottom = r2.top + nDrawSize;
  3246. }
  3247. // draw name
  3248. dc.SetTextColor( dwForeColor );
  3249. dc.SetBkMode( TRANSPARENT );
  3250. dc.TextOut( r2.right + 4, r2.top + 4, pszTextureName, iLen );
  3251. // draw size
  3252. sprintf( szName, "%dx%d", m_pTexure->GetWidth(), m_pTexure->GetHeight() );
  3253. dc.TextOut( r2.right + 4, r2.top + 4 + iFontHeight, szName, strlen( szName ) );
  3254. }
  3255. if (pOldPalette)
  3256. {
  3257. dc.SelectPalette( pOldPalette, FALSE );
  3258. }
  3259. dc.RestoreDC( -1 );
  3260. dc.Detach();
  3261. }
  3262. BEGIN_MESSAGE_MAP(CColorButton, CButton)
  3263. END_MESSAGE_MAP()
  3264. CColorButton::CColorButton( ) :
  3265. CButton()
  3266. {
  3267. m_flRed = m_flGreen = m_flBlue = 1.0f;
  3268. }
  3269. void CColorButton::SetColor( float flRed, float flGreen, float flBlue )
  3270. {
  3271. m_flRed = flRed;
  3272. m_flGreen = flGreen;
  3273. m_flBlue = flBlue;
  3274. Invalidate();
  3275. }
  3276. BOOL CColorButton::PreCreateWindow(CREATESTRUCT& cs)
  3277. {
  3278. cs.style |= BS_OWNERDRAW;
  3279. return __super::PreCreateWindow( cs );
  3280. }
  3281. void CColorButton::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  3282. {
  3283. UINT uStyle = DFCS_BUTTONPUSH;
  3284. // This code only works with buttons.
  3285. ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);
  3286. // If drawing selected, add the pushed style to DrawFrameControl.
  3287. if (lpDrawItemStruct->itemState & ODS_SELECTED)
  3288. uStyle |= DFCS_PUSHED;
  3289. CDC dc;
  3290. dc.Attach( lpDrawItemStruct->hDC );
  3291. dc.SaveDC();
  3292. COLORREF dwBackColor = RGB( m_flRed * 255, m_flGreen * 255, m_flBlue * 255 );
  3293. // Draw the button frame.
  3294. ::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem,
  3295. DFC_BUTTON, uStyle);
  3296. // draw background
  3297. CBrush brush;
  3298. CRect r2( lpDrawItemStruct->rcItem );
  3299. brush.CreateSolidBrush( dwBackColor) ;
  3300. r2.InflateRect( -4, -4 );
  3301. dc.FillRect( &r2, &brush );
  3302. dc.RestoreDC( -1 );
  3303. dc.Detach();
  3304. }
  3305. // CSculptBlendOptions dialog
  3306. IMPLEMENT_DYNAMIC(CSculptBlendOptions, CDialog)
  3307. //-----------------------------------------------------------------------------
  3308. // Purpose: constructor
  3309. //-----------------------------------------------------------------------------
  3310. CSculptBlendOptions::CSculptBlendOptions(CWnd* pParent /*=NULL*/) :
  3311. CDialog(CSculptBlendOptions::IDD, pParent),
  3312. CSculptPainter()
  3313. {
  3314. m_flFalloffSpot = 0.5f;
  3315. m_flFalloffEndingValue = 0.0f;
  3316. m_Direction = 1.0f;
  3317. m_nSelectedTexture = 0;
  3318. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3319. {
  3320. m_ColorMode[ i ] = COLOR_MODE_SINGLE;
  3321. m_vStartDrawColor[ i ].Init( 1.0f, 1.0f, 1.0f );
  3322. m_vEndDrawColor[ i ].Init( 1.0f, 1.0f, 1.0f );
  3323. }
  3324. m_nDefaultFalloffPosition = 50;
  3325. m_nDefaultFalloffFinal = 0;
  3326. m_nDefaultBlendAmount = 50;
  3327. m_nDefaultColorBlendAmount = 0;
  3328. m_nDefaultAlphaBlendAmount = 0;
  3329. m_b4WayBlendMode = false;
  3330. }
  3331. //-----------------------------------------------------------------------------
  3332. // Purpose: destructor
  3333. //-----------------------------------------------------------------------------
  3334. CSculptBlendOptions::~CSculptBlendOptions()
  3335. {
  3336. }
  3337. //-----------------------------------------------------------------------------
  3338. // Purpose: initializes the dialog
  3339. // Output : returns true if successful
  3340. //-----------------------------------------------------------------------------
  3341. BOOL CSculptBlendOptions::OnInitDialog( void )
  3342. {
  3343. CDialog::OnInitDialog();
  3344. m_FalloffPositionControl.SetRange( 0, 100 );
  3345. m_FalloffPositionControl.SetTicFreq( 10 );
  3346. m_FalloffPositionControl.SetPos( m_nDefaultFalloffPosition );
  3347. m_FalloffFinalControl.SetRange( 0, 100 );
  3348. m_FalloffFinalControl.SetTicFreq( 10 );
  3349. m_FalloffFinalControl.SetPos( m_nDefaultFalloffFinal );
  3350. m_BlendAmountControl.SetRange( 0, 100 );
  3351. m_BlendAmountControl.SetTicFreq( 10 );
  3352. m_BlendAmountControl.SetPos( m_nDefaultBlendAmount );
  3353. m_ColorBlendAmountControl.SetRange( 0, 100 );
  3354. m_ColorBlendAmountControl.SetTicFreq( 10 );
  3355. m_ColorBlendAmountControl.SetPos( m_nDefaultColorBlendAmount );
  3356. m_AlphaBlendAmountControl.SetRange( 0, 100 );
  3357. m_AlphaBlendAmountControl.SetTicFreq( 10 );
  3358. m_AlphaBlendAmountControl.SetPos( m_nDefaultAlphaBlendAmount );
  3359. m_BlendColorOperationControl.InsertString( -1, "Single");
  3360. m_BlendColorOperationControl.InsertString( -1, "Blend");
  3361. m_BlendColorOperationControl.InsertString( -1, "Or");
  3362. return TRUE;
  3363. }
  3364. void CSculptBlendOptions::SetColorMode( ColorMode NewMode, bool bSetDialog )
  3365. {
  3366. m_ColorMode[ m_nSelectedTexture ] = NewMode;
  3367. switch( m_ColorMode[ m_nSelectedTexture ] )
  3368. {
  3369. case COLOR_MODE_SINGLE:
  3370. m_ColorEndControl.ShowWindow( SW_HIDE );
  3371. break;
  3372. case COLOR_MODE_RANGE:
  3373. m_ColorEndControl.ShowWindow( SW_SHOW );
  3374. break;
  3375. case COLOR_MODE_OR:
  3376. m_ColorEndControl.ShowWindow( SW_SHOW );
  3377. break;
  3378. }
  3379. if ( bSetDialog == true )
  3380. {
  3381. m_BlendColorOperationControl.SetCurSel( m_ColorMode[ m_nSelectedTexture ] );
  3382. }
  3383. }
  3384. void CSculptBlendOptions::SelectTexture( int nTexture )
  3385. {
  3386. m_nSelectedTexture = nTexture;
  3387. m_ColorStartControl.SetColor( m_vStartDrawColor[ m_nSelectedTexture ].x, m_vStartDrawColor[ m_nSelectedTexture ].y, m_vStartDrawColor[ m_nSelectedTexture ].z );
  3388. m_ColorEndControl.SetColor( m_vEndDrawColor[ m_nSelectedTexture ].x, m_vEndDrawColor[ m_nSelectedTexture ].y, m_vEndDrawColor[ m_nSelectedTexture ].z );
  3389. SetColorMode( m_ColorMode[ m_nSelectedTexture ], true );
  3390. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3391. {
  3392. m_ColorMaskControl[ i ].SetCheck( ( i == m_nSelectedTexture ? BST_CHECKED : BST_UNCHECKED ) );
  3393. }
  3394. }
  3395. //-----------------------------------------------------------------------------
  3396. // Purpose: prevent the dialog from closing
  3397. //-----------------------------------------------------------------------------
  3398. void CSculptBlendOptions::OnOK()
  3399. {
  3400. }
  3401. //-----------------------------------------------------------------------------
  3402. // Purpose: prevent the dialog from closing
  3403. //-----------------------------------------------------------------------------
  3404. void CSculptBlendOptions::OnCancel()
  3405. {
  3406. }
  3407. //-----------------------------------------------------------------------------
  3408. // Purpose: set up the data exchange for the variables
  3409. // Input : pDX - the data exchange object
  3410. //-----------------------------------------------------------------------------
  3411. void CSculptBlendOptions::DoDataExchange(CDataExchange* pDX)
  3412. {
  3413. CDialog::DoDataExchange(pDX);
  3414. DDX_Control(pDX, IDC_BLEND_AMOUNT, m_BlendAmountControl);
  3415. DDX_Control(pDX, IDC_BLEND_AMOUNT_TEXT, m_BlendAmountTextControl);
  3416. DDX_Control(pDX, IDC_TEXTURE_BUTTON1, m_TextureControl[ 0 ]);
  3417. DDX_Control(pDX, IDC_TEXTURE_BUTTON2, m_TextureControl[ 1 ]);
  3418. DDX_Control(pDX, IDC_TEXTURE_BUTTON3, m_TextureControl[ 2 ]);
  3419. DDX_Control(pDX, IDC_TEXTURE_BUTTON4, m_TextureControl[ 3 ]);
  3420. DDX_Control(pDX, IDC_TEXTURE1_MASK, m_TextureMaskControl[ 0 ]);
  3421. DDX_Control(pDX, IDC_TEXTURE2_MASK, m_TextureMaskControl[ 1 ]);
  3422. DDX_Control(pDX, IDC_TEXTURE3_MASK, m_TextureMaskControl[ 2 ]);
  3423. DDX_Control(pDX, IDC_TEXTURE4_MASK, m_TextureMaskControl[ 3 ]);
  3424. DDX_Control(pDX, IDC_COLOR1_MASK, m_ColorMaskControl[ 0 ]);
  3425. DDX_Control(pDX, IDC_COLOR2_MASK, m_ColorMaskControl[ 1 ]);
  3426. DDX_Control(pDX, IDC_COLOR3_MASK, m_ColorMaskControl[ 2 ]);
  3427. DDX_Control(pDX, IDC_COLOR4_MASK, m_ColorMaskControl[ 3 ]);
  3428. DDX_Control(pDX, IDC_COLOR_BLEND_AMOUNT, m_ColorBlendAmountControl);
  3429. DDX_Control(pDX, IDC_COLOR_BLEND_AMOUNT_TEXT, m_ColorBlendAmountTextControl);
  3430. DDX_Control(pDX, IDC_SET_COLOR, m_ColorStartControl);
  3431. DDX_Control(pDX, IDC_SET_COLOR2, m_ColorEndControl);
  3432. DDX_Control(pDX, IDC_BLEND_COLOR_OPERATION, m_BlendColorOperationControl);
  3433. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_POSITION, m_FalloffPositionControl);
  3434. DDX_Control(pDX, IDC_SCULPT_PUSH_OPTION_FALLOFF_FINAL, m_FalloffFinalControl);
  3435. DDX_Control(pDX, IDC_ALPHA_BLEND_AMOUNT, m_AlphaBlendAmountControl);
  3436. DDX_Control(pDX, IDC_ALPHA_BLEND_AMOUNT_TEXT, m_AlphaBlendAmountTextControl);
  3437. }
  3438. BEGIN_MESSAGE_MAP(CSculptBlendOptions, CDialog)
  3439. ON_NOTIFY(NM_CUSTOMDRAW, IDC_BLEND_AMOUNT, &CSculptBlendOptions::OnNMCustomdrawBlendAmount)
  3440. ON_WM_SHOWWINDOW()
  3441. ON_BN_CLICKED(IDC_TEXTURE_BUTTON1, &CSculptBlendOptions::OnBnClickedTextureButton1)
  3442. ON_BN_CLICKED(IDC_TEXTURE_BUTTON2, &CSculptBlendOptions::OnBnClickedTextureButton2)
  3443. ON_BN_CLICKED(IDC_TEXTURE_BUTTON3, &CSculptBlendOptions::OnBnClickedTextureButton3)
  3444. ON_BN_CLICKED(IDC_TEXTURE_BUTTON4, &CSculptBlendOptions::OnBnClickedTextureButton4)
  3445. ON_COMMAND(ID_BLEND_SELECT_TEXTURE_1, &CSculptBlendOptions::OnBnClickedTextureButton1)
  3446. ON_COMMAND(ID_BLEND_SELECT_TEXTURE_2, &CSculptBlendOptions::OnBnClickedTextureButton2)
  3447. ON_COMMAND(ID_BLEND_SELECT_TEXTURE_3, &CSculptBlendOptions::OnBnClickedTextureButton3)
  3448. ON_COMMAND(ID_BLEND_SELECT_TEXTURE_4, &CSculptBlendOptions::OnBnClickedTextureButton4)
  3449. ON_COMMAND(ID_BLEND_SHRINK_BRUSH, &CSculptBlendOptions::ShrinkBrush)
  3450. ON_COMMAND(ID_BLEND_ENLARGE_BRUSH, &CSculptBlendOptions::EnlargeBrush)
  3451. ON_BN_CLICKED(IDC_SET_COLOR, &CSculptBlendOptions::OnBnClickedSetColor)
  3452. ON_BN_CLICKED(IDC_SET_COLOR2, &CSculptBlendOptions::OnBnClickedSetColor2)
  3453. ON_NOTIFY(NM_CUSTOMDRAW, IDC_COLOR_BLEND_AMOUNT, &CSculptBlendOptions::OnNMCustomdrawColorBlendAmount)
  3454. ON_CBN_SELCHANGE(IDC_BLEND_COLOR_OPERATION, &CSculptBlendOptions::OnCbnSelchangeBlendColorOperation)
  3455. ON_NOTIFY(NM_CUSTOMDRAW, IDC_ALPHA_BLEND_AMOUNT, &CSculptBlendOptions::OnNMCustomdrawAlphaBlendAmount)
  3456. ON_WM_RBUTTONDBLCLK()
  3457. END_MESSAGE_MAP()
  3458. void CSculptBlendOptions::OnShowWindow(BOOL bShow, UINT nStatus)
  3459. {
  3460. __super::OnShowWindow(bShow, nStatus);
  3461. if ( bShow == FALSE )
  3462. {
  3463. m_nDefaultFalloffPosition = m_FalloffPositionControl.GetPos();
  3464. m_nDefaultFalloffFinal = m_FalloffFinalControl.GetPos();
  3465. m_nDefaultBlendAmount = m_BlendAmountControl.GetPos();
  3466. m_nDefaultColorBlendAmount = m_ColorBlendAmountControl.GetPos();
  3467. m_nDefaultAlphaBlendAmount = m_AlphaBlendAmountControl.GetPos();
  3468. APP()->ClearCustomAccelerator();
  3469. return;
  3470. }
  3471. // Get the displacement manager from the active map document.
  3472. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  3473. if( pDispMgr )
  3474. {
  3475. int nDispCount = pDispMgr->SelectCount();
  3476. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  3477. {
  3478. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  3479. if ( pDisp )
  3480. {
  3481. CMapFace *pFace = static_cast< CMapFace * >( pDisp->GetParent() );
  3482. IMaterial *pMaterial = pFace->GetTexture()->GetMaterial();
  3483. if ( strcmpi( pMaterial->GetShaderName(), "Lightmapped_4WayBlend" ) == 0 )
  3484. {
  3485. m_b4WayBlendMode = true;
  3486. }
  3487. else
  3488. {
  3489. m_b4WayBlendMode = false;
  3490. }
  3491. for( int i = 1; i <= MAX_MULTIBLEND_CHANNELS; i++ )
  3492. {
  3493. char temp[ 128 ];
  3494. if ( i == 1 )
  3495. {
  3496. sprintf( temp, "$basetexture" );
  3497. }
  3498. else
  3499. {
  3500. sprintf( temp, "$basetexture%d", i );
  3501. }
  3502. IMaterialVar *pMaterialVar = pMaterial->FindVar( temp, NULL, false );
  3503. if ( pMaterialVar != NULL )
  3504. {
  3505. IEditorTexture *pTexture = g_Textures.FindActiveTexture( pMaterialVar->GetStringValue() );
  3506. pTexture->Load();
  3507. m_TextureControl[ i - 1 ].SetTexture( pTexture );
  3508. m_TextureControl[ i - 1 ].SetSelected( ( m_nSelectedTexture == i - 1 ) );
  3509. m_TextureMaskControl[ i - 1 ].SetCheck( BST_CHECKED );
  3510. m_ColorMaskControl[ i - 1 ].SetCheck( BST_UNCHECKED );
  3511. }
  3512. m_ColorMaskControl[ i - 1 ].EnableWindow( !m_b4WayBlendMode );
  3513. }
  3514. m_AlphaBlendAmountControl.EnableWindow( !m_b4WayBlendMode );
  3515. m_AlphaBlendAmountTextControl.EnableWindow( !m_b4WayBlendMode );
  3516. m_ColorBlendAmountControl.EnableWindow( !m_b4WayBlendMode );
  3517. m_ColorBlendAmountTextControl.EnableWindow( !m_b4WayBlendMode );
  3518. m_BlendColorOperationControl.EnableWindow( !m_b4WayBlendMode );
  3519. m_ColorStartControl.EnableWindow( !m_b4WayBlendMode );
  3520. m_ColorEndControl.EnableWindow( !m_b4WayBlendMode );
  3521. break;
  3522. }
  3523. }
  3524. }
  3525. m_TextureControl[ m_nSelectedTexture ].SetSelected( true );
  3526. SelectTexture( m_nSelectedTexture );
  3527. APP()->SetCustomAccelerator( m_hWnd, IDR_BLEND_ACCELERATOR );
  3528. }
  3529. //-----------------------------------------------------------------------------
  3530. // Purpose: setup for starting to paint on the displacement
  3531. // Input : pView - the 3d view
  3532. // vPoint - the initial click point
  3533. // Output : returns true if successful
  3534. //-----------------------------------------------------------------------------
  3535. bool CSculptBlendOptions::BeginPaint( CMapView3D *pView, const Vector2D &vPoint )
  3536. {
  3537. __super::BeginPaint( pView, vPoint );
  3538. if ( m_bCtrlDown )
  3539. {
  3540. m_Direction = -1.0f;
  3541. }
  3542. else
  3543. {
  3544. m_Direction = 1.0f;
  3545. }
  3546. m_nLastCollideDisplacement = -1;
  3547. return true;
  3548. }
  3549. //-----------------------------------------------------------------------------
  3550. // Purpose: draws the tool in the 3d view
  3551. // Input : pRender - the 3d renderer
  3552. //-----------------------------------------------------------------------------
  3553. void CSculptBlendOptions::RenderTool3D( CRender3D *pRender )
  3554. {
  3555. pRender->PushRenderMode( RENDER_MODE_WIREFRAME );
  3556. m_flFalloffSpot = m_FalloffPositionControl.GetPos() / 100.0f;
  3557. m_flFalloffEndingValue = m_FalloffFinalControl.GetPos() / 100.0f;
  3558. if ( m_InSizingMode )
  3559. { // yellow for sizing mode
  3560. pRender->BeginClientSpace();
  3561. pRender->SetDrawColor( 255, 255, 0 );
  3562. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  3563. if ( m_flFalloffSpot > 0.0f )
  3564. {
  3565. pRender->SetDrawColor( 192, 192, 0 );
  3566. pRender->DrawCircle( Vector( m_StartSizingPoint.x, m_StartSizingPoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  3567. }
  3568. pRender->EndClientSpace();
  3569. }
  3570. else if ( m_Direction < 0.0f )
  3571. { // red for negative blending
  3572. pRender->BeginClientSpace();
  3573. pRender->SetDrawColor( 255, 0, 0 );
  3574. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  3575. if ( m_flFalloffSpot > 0.0f )
  3576. {
  3577. pRender->SetDrawColor( 192, 0, 0 );
  3578. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  3579. }
  3580. pRender->EndClientSpace();
  3581. }
  3582. else
  3583. { // green for positive blending
  3584. pRender->BeginClientSpace();
  3585. pRender->SetDrawColor( 0, 255, 0 );
  3586. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize, 32 );
  3587. if ( m_flFalloffSpot > 0.0f )
  3588. {
  3589. pRender->SetDrawColor( 0, 192, 0 );
  3590. pRender->DrawCircle( Vector( m_MousePoint.x, m_MousePoint.y, 0.0f ), Vector( 0.0f, 0.0f, 1.0f ), m_BrushSize * m_flFalloffSpot, 32 );
  3591. }
  3592. pRender->EndClientSpace();
  3593. }
  3594. pRender->PopRenderMode();
  3595. }
  3596. //-----------------------------------------------------------------------------
  3597. // Purpose: handles the right mouse button down in the 3d view
  3598. // Input : pView - the 3d view
  3599. // nFlags - the button flags
  3600. // vPoint - the mouse point
  3601. // Output : returns true if successful
  3602. //-----------------------------------------------------------------------------
  3603. bool CSculptBlendOptions::OnRMouseDown3D( CMapView3D *pView, UINT nFlags, const Vector2D &vPoint )
  3604. {
  3605. CSculptTool::OnRMouseDown3D( pView, nFlags, vPoint );
  3606. return true;
  3607. }
  3608. bool CSculptBlendOptions::DoPaint( CMapView3D *pView, const Vector2D &vPoint )
  3609. {
  3610. Vector vCollisionPoint, vCollisionNormal;
  3611. float flCollisionIntercept;
  3612. int nCollideDisplacement, nCollideTri;
  3613. if ( FindCollisionIntercept( pView->GetCamera(), vPoint, true, vCollisionPoint, vCollisionNormal, flCollisionIntercept, &nCollideDisplacement, &nCollideTri ) == false )
  3614. {
  3615. return false;
  3616. }
  3617. // if ( m_nLastCollideDisplacement != -1 && m_nLastCollideDisplacement == nCollideDisplacement && m_nLastCollideTri == nCollideTri )
  3618. // {
  3619. // return false;
  3620. // }
  3621. m_nLastCollideDisplacement = nCollideDisplacement;
  3622. m_nLastCollideTri = nCollideTri;
  3623. return __super::DoPaint( pView, vPoint );
  3624. }
  3625. //-----------------------------------------------------------------------------
  3626. // Purpose: applies the specific push operation onto the displacement
  3627. // Input : pView - the 3d view
  3628. // vPoint - the mouse point
  3629. // pDisp - the displacement to apply the push to
  3630. // pOrigDisp - the original displacement prior to any adjustments
  3631. //-----------------------------------------------------------------------------
  3632. void CSculptBlendOptions::DoPaintOperation( CMapView3D *pView, const Vector2D &vPoint, CMapDisp *pDisp, CMapDisp *pOrigDisp )
  3633. {
  3634. Vector4D vBlend, vPaintBlend;
  3635. Vector4D vAlphaBlend, vPaintAlphaBlend;
  3636. Vector vColor[ MAX_MULTIBLEND_CHANNELS ], vPaintColor[ MAX_MULTIBLEND_CHANNELS ];
  3637. float flDistance;
  3638. float flLengthPercent;
  3639. int nIndex = m_nSelectedTexture;
  3640. float flTextureBlendAmount = ( float )m_BlendAmountControl.GetPos() / 2000.0f;
  3641. float flColorBlendAmount = ( float )m_ColorBlendAmountControl.GetPos() / 2000.0f;
  3642. float flAlphaBlendAmount = ( float )m_AlphaBlendAmountControl.GetPos() / 1000.0f;
  3643. bool bDrawTexture = ( m_BlendAmountControl.GetPos() > 0 );
  3644. bool bDrawAlpha = ( m_AlphaBlendAmountControl.GetPos() > 0 );
  3645. bool bDrawColor = ( m_ColorBlendAmountControl.GetPos() > 0 );
  3646. bool bDrawTextureChannel[ MAX_MULTIBLEND_CHANNELS ], bDrawColorChannel[ MAX_MULTIBLEND_CHANNELS ];
  3647. m_flFalloffSpot = m_FalloffPositionControl.GetPos() / 100.0f;
  3648. m_flFalloffEndingValue = m_FalloffFinalControl.GetPos() / 100.0f;
  3649. if ( nIndex < 0 )
  3650. {
  3651. return;
  3652. }
  3653. flAlphaBlendAmount *= m_Direction;
  3654. if ( WinTab_Opened() == true )
  3655. {
  3656. flTextureBlendAmount *= WinTab_GetPressure();
  3657. flColorBlendAmount *= WinTab_GetPressure();
  3658. flAlphaBlendAmount *= WinTab_GetPressure();
  3659. }
  3660. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3661. {
  3662. bDrawTextureChannel[ i ] = ( bDrawTexture == true && m_TextureMaskControl[ i ].GetCheck() == BST_CHECKED );
  3663. bDrawColorChannel[ i ] = ( bDrawColor == true && m_ColorMaskControl[ i ].GetCheck() == BST_CHECKED );
  3664. }
  3665. AddToUndo( &pDisp );
  3666. int nVertCount = pDisp->GetSize();
  3667. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  3668. {
  3669. if ( IsPointInScreenCircle( pView, pDisp, pOrigDisp, iVert, true, false, &flLengthPercent ) )
  3670. {
  3671. pDisp->GetMultiBlend( iVert, vBlend, vAlphaBlend, vColor[ 0 ], vColor[ 1 ], vColor[ 2 ], vColor[ 3 ] );
  3672. if ( flLengthPercent > m_flFalloffSpot )
  3673. {
  3674. flLengthPercent = ( flLengthPercent - m_flFalloffSpot ) / ( 1.0f - m_flFalloffSpot );
  3675. flLengthPercent = 1.0 - flLengthPercent;
  3676. flDistance = ( ( 1.0f - m_flFalloffEndingValue ) * flLengthPercent ) + ( m_flFalloffEndingValue );
  3677. }
  3678. else
  3679. {
  3680. flDistance = 1.0f;
  3681. }
  3682. if ( flDistance == 0.0f )
  3683. {
  3684. continue;
  3685. }
  3686. float flTextureAmount = flTextureBlendAmount * flDistance;
  3687. float flColorAmount = flColorBlendAmount * flDistance;
  3688. float flAlphaAmount = flAlphaBlendAmount * flDistance;
  3689. vPaintBlend = vBlend;
  3690. vPaintAlphaBlend = vAlphaBlend;
  3691. vPaintColor[ 0 ] = vColor[ 0 ];
  3692. vPaintColor[ 1 ] = vColor[ 1 ];
  3693. vPaintColor[ 2 ] = vColor[ 2 ];
  3694. vPaintColor[ 3 ] = vColor[ 3 ];
  3695. Assert( MAX_MULTIBLEND_CHANNELS == 4 );
  3696. if ( bDrawTexture == true )
  3697. {
  3698. if ( m_Direction > 0.0f )
  3699. {
  3700. if ( nIndex == 4 )
  3701. {
  3702. float flRemainder = flTextureAmount;
  3703. #if 1
  3704. // for( int i = 1; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3705. for( int i = MAX_MULTIBLEND_CHANNELS - 1; i > 0; i-- )
  3706. {
  3707. if ( bDrawTextureChannel[ i ] == false )
  3708. {
  3709. continue;
  3710. }
  3711. if ( vPaintBlend[ i ] > flRemainder )
  3712. {
  3713. vPaintBlend[ i ] -= flRemainder;
  3714. flRemainder = 0.0f;
  3715. break;
  3716. }
  3717. else
  3718. {
  3719. flRemainder -= vPaintBlend[ i ];
  3720. vPaintBlend[ i ] = 0.0f;
  3721. }
  3722. }
  3723. #else
  3724. for( int i = MAX_MULTIBLEND_CHANNELS - 1; i > 0; i-- )
  3725. {
  3726. if ( m_TextureMaskControl[ i ].GetCheck() != BST_CHECKED )
  3727. {
  3728. continue;
  3729. }
  3730. if ( vPaintBlend[ i ] > flRemainder )
  3731. {
  3732. vPaintBlend[ i ] -= flRemainder;
  3733. }
  3734. else
  3735. {
  3736. vPaintBlend[ i ] = 0.0f;
  3737. }
  3738. }
  3739. #endif
  3740. }
  3741. else
  3742. {
  3743. if ( m_b4WayBlendMode )
  3744. {
  3745. vPaintBlend[ nIndex ] += flTextureAmount;
  3746. for ( int i = nIndex + 1; i < MAX_MULTIBLEND_CHANNELS; i++)
  3747. {
  3748. if ( bDrawTextureChannel[ i ] == false )
  3749. {
  3750. continue;
  3751. }
  3752. if ( vPaintBlend[ i ] > flTextureAmount )
  3753. {
  3754. vPaintBlend[ i ] -= flTextureAmount;
  3755. }
  3756. else
  3757. {
  3758. vPaintBlend[ i ] = 0.0f;
  3759. }
  3760. }
  3761. }
  3762. else // multiblend
  3763. {
  3764. for( int i = nIndex; i >= 0; i-- )
  3765. // for( int i = MAX_MULTIBLEND_CHANNELS - 1; i > 0; i-- )
  3766. {
  3767. if ( i == nIndex )
  3768. {
  3769. vPaintBlend[ i ] += flTextureAmount;
  3770. }
  3771. else
  3772. {
  3773. if ( bDrawTextureChannel[ i ] == false )
  3774. {
  3775. continue;
  3776. }
  3777. if ( vPaintBlend[ i ] > flTextureAmount )
  3778. {
  3779. vPaintBlend[ i ] -= flTextureAmount;
  3780. flTextureAmount = 0.0f;
  3781. }
  3782. else
  3783. {
  3784. flTextureAmount -= vPaintBlend[ i ];
  3785. vPaintBlend[ i ] = 0.0f;
  3786. }
  3787. }
  3788. }
  3789. }
  3790. }
  3791. }
  3792. else
  3793. {
  3794. vPaintBlend[ nIndex ] -= flTextureAmount;
  3795. }
  3796. vPaintBlend.x = clamp( vPaintBlend.x, 0.0f, 1.0f );
  3797. vPaintBlend.y = clamp( vPaintBlend.y, 0.0f, 1.0f );
  3798. vPaintBlend.z = clamp( vPaintBlend.z, 0.0f, 1.0f );
  3799. vPaintBlend.w = clamp( vPaintBlend.w, 0.0f, 1.0f );
  3800. }
  3801. if ( bDrawColor == true )
  3802. {
  3803. Vector vResultColor;
  3804. switch( m_ColorMode[ nIndex ] )
  3805. {
  3806. case COLOR_MODE_SINGLE:
  3807. vResultColor = m_vStartDrawColor[ nIndex ];
  3808. break;
  3809. case COLOR_MODE_RANGE:
  3810. {
  3811. float flRange = RandomFloat( 0.0f, 1.0f );
  3812. vResultColor.x = m_vStartDrawColor[ nIndex ].x + ( ( m_vEndDrawColor[ nIndex ].x - m_vStartDrawColor[ nIndex ].x ) * flRange );
  3813. vResultColor.y = m_vStartDrawColor[ nIndex ].y + ( ( m_vEndDrawColor[ nIndex ].y - m_vStartDrawColor[ nIndex ].y ) * flRange );
  3814. vResultColor.z = m_vStartDrawColor[ nIndex ].z + ( ( m_vEndDrawColor[ nIndex ].z - m_vStartDrawColor[ nIndex ].z ) * flRange );
  3815. }
  3816. break;
  3817. case COLOR_MODE_OR:
  3818. if ( RandomInt( 1, 100 ) > 50 )
  3819. {
  3820. vResultColor = m_vStartDrawColor[ nIndex ];
  3821. }
  3822. else
  3823. {
  3824. vResultColor = m_vEndDrawColor[ nIndex ];
  3825. }
  3826. break;
  3827. }
  3828. if ( m_Direction < 0.0f )
  3829. {
  3830. vResultColor.Init( 1.0f, 1.0f, 1.0f );
  3831. }
  3832. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3833. {
  3834. if ( bDrawColorChannel[ i ] == true )
  3835. {
  3836. vPaintColor[ i ] = ( vPaintColor[ i ] * ( 1.0f - flColorAmount ) ) + ( vResultColor * flColorAmount );
  3837. }
  3838. }
  3839. }
  3840. if ( bDrawAlpha == true )
  3841. {
  3842. vPaintAlphaBlend[ nIndex ] = clamp( vPaintAlphaBlend[ nIndex ] + flAlphaAmount, 0.0f, 2.0f );
  3843. }
  3844. pDisp->SetMultiBlend( iVert, vPaintBlend, vPaintAlphaBlend, vPaintColor[ 0 ], vPaintColor[ 1 ], vPaintColor[ 2 ], vPaintColor[ 3 ] );
  3845. }
  3846. }
  3847. }
  3848. void CSculptBlendOptions::OnNMCustomdrawBlendAmount(NMHDR *pNMHDR, LRESULT *pResult)
  3849. {
  3850. // LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  3851. // TODO: Add your control notification handler code here
  3852. *pResult = 0;
  3853. if ( m_BlendAmountControl.GetPos() == 0 )
  3854. {
  3855. m_BlendAmountTextControl.SetWindowText( "Off" );
  3856. }
  3857. else
  3858. {
  3859. char temp[ 128 ];
  3860. sprintf( temp, "%d%%", m_BlendAmountControl.GetPos() );
  3861. m_BlendAmountTextControl.SetWindowText( temp );
  3862. }
  3863. }
  3864. void CSculptBlendOptions::OnBnClickedTextureButton1()
  3865. {
  3866. m_TextureControl[ m_nSelectedTexture ].SetSelected( false );
  3867. SelectTexture( 0 );
  3868. m_TextureControl[ m_nSelectedTexture ].SetSelected( true );
  3869. }
  3870. void CSculptBlendOptions::OnBnClickedTextureButton2()
  3871. {
  3872. m_TextureControl[ m_nSelectedTexture ].SetSelected( false );
  3873. SelectTexture( 1 );
  3874. m_TextureControl[ m_nSelectedTexture ].SetSelected( true );
  3875. }
  3876. void CSculptBlendOptions::OnBnClickedTextureButton3()
  3877. {
  3878. m_TextureControl[ m_nSelectedTexture ].SetSelected( false );
  3879. SelectTexture( 2 );
  3880. m_TextureControl[ m_nSelectedTexture ].SetSelected( true );
  3881. }
  3882. void CSculptBlendOptions::OnBnClickedTextureButton4()
  3883. {
  3884. m_TextureControl[ m_nSelectedTexture ].SetSelected( false );
  3885. SelectTexture( 3 );
  3886. m_TextureControl[ m_nSelectedTexture ].SetSelected( true );
  3887. }
  3888. #define BRUSH_CHANGE_AMOUNT 4
  3889. void CSculptBlendOptions::ShrinkBrush()
  3890. {
  3891. if ( m_BrushSize > BRUSH_CHANGE_AMOUNT + 1 )
  3892. {
  3893. m_BrushSize -= BRUSH_CHANGE_AMOUNT;
  3894. }
  3895. }
  3896. void CSculptBlendOptions::EnlargeBrush()
  3897. {
  3898. m_BrushSize += BRUSH_CHANGE_AMOUNT;
  3899. }
  3900. #include <tier0/memdbgoff.h>
  3901. void CSculptBlendOptions::OnBnClickedSetColor()
  3902. {
  3903. CColorDialog dlg( RGB( m_vStartDrawColor[ m_nSelectedTexture ].x * 255, m_vStartDrawColor[ m_nSelectedTexture ].y * 255, m_vStartDrawColor[ m_nSelectedTexture ].z * 255 ), CC_FULLOPEN );
  3904. if ( dlg.DoModal() == IDOK )
  3905. {
  3906. m_vStartDrawColor[ m_nSelectedTexture ].x = GetRValue( dlg.m_cc.rgbResult ) / 255.0f;
  3907. m_vStartDrawColor[ m_nSelectedTexture ].y = GetGValue( dlg.m_cc.rgbResult ) / 255.0f;
  3908. m_vStartDrawColor[ m_nSelectedTexture ].z = GetBValue( dlg.m_cc.rgbResult ) / 255.0f;
  3909. m_ColorStartControl.SetColor( m_vStartDrawColor[ m_nSelectedTexture ].x, m_vStartDrawColor[ m_nSelectedTexture ].y, m_vStartDrawColor[ m_nSelectedTexture ].z );
  3910. }
  3911. }
  3912. void CSculptBlendOptions::OnBnClickedSetColor2()
  3913. {
  3914. CColorDialog dlg( RGB( m_vEndDrawColor[ m_nSelectedTexture ].x * 255, m_vEndDrawColor[ m_nSelectedTexture ].y * 255, m_vEndDrawColor[ m_nSelectedTexture ].z * 255 ), CC_FULLOPEN );
  3915. if ( dlg.DoModal() == IDOK )
  3916. {
  3917. m_vEndDrawColor[ m_nSelectedTexture ].x = GetRValue( dlg.m_cc.rgbResult ) / 255.0f;
  3918. m_vEndDrawColor[ m_nSelectedTexture ].y = GetGValue( dlg.m_cc.rgbResult ) / 255.0f;
  3919. m_vEndDrawColor[ m_nSelectedTexture ].z = GetBValue( dlg.m_cc.rgbResult ) / 255.0f;
  3920. m_ColorEndControl.SetColor( m_vEndDrawColor[ m_nSelectedTexture ].x, m_vEndDrawColor[ m_nSelectedTexture ].y, m_vEndDrawColor[ m_nSelectedTexture ].z );
  3921. }
  3922. }
  3923. void CSculptBlendOptions::OnNMCustomdrawColorBlendAmount(NMHDR *pNMHDR, LRESULT *pResult)
  3924. {
  3925. *pResult = 0;
  3926. if ( m_ColorBlendAmountControl.GetPos() == 0 )
  3927. {
  3928. m_ColorBlendAmountTextControl.SetWindowText( "Off" );
  3929. }
  3930. else
  3931. {
  3932. char temp[ 128 ];
  3933. sprintf( temp, "%d%%", m_ColorBlendAmountControl.GetPos() );
  3934. m_ColorBlendAmountTextControl.SetWindowText( temp );
  3935. }
  3936. }
  3937. void CSculptBlendOptions::OnCbnSelchangeBlendColorOperation()
  3938. {
  3939. SetColorMode( ( ColorMode )m_BlendColorOperationControl.GetCurSel(), false );
  3940. }
  3941. void CSculptBlendOptions::OnNMCustomdrawAlphaBlendAmount(NMHDR *pNMHDR, LRESULT *pResult)
  3942. {
  3943. // LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  3944. *pResult = 0;
  3945. if ( m_AlphaBlendAmountControl.GetPos() == 0 )
  3946. {
  3947. m_AlphaBlendAmountTextControl.SetWindowText( "Off" );
  3948. }
  3949. else
  3950. {
  3951. char temp[ 128 ];
  3952. sprintf( temp, "%d%%", m_AlphaBlendAmountControl.GetPos() );
  3953. m_AlphaBlendAmountTextControl.SetWindowText( temp );
  3954. }
  3955. }
  3956. void CSculptBlendOptions::OnRButtonDblClk(UINT nFlags, CPoint point)
  3957. {
  3958. __super::OnRButtonDblClk(nFlags, point);
  3959. // Get the displacement manager from the active map document.
  3960. IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
  3961. if( !pDispMgr )
  3962. {
  3963. return;
  3964. }
  3965. bool bDrawTexture = ( m_BlendAmountControl.GetPos() > 0 );
  3966. bool bDrawAlpha = ( m_AlphaBlendAmountControl.GetPos() > 0 );
  3967. bool bDrawColor = ( m_ColorBlendAmountControl.GetPos() > 0 );
  3968. bool bDrawTextureChannel[ MAX_MULTIBLEND_CHANNELS ], bDrawColorChannel[ MAX_MULTIBLEND_CHANNELS ];
  3969. Vector4D vBlend, vPaintBlend, vAlphaBlend, vPaintAlphaBlend;
  3970. Vector vColor[ MAX_MULTIBLEND_CHANNELS ], vPaintColor[ MAX_MULTIBLEND_CHANNELS ];
  3971. vPaintBlend.Init( 1.0f, 0.0f, 0.0f, 0.0f );
  3972. vPaintAlphaBlend.Init();
  3973. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3974. {
  3975. vPaintColor[ i ] = Vector( 1.0f, 1.0f, 1.0f );
  3976. bDrawTextureChannel[ i ] = ( bDrawTexture == true && m_TextureMaskControl[ i ].GetCheck() == BST_CHECKED );
  3977. bDrawColorChannel[ i ] = ( bDrawColor == true && m_ColorMaskControl[ i ].GetCheck() == BST_CHECKED );
  3978. }
  3979. // For each displacement surface is the selection list attempt to paint on it.
  3980. int nDispCount = pDispMgr->SelectCount();
  3981. for ( int iDisp = 0; iDisp < nDispCount; iDisp++ )
  3982. {
  3983. CMapDisp *pDisp = pDispMgr->GetFromSelect( iDisp );
  3984. if ( pDisp )
  3985. {
  3986. AddToUndo( &pDisp );
  3987. int nVertCount = pDisp->GetSize();
  3988. for ( int iVert = 0; iVert < nVertCount; iVert++ )
  3989. {
  3990. pDisp->GetMultiBlend( iVert, vBlend, vAlphaBlend, vColor[ 0 ], vColor[ 1 ], vColor[ 2 ], vColor[ 3 ] );
  3991. if ( bDrawAlpha == true )
  3992. {
  3993. vAlphaBlend = vPaintAlphaBlend;
  3994. }
  3995. for( int i = 0; i < MAX_MULTIBLEND_CHANNELS; i++ )
  3996. {
  3997. if ( bDrawTextureChannel[ i ] == true )
  3998. {
  3999. vBlend[ i ] = vPaintBlend[ i ];
  4000. }
  4001. if ( bDrawColorChannel[ i ] == true )
  4002. {
  4003. vColor[ i ] = vPaintColor[ i ];
  4004. }
  4005. }
  4006. pDisp->SetMultiBlend( iVert, vBlend, vAlphaBlend, vColor[ 0 ], vColor[ 1 ], vColor[ 2 ], vColor[ 3 ] );
  4007. }
  4008. }
  4009. }
  4010. pDispMgr->PostUndo();
  4011. }