guiConvexShapeEditorCtrl.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "gui/worldEditor/guiConvexShapeEditorCtrl.h"
  24. #include "console/consoleTypes.h"
  25. #include "T3D/convexShape.h"
  26. #include "renderInstance/renderPassManager.h"
  27. #include "collision/collision.h"
  28. #include "math/util/frustum.h"
  29. #include "math/mathUtils.h"
  30. #include "gfx/gfxPrimitiveBuffer.h"
  31. #include "gfx/gfxTextureHandle.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "gfx/primBuilder.h"
  34. #include "gfx/gfxDrawUtil.h"
  35. #include "scene/sceneRenderState.h"
  36. #include "scene/sceneManager.h"
  37. #include "gui/core/guiCanvas.h"
  38. #include "gui/buttons/guiButtonCtrl.h"
  39. #include "gui/worldEditor/undoActions.h"
  40. #include "T3D/gameBase/gameConnection.h"
  41. #include "gfx/sim/debugDraw.h"
  42. #include "collision/optimizedPolyList.h"
  43. #include "core/volume.h"
  44. #include "gui/worldEditor/worldEditor.h"
  45. #include "T3D/prefab.h"
  46. IMPLEMENT_CONOBJECT( GuiConvexEditorCtrl );
  47. ConsoleDocClass( GuiConvexEditorCtrl,
  48. "@brief The base class for the sketch tool\n\n"
  49. "Editor use only.\n\n"
  50. "@internal"
  51. );
  52. GuiConvexEditorCtrl::GuiConvexEditorCtrl()
  53. : mIsDirty( false ),
  54. mFaceHL( -1 ),
  55. mFaceSEL( -1 ),
  56. mFaceSavedXfm( true ),
  57. mSavedUndo( false ),
  58. mDragging( false ),
  59. mGizmoMatOffset( Point3F::Zero ),
  60. mPivotPos( Point3F::Zero ),
  61. mUsingPivot( false ),
  62. mSettingPivot( false ),
  63. mActiveTool( NULL ),
  64. mCreateTool( NULL ),
  65. mMouseDown( false ),
  66. mUndoManager( NULL ),
  67. mLastUndo( NULL ),
  68. mHasCopied( false ),
  69. mSavedGizmoFlags( -1 ),
  70. mCtrlDown( false )
  71. {
  72. mMaterialName = StringTable->insert("Grid512_OrangeLines_Mat");
  73. }
  74. GuiConvexEditorCtrl::~GuiConvexEditorCtrl()
  75. {
  76. }
  77. bool GuiConvexEditorCtrl::onAdd()
  78. {
  79. if ( !Parent::onAdd() )
  80. return false;
  81. SceneManager::getPreRenderSignal().notify( this, &GuiConvexEditorCtrl::_prepRenderImage );
  82. mCreateTool = new ConvexEditorCreateTool( this );
  83. return true;
  84. }
  85. void GuiConvexEditorCtrl::onRemove()
  86. {
  87. SceneManager::getPreRenderSignal().remove( this, &GuiConvexEditorCtrl::_prepRenderImage );
  88. SAFE_DELETE( mCreateTool );
  89. Parent::onRemove();
  90. }
  91. void GuiConvexEditorCtrl::initPersistFields()
  92. {
  93. addField( "isDirty", TypeBool, Offset( mIsDirty, GuiConvexEditorCtrl ) );
  94. addField( "materialName", TypeString, Offset(mMaterialName, GuiConvexEditorCtrl) );
  95. Parent::initPersistFields();
  96. }
  97. bool GuiConvexEditorCtrl::onWake()
  98. {
  99. if ( !Parent::onWake() )
  100. return false;
  101. SimGroup *missionGroup;
  102. if ( !Sim::findObject( "MissionGroup", missionGroup ) )
  103. return true;
  104. SimGroup::iterator itr = missionGroup->begin();
  105. for ( ; itr != missionGroup->end(); itr++ )
  106. {
  107. if ( dStrcmp( (*itr)->getClassName(), "ConvexShape" ) == 0 )
  108. {
  109. mConvexSEL = static_cast<ConvexShape*>( *itr );
  110. mGizmo->set( mConvexSEL->getTransform(), mConvexSEL->getPosition(), mConvexSEL->getScale() );
  111. return true;
  112. }
  113. }
  114. return true;
  115. }
  116. void GuiConvexEditorCtrl::onSleep()
  117. {
  118. Parent::onSleep();
  119. mConvexSEL = NULL;
  120. mConvexHL = NULL;
  121. }
  122. void GuiConvexEditorCtrl::setVisible( bool val )
  123. {
  124. //ConvexShape::smRenderEdges = value;
  125. if ( isProperlyAdded() )
  126. {
  127. if ( !val )
  128. {
  129. mFaceHL = -1;
  130. mConvexHL = NULL;
  131. setSelection( NULL, -1 );
  132. if ( mSavedGizmoFlags != -1 )
  133. {
  134. mGizmoProfile->flags = mSavedGizmoFlags;
  135. mSavedGizmoFlags = -1;
  136. }
  137. }
  138. else
  139. {
  140. mConvexHL = NULL;
  141. mFaceHL = -1;
  142. setSelection( NULL, -1 );
  143. WorldEditor *wedit;
  144. if ( Sim::findObject( "EWorldEditor", wedit ) )
  145. {
  146. S32 count = wedit->getSelectionSize();
  147. for ( S32 i = 0; i < count; i++ )
  148. {
  149. S32 objId = wedit->getSelectObject(i);
  150. ConvexShape *pShape;
  151. if ( Sim::findObject( objId, pShape ) )
  152. {
  153. mConvexSEL = pShape;
  154. wedit->clearSelection();
  155. wedit->selectObject( String::ToString("%i",objId) );
  156. break;
  157. }
  158. }
  159. }
  160. updateGizmoPos();
  161. mSavedGizmoFlags = mGizmoProfile->flags;
  162. }
  163. }
  164. Parent::setVisible( val );
  165. }
  166. void GuiConvexEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
  167. {
  168. mouseLock();
  169. mMouseDown = true;
  170. if ( event.modifier & SI_ALT )
  171. {
  172. setActiveTool( mCreateTool );
  173. mActiveTool->on3DMouseDown( event );
  174. return;
  175. }
  176. if ( mConvexSEL && isShapeValid( mConvexSEL ) )
  177. mLastValidShape = mConvexSEL->mSurfaces;
  178. if ( mConvexSEL &&
  179. mFaceSEL != -1 &&
  180. mGizmo->getMode() == RotateMode &&
  181. mGizmo->getSelection() == Gizmo::Centroid )
  182. {
  183. mSettingPivot = true;
  184. mSavedPivotPos = mGizmo->getPosition();
  185. setPivotPos( mConvexSEL, mFaceSEL, event );
  186. updateGizmoPos();
  187. return;
  188. }
  189. mGizmo->on3DMouseDown( event );
  190. }
  191. void GuiConvexEditorCtrl::on3DRightMouseDown(const Gui3DMouseEvent & event)
  192. {
  193. return;
  194. /*
  195. if ( mConvexSEL && mFaceSEL != -1 && mFaceSEL == mFaceHL )
  196. {
  197. _submitUndo( "Split ConvexShape face." );
  198. const MatrixF &surf = mConvexSEL->mSurfaces[mFaceSEL];
  199. MatrixF newSurf( surf );
  200. MatrixF rotMat( EulerF( 0.0f, mDegToRad( 2.0f ), 0.0f ) );
  201. newSurf *= rotMat;
  202. mConvexSEL->mSurfaces.insert( mFaceSEL+1, newSurf );
  203. }
  204. */
  205. }
  206. void GuiConvexEditorCtrl::on3DRightMouseUp(const Gui3DMouseEvent & event)
  207. {
  208. //ConvexShape *hitShape;
  209. //S32 hitFace;
  210. //bool hit = _cursorCast( event, &hitShape, &hitFace );
  211. //Con::printf( hit ? "HIT" : "MISS" );
  212. }
  213. void GuiConvexEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
  214. {
  215. mouseUnlock();
  216. mMouseDown = false;
  217. mHasCopied = false;
  218. mHasGeometry = false;
  219. if ( mActiveTool )
  220. {
  221. ConvexEditorTool::EventResult result = mActiveTool->on3DMouseUp( event );
  222. if ( result == ConvexEditorTool::Done )
  223. setActiveTool( NULL );
  224. return;
  225. }
  226. if ( !mSettingPivot && !mDragging && ( mGizmo->getSelection() == Gizmo::None || !mConvexSEL ) )
  227. {
  228. if ( mConvexSEL != mConvexHL )
  229. {
  230. setSelection( mConvexHL, -1 );
  231. }
  232. else
  233. {
  234. if ( mFaceSEL != mFaceHL )
  235. setSelection( mConvexSEL, mFaceHL );
  236. else
  237. setSelection( mConvexSEL, -1 );
  238. }
  239. mUsingPivot = false;
  240. }
  241. mSettingPivot = false;
  242. mSavedPivotPos = mGizmo->getPosition();
  243. mSavedUndo = false;
  244. mGizmo->on3DMouseUp( event );
  245. if ( mDragging )
  246. {
  247. mDragging = false;
  248. if ( mConvexSEL )
  249. {
  250. Vector< U32 > removedPlanes;
  251. mConvexSEL->cullEmptyPlanes( &removedPlanes );
  252. // If a face has been removed we need to validate / remap
  253. // our selected and highlighted faces.
  254. if ( !removedPlanes.empty() )
  255. {
  256. S32 prevFaceHL = mFaceHL;
  257. S32 prevFaceSEL = mFaceSEL;
  258. if ( removedPlanes.contains( mFaceHL ) )
  259. prevFaceHL = mFaceHL = -1;
  260. if ( removedPlanes.contains( mFaceSEL ) )
  261. prevFaceSEL = mFaceSEL = -1;
  262. for ( S32 i = 0; i < removedPlanes.size(); i++ )
  263. {
  264. if ( (S32)removedPlanes[i] < prevFaceSEL )
  265. mFaceSEL--;
  266. if ( (S32)removedPlanes[i] < prevFaceHL )
  267. mFaceHL--;
  268. }
  269. setSelection( mConvexSEL, mFaceSEL );
  270. // We need to reindex faces.
  271. updateShape( mConvexSEL );
  272. }
  273. }
  274. }
  275. updateGizmoPos();
  276. }
  277. void GuiConvexEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
  278. {
  279. if ( mActiveTool )
  280. {
  281. // If we have an active tool pass this event to it.
  282. // If it handled it, consume the event.
  283. if ( mActiveTool->on3DMouseMove( event ) )
  284. return;
  285. }
  286. ConvexShape *hitShape = NULL;
  287. S32 hitFace = -1;
  288. _cursorCast( event, &hitShape, &hitFace );
  289. if ( !mConvexSEL )
  290. {
  291. mConvexHL = hitShape;
  292. mFaceHL = -1;
  293. }
  294. else
  295. {
  296. if ( mConvexSEL == hitShape )
  297. {
  298. mConvexHL = hitShape;
  299. mFaceHL = hitFace;
  300. }
  301. else
  302. {
  303. // Mousing over a shape that is not the one currently selected.
  304. if ( mFaceSEL != -1 )
  305. {
  306. mFaceHL = -1;
  307. }
  308. else
  309. {
  310. mConvexHL = hitShape;
  311. mFaceHL = -1;
  312. }
  313. }
  314. }
  315. if ( mConvexSEL )
  316. mGizmo->on3DMouseMove( event );
  317. }
  318. void GuiConvexEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
  319. {
  320. if ( mActiveTool )
  321. {
  322. // If we have an active tool pass this event to it.
  323. // If it handled it, consume the event.
  324. if ( mActiveTool->on3DMouseDragged( event ) )
  325. return;
  326. }
  327. //mGizmoProfile->rotateScalar = 0.55f;
  328. //mGizmoProfile->scaleScalar = 0.55f;
  329. if ( !mConvexSEL )
  330. return;
  331. if ( mGizmo->getMode() == RotateMode &&
  332. mGizmo->getSelection() == Gizmo::Centroid )
  333. {
  334. setPivotPos( mConvexSEL, mFaceSEL, event );
  335. mDragging = true;
  336. return;
  337. }
  338. mGizmo->on3DMouseDragged( event );
  339. if ( event.modifier & SI_SHIFT &&
  340. ( mGizmo->getMode() == MoveMode || mGizmo->getMode() == RotateMode ) &&
  341. !mHasCopied )
  342. {
  343. if ( mFaceSEL != -1 )
  344. {
  345. ConvexShape *newShape = mCreateTool->extrudeShapeFromFace( mConvexSEL, mFaceSEL );
  346. //newShape->_updateGeometry();
  347. submitUndo( CreateShape, newShape );
  348. setSelection( newShape, 0 );
  349. updateGizmoPos();
  350. mGizmo->on3DMouseDown( event );
  351. mHasCopied = true;
  352. mSavedUndo = true;
  353. }
  354. else
  355. {
  356. ConvexShape *newShape = new ConvexShape();
  357. newShape->setTransform( mConvexSEL->getTransform() );
  358. newShape->setScale( mConvexSEL->getScale() );
  359. newShape->mSurfaces.clear();
  360. newShape->mSurfaces.merge( mConvexSEL->mSurfaces );
  361. setupShape( newShape );
  362. submitUndo( CreateShape, newShape );
  363. setSelection( newShape, -1 );
  364. updateGizmoPos();
  365. mHasCopied = true;
  366. mSavedUndo = true;
  367. }
  368. return;
  369. }
  370. if ( mGizmo->getMode() == RotateMode &&
  371. event.modifier & SI_CTRL &&
  372. !mHasCopied &&
  373. mFaceSEL != -1 )
  374. {
  375. // Can must verify that splitting the face at the current angle
  376. // ( of the gizmo ) will generate a valid shape. If not enough rotation
  377. // has occurred we will have two faces that are coplanar and must wait
  378. // until later in the drag to perform the split.
  379. //AssertFatal( isShapeValid( mConvexSEL ), "Shape was already invalid at beginning of split operation." );
  380. if ( !isShapeValid( mConvexSEL ) )
  381. return;
  382. mLastValidShape = mConvexSEL->mSurfaces;
  383. Point3F rot = mGizmo->getDeltaTotalRot();
  384. rot.normalize();
  385. rot *= mDegToRad( 10.0f );
  386. MatrixF rotMat( (EulerF)rot );
  387. MatrixF worldToObj( mConvexSEL->getTransform() );
  388. worldToObj.scale( mConvexSEL->getScale() );
  389. worldToObj.inverse();
  390. mConvexSEL->mSurfaces.increment();
  391. MatrixF &newSurf = mConvexSEL->mSurfaces.last();
  392. newSurf = mConvexSEL->mSurfaces[mFaceSEL] * rotMat;
  393. //worldToObj.mul( mGizmo->getTransform() );
  394. //Point3F pos( mPivotPos );
  395. //worldToObj.mulP( pos );
  396. //newSurf.setPosition( pos );
  397. updateShape( mConvexSEL );
  398. if ( !isShapeValid( mConvexSEL ) )
  399. {
  400. mConvexSEL->mSurfaces = mLastValidShape;
  401. updateShape( mConvexSEL );
  402. }
  403. else
  404. {
  405. mHasCopied = true;
  406. mSavedUndo = true;
  407. mLastValidShape = mConvexSEL->mSurfaces;
  408. submitUndo( ModifyShape, mConvexSEL );
  409. setSelection( mConvexSEL, mConvexSEL->mSurfaces.size() - 1 );
  410. updateGizmoPos();
  411. }
  412. return;
  413. }
  414. // If we are dragging, but no gizmo selection...
  415. // Then treat this like a regular mouse move, update the highlighted
  416. // convex/face under the cursor and handle onMouseUp as we normally would
  417. // to change the selection.
  418. if ( mGizmo->getSelection() == Gizmo::None )
  419. {
  420. ConvexShape *hitShape = NULL;
  421. S32 hitFace = -1;
  422. _cursorCast( event, &hitShape, &hitFace );
  423. mFaceHL = hitFace;
  424. mConvexHL = hitShape;
  425. return;
  426. }
  427. mDragging = true;
  428. // Manipulating a face.
  429. if ( mFaceSEL != -1 )
  430. {
  431. if ( !mSavedUndo )
  432. {
  433. mSavedUndo = true;
  434. submitUndo( ModifyShape, mConvexSEL );
  435. }
  436. if ( mGizmo->getMode() == ScaleMode )
  437. {
  438. scaleFace( mConvexSEL, mFaceSEL, mGizmo->getScale() );
  439. }
  440. else
  441. {
  442. // Why does this have to be so ugly.
  443. if ( mGizmo->getMode() == RotateMode ||
  444. ( mGizmo->getMode() == MoveMode &&
  445. ( event.modifier & SI_CTRL ||
  446. ( mGizmo->getSelection() == Gizmo::Axis_Z && mHasCopied )
  447. )
  448. )
  449. )
  450. {
  451. const MatrixF &gMat = mGizmo->getTransform();
  452. MatrixF surfMat;
  453. surfMat.mul( mConvexSEL->mWorldToObj, gMat );
  454. MatrixF worldToObj ( mConvexSEL->getTransform() );
  455. worldToObj.scale( mConvexSEL->getScale() );
  456. worldToObj.inverse();
  457. Point3F newPos;
  458. newPos = gMat.getPosition();
  459. worldToObj.mulP( newPos );
  460. surfMat.setPosition( newPos );
  461. // Clear out floating point errors.
  462. cleanMatrix( surfMat );
  463. mConvexSEL->mSurfaces[mFaceSEL] = surfMat;
  464. updateShape( mConvexSEL, mFaceSEL );
  465. }
  466. else
  467. {
  468. // Translating a face in x/y/z
  469. translateFace( mConvexSEL, mFaceSEL, mGizmo->getTotalOffset() );
  470. }
  471. }
  472. if ( isShapeValid( mConvexSEL ) )
  473. {
  474. AssertFatal( mConvexSEL->mSurfaces.size() > mFaceSEL, "mFaceSEL out of range." );
  475. mLastValidShape = mConvexSEL->mSurfaces;
  476. }
  477. else
  478. {
  479. AssertFatal( mLastValidShape.size() > mFaceSEL, "mFaceSEL out of range." );
  480. mConvexSEL->mSurfaces = mLastValidShape;
  481. updateShape( mConvexSEL );
  482. }
  483. return;
  484. }
  485. // Manipulating a whole Convex.
  486. if ( !mSavedUndo )
  487. {
  488. mSavedUndo = true;
  489. submitUndo( ModifyShape, mConvexSEL );
  490. }
  491. if ( mGizmo->getMode() == MoveMode )
  492. {
  493. mConvexSEL->setPosition( mGizmo->getPosition() );
  494. }
  495. else if ( mGizmo->getMode() == RotateMode )
  496. {
  497. mConvexSEL->setTransform( mGizmo->getTransform() );
  498. }
  499. else
  500. {
  501. mConvexSEL->setScale( mGizmo->getScale() );
  502. }
  503. if ( mConvexSEL->getClientObject() )
  504. {
  505. ConvexShape *clientObj = static_cast< ConvexShape* >( mConvexSEL->getClientObject() );
  506. clientObj->setTransform( mConvexSEL->getTransform() );
  507. clientObj->setScale( mConvexSEL->getScale() );
  508. }
  509. }
  510. void GuiConvexEditorCtrl::on3DMouseEnter(const Gui3DMouseEvent & event)
  511. {
  512. }
  513. void GuiConvexEditorCtrl::on3DMouseLeave(const Gui3DMouseEvent & event)
  514. {
  515. }
  516. bool GuiConvexEditorCtrl::onKeyDown( const GuiEvent &evt )
  517. {
  518. bool handled = false;
  519. switch ( evt.keyCode )
  520. {
  521. case KEY_ESCAPE:
  522. handled = handleEscape();
  523. break;
  524. case KEY_A:
  525. if ( evt.modifier & SI_ALT )
  526. {
  527. GizmoAlignment align = mGizmo->getProfile()->alignment;
  528. if ( align == World )
  529. mGizmo->getProfile()->alignment = Object;
  530. else
  531. mGizmo->getProfile()->alignment = World;
  532. handled = true;
  533. }
  534. break;
  535. case KEY_LCONTROL:
  536. //mCtrlDown = true;
  537. break;
  538. default:
  539. break;
  540. }
  541. return handled;
  542. }
  543. bool GuiConvexEditorCtrl::onKeyUp( const GuiEvent &evt )
  544. {
  545. bool handled = false;
  546. switch ( evt.keyCode )
  547. {
  548. case KEY_LCONTROL:
  549. //mCtrlDown = false;
  550. break;
  551. default:
  552. break;
  553. }
  554. return handled;
  555. }
  556. void GuiConvexEditorCtrl::get3DCursor( GuiCursor *&cursor,
  557. bool &visible,
  558. const Gui3DMouseEvent &event_ )
  559. {
  560. //cursor = mAddNodeCursor;
  561. //visible = false;
  562. cursor = NULL;
  563. visible = false;
  564. GuiCanvas *root = getRoot();
  565. if ( !root )
  566. return;
  567. S32 currCursor = PlatformCursorController::curArrow;
  568. if ( root->mCursorChanged == currCursor )
  569. return;
  570. PlatformWindow *window = root->getPlatformWindow();
  571. PlatformCursorController *controller = window->getCursorController();
  572. // We've already changed the cursor,
  573. // so set it back before we change it again.
  574. if( root->mCursorChanged != -1)
  575. controller->popCursor();
  576. // Now change the cursor shape
  577. controller->pushCursor(currCursor);
  578. root->mCursorChanged = currCursor;
  579. }
  580. void GuiConvexEditorCtrl::updateGizmo()
  581. {
  582. mGizmoProfile->restoreDefaultState();
  583. const GizmoMode &mode = mGizmoProfile->mode;
  584. S32 &flags = mGizmoProfile->flags;
  585. GizmoAlignment &align = mGizmoProfile->alignment;
  586. U8 keys = Input::getModifierKeys();
  587. mCtrlDown = keys & ( SI_LCTRL | SI_LSHIFT );
  588. bool altDown = keys & ( SI_LALT );
  589. if ( altDown )
  590. {
  591. flags = 0;
  592. return;
  593. }
  594. if ( mFaceSEL != -1 )
  595. {
  596. align = Object;
  597. flags |= GizmoProfile::CanRotateUniform;
  598. flags &= ~GizmoProfile::CanRotateScreen;
  599. }
  600. else
  601. {
  602. flags &= ~GizmoProfile::CanRotateUniform;
  603. flags |= GizmoProfile::CanRotateScreen;
  604. }
  605. if ( mFaceSEL != -1 && mode == ScaleMode )
  606. flags &= ~GizmoProfile::CanScaleZ;
  607. else
  608. flags |= GizmoProfile::CanScaleZ;
  609. if ( mFaceSEL != -1 && mode == MoveMode )
  610. {
  611. if ( mCtrlDown )
  612. flags &= ~( GizmoProfile::CanTranslateX | GizmoProfile::CanTranslateY | GizmoProfile::PlanarHandlesOn );
  613. else
  614. flags |= ( GizmoProfile::CanTranslateX | GizmoProfile::CanTranslateY | GizmoProfile::PlanarHandlesOn );
  615. }
  616. }
  617. void GuiConvexEditorCtrl::renderScene(const RectI & updateRect)
  618. {
  619. // Synch selected ConvexShape with the WorldEditor.
  620. WorldEditor *wedit;
  621. if ( Sim::findObject( "EWorldEditor", wedit) )
  622. {
  623. S32 count = wedit->getSelectionSize();
  624. if ( !mConvexSEL && count != 0 )
  625. wedit->clearSelection();
  626. else if ( mConvexSEL && count != 1 )
  627. {
  628. wedit->clearSelection();
  629. wedit->selectObject( mConvexSEL->getIdString() );
  630. }
  631. else if ( mConvexSEL && count == 1 )
  632. {
  633. if ( wedit->getSelectObject(0) != mConvexSEL->getId() )
  634. {
  635. wedit->clearSelection();
  636. wedit->selectObject( mConvexSEL->getIdString() );
  637. }
  638. }
  639. }
  640. // Update status bar text.
  641. SimObject *statusbar;
  642. if ( Sim::findObject( "EditorGuiStatusBar", statusbar ) )
  643. {
  644. String text( "Sketch Tool." );
  645. GizmoMode mode = mGizmo->getMode();
  646. if ( mMouseDown && mGizmo->getSelection() != Gizmo::None && mConvexSEL )
  647. {
  648. Point3F delta;
  649. String qualifier;
  650. if ( mode == RotateMode )
  651. {
  652. if ( mSettingPivot )
  653. delta = mGizmo->getPosition() - mSavedPivotPos;
  654. else
  655. delta = mGizmo->getDeltaTotalRot();
  656. }
  657. else if ( mode == MoveMode )
  658. delta = mGizmo->getTotalOffset();
  659. else if ( mode == ScaleMode )
  660. delta = mGizmo->getDeltaTotalScale();
  661. if ( mGizmo->getAlignment() == Object &&
  662. mode != ScaleMode )
  663. {
  664. mConvexSEL->mWorldToObj.mulV( delta );
  665. if ( mFaceSEL != -1 && mode != RotateMode )
  666. {
  667. MatrixF objToSurf( mConvexSEL->mSurfaces[ mFaceSEL ] );
  668. objToSurf.scale( mConvexSEL->getScale() );
  669. objToSurf.inverse();
  670. objToSurf.mulV( delta );
  671. }
  672. }
  673. if ( mIsZero( delta.x, 0.0001f ) )
  674. delta.x = 0.0f;
  675. if ( mIsZero( delta.y, 0.0001f ) )
  676. delta.y = 0.0f;
  677. if ( mIsZero( delta.z, 0.0001f ) )
  678. delta.z = 0.0f;
  679. if ( mode == RotateMode )
  680. {
  681. if ( mSettingPivot )
  682. text = String::ToString( "Delta position ( x: %4.2f, y: %4.2f, z: %4.2f ).", delta.x, delta.y, delta.z );
  683. else
  684. {
  685. delta.x = mRadToDeg( delta.x );
  686. delta.y = mRadToDeg( delta.y );
  687. delta.z = mRadToDeg( delta.z );
  688. text = String::ToString( "Delta angle ( x: %4.2f, y: %4.2f, z: %4.2f ).", delta.x, delta.y, delta.z );
  689. }
  690. }
  691. else if ( mode == MoveMode )
  692. text = String::ToString( "Delta position ( x: %4.2f, y: %4.2f, z: %4.2f ).", delta.x, delta.y, delta.z );
  693. else if ( mode == ScaleMode )
  694. text = String::ToString( "Delta scale ( x: %4.2f, y: %4.2f, z: %4.2f ).", delta.x, delta.y, delta.z );
  695. }
  696. else
  697. {
  698. if ( !mConvexSEL )
  699. text = "Sketch Tool. ALT + Click-Drag to create a new ConvexShape.";
  700. else if ( mFaceSEL == -1 )
  701. {
  702. if ( mode == MoveMode )
  703. text = "Move selection. SHIFT while dragging duplicates objects.";
  704. else if ( mode == RotateMode )
  705. text = "Rotate selection.";
  706. else if ( mode == ScaleMode )
  707. text = "Scale selection.";
  708. }
  709. else
  710. {
  711. if ( mode == MoveMode )
  712. text = "Move face. SHIFT while beginning a drag EXTRUDES a new convex. Press CTRL for alternate translation mode.";
  713. else if ( mode == RotateMode )
  714. text = "Rotate face. Gizmo/Pivot is draggable. CTRL while dragging splits/folds a new face. SHIFT while dragging extrudes a new convex.";
  715. else if ( mode == ScaleMode )
  716. text = "Scale face.";
  717. }
  718. }
  719. // Issue a warning in the status bar
  720. // if this convex has an excessive number of surfaces...
  721. if ( mConvexSEL && mConvexSEL->getSurfaces().size() > ConvexShape::smMaxSurfaces )
  722. {
  723. text = "WARNING: Reduce the number of surfaces on the selected ConvexShape, only the first 100 will be saved!";
  724. }
  725. Con::executef( statusbar, "setInfo", text.c_str() );
  726. Con::executef( statusbar, "setSelectionObjectsByCount", Con::getIntArg( mConvexSEL == NULL ? 0 : 1 ) );
  727. }
  728. if ( mActiveTool )
  729. mActiveTool->renderScene( updateRect );
  730. ColorI colorHL( 255, 50, 255, 255 );
  731. ColorI colorSEL( 255, 50, 255, 255 );
  732. ColorI colorNA( 255, 255, 255, 100 );
  733. GFXDrawUtil *drawer = GFX->getDrawUtil();
  734. if ( mConvexSEL && !mDragging )
  735. {
  736. if ( mFaceSEL == -1 )
  737. {
  738. GFXStateBlockDesc desc;
  739. desc.setBlend( true );
  740. desc.setZReadWrite( true, true );
  741. Box3F objBox = mConvexSEL->getObjBox();
  742. objBox.scale( mConvexSEL->getScale() );
  743. const MatrixF &objMat = mConvexSEL->getTransform();
  744. Point3F boxPos = objBox.getCenter();
  745. objMat.mulP( boxPos );
  746. drawer->drawObjectBox( desc, objBox.getExtents(), boxPos, objMat, ColorI::WHITE );
  747. }
  748. else
  749. {
  750. mConvexSEL->renderFaceEdges( -1, colorNA );
  751. drawFacePlane( mConvexSEL, mFaceSEL );
  752. }
  753. if ( mConvexHL == mConvexSEL &&
  754. mFaceHL != -1 &&
  755. mFaceHL != mFaceSEL &&
  756. mGizmo->getSelection() == Gizmo::None )
  757. {
  758. mConvexSEL->renderFaceEdges( mFaceHL, colorHL );
  759. }
  760. }
  761. if ( mConvexHL && mConvexHL != mConvexSEL )
  762. {
  763. mConvexHL->renderFaceEdges( -1 );
  764. }
  765. if ( mGizmo->getMode() != RotateMode && mUsingPivot )
  766. {
  767. mUsingPivot = false;
  768. updateGizmoPos();
  769. }
  770. F32 gizmoAlpha = 1.0f;
  771. if ( !mConvexSEL )
  772. gizmoAlpha = 0.0f;
  773. if ( mMouseDown && mGizmo->getSelection() != Gizmo::None && mConvexSEL )
  774. {
  775. if ( mSettingPivot )
  776. gizmoAlpha = 1.0f;
  777. else
  778. gizmoAlpha = 0.0f;
  779. }
  780. DebugDrawer::get()->render();
  781. {
  782. GFXTransformSaver saver;
  783. // Now draw all the 2d stuff!
  784. GFX->setClipRect(updateRect);
  785. if ( mConvexSEL && mFaceSEL != -1 )
  786. {
  787. Vector< Point3F > lineList;
  788. mConvexSEL->getSurfaceLineList( mFaceSEL, lineList );
  789. MatrixF objToWorld( mConvexSEL->getTransform() );
  790. objToWorld.scale( mConvexSEL->getScale() );
  791. for ( S32 i = 0; i < lineList.size(); i++ )
  792. objToWorld.mulP( lineList[i] );
  793. for ( S32 i = 0; i < lineList.size() - 1; i++ )
  794. {
  795. Point3F p0( lineList[i] );
  796. Point3F p1( lineList[i+1] );
  797. drawLine( p0, p1, colorSEL, 3.0f );
  798. }
  799. }
  800. if ( gizmoAlpha == 1.0f )
  801. {
  802. if ( mGizmoProfile->mode != NoneMode )
  803. mGizmo->renderText( mSaveViewport, mSaveModelview, mSaveProjection );
  804. }
  805. if ( mActiveTool )
  806. mActiveTool->render2D();
  807. }
  808. if ( gizmoAlpha == 1.0f )
  809. mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix, mLastCameraQuery.fov );
  810. }
  811. void GuiConvexEditorCtrl::drawFacePlane( ConvexShape *shape, S32 faceId )
  812. {
  813. // Build a vb of the face points ( in world space ) scaled outward in
  814. // the surface space in x/y with uv coords.
  815. /*
  816. Vector< Point3F > points;
  817. Vector< Point2F > coords;
  818. shape->getSurfaceTriangles( faceId, &points, &coords, false );
  819. if ( points.empty() )
  820. return;
  821. GFXVertexBufferHandle< GFXVertexPCT > vb;
  822. vb.set( GFX, points.size(), GFXBufferTypeVolatile );
  823. GFXVertexPCT *vert = vb.lock();
  824. for ( S32 i = 0; i < points.size(); i++ )
  825. {
  826. vert->point = points[i];
  827. vert->color.set( 255, 255, 255, 200 );
  828. vert->texCoord = coords[i];
  829. vert++;
  830. }
  831. vb.unlock();
  832. GFXTransformSaver saver;
  833. MatrixF renderMat( shape->getTransform() );
  834. renderMat.scale( shape->getScale() );
  835. GFX->multWorld( renderMat );
  836. GFXStateBlockDesc desc;
  837. desc.setBlend( true );
  838. desc.setCullMode( GFXCullNone );
  839. desc.setZReadWrite( true, false );
  840. desc.samplersDefined = true;
  841. desc.samplers[0] = GFXSamplerStateDesc::getWrapLinear();
  842. GFX->setStateBlockByDesc( desc );
  843. GFX->setVertexBuffer( vb );
  844. GFXTexHandle tex( "core/art/grids/512_transp", &GFXDefaultStaticDiffuseProfile, "ConvexEditor_grid" );
  845. GFX->setTexture( 0, tex );
  846. GFX->setupGenericShaders();
  847. GFX->drawPrimitive( GFXTriangleList, 0, points.size() / 3 );
  848. */
  849. }
  850. void GuiConvexEditorCtrl::scaleFace( ConvexShape *shape, S32 faceId, Point3F scale )
  851. {
  852. if ( !mHasGeometry )
  853. {
  854. mHasGeometry = true;
  855. mSavedGeometry = shape->mGeometry;
  856. mSavedSurfaces = shape->mSurfaces;
  857. }
  858. else
  859. {
  860. shape->mGeometry = mSavedGeometry;
  861. shape->mSurfaces = mSavedSurfaces;
  862. }
  863. if ( shape->mGeometry.faces.size() <= faceId )
  864. return;
  865. ConvexShape::Face &face = shape->mGeometry.faces[faceId];
  866. Vector< Point3F > &pointList = shape->mGeometry.points;
  867. AssertFatal( shape->mSurfaces[ face.id ].isAffine(), "ConvexShapeEditor - surface not affine." );
  868. Point3F projScale;
  869. scale.z = 1.0f;
  870. const MatrixF &surfToObj = shape->mSurfaces[ face.id ];
  871. MatrixF objToSurf( surfToObj );
  872. objToSurf.inverse();
  873. for ( S32 i = 0; i < face.points.size(); i++ )
  874. {
  875. Point3F &pnt = pointList[ face.points[i] ];
  876. objToSurf.mulP( pnt );
  877. pnt *= scale;
  878. surfToObj.mulP( pnt );
  879. }
  880. updateModifiedFace( shape, faceId );
  881. }
  882. void GuiConvexEditorCtrl::translateFace( ConvexShape *shape, S32 faceId, const Point3F &displace )
  883. {
  884. if ( !mHasGeometry )
  885. {
  886. mHasGeometry = true;
  887. mSavedGeometry = shape->mGeometry;
  888. mSavedSurfaces = shape->mSurfaces;
  889. }
  890. else
  891. {
  892. shape->mGeometry = mSavedGeometry;
  893. shape->mSurfaces = mSavedSurfaces;
  894. }
  895. if ( shape->mGeometry.faces.size() <= faceId )
  896. return;
  897. ConvexShape::Face &face = shape->mGeometry.faces[faceId];
  898. Vector< Point3F > &pointList = shape->mGeometry.points;
  899. AssertFatal( shape->mSurfaces[ face.id ].isAffine(), "ConvexShapeEditor - surface not affine." );
  900. // Transform displacement into object space.
  901. MatrixF worldToObj( shape->getTransform() );
  902. worldToObj.scale( shape->getScale() );
  903. worldToObj.inverse();
  904. Point3F displaceOS;
  905. worldToObj.mulV( displace, &displaceOS );
  906. for ( S32 i = 0; i < face.points.size(); i++ )
  907. {
  908. Point3F &pnt = pointList[ face.points[i] ];
  909. pnt += displaceOS;
  910. }
  911. updateModifiedFace( shape, faceId );
  912. }
  913. void GuiConvexEditorCtrl::updateModifiedFace( ConvexShape *shape, S32 faceId )
  914. {
  915. if ( shape->mGeometry.faces.size() <= faceId )
  916. return;
  917. ConvexShape::Face &face = shape->mGeometry.faces[faceId];
  918. Vector< Point3F > &pointList = shape->mGeometry.points;
  919. Vector< ConvexShape::Face > &faceList = shape->mGeometry.faces;
  920. for ( S32 i = 0; i < faceList.size(); i++ )
  921. {
  922. ConvexShape::Face &curFace = faceList[i];
  923. MatrixF &curSurface = shape->mSurfaces[ curFace.id ];
  924. U32 curPntCount = curFace.points.size();
  925. if ( curPntCount < 3 )
  926. continue;
  927. // Does this face use any of the points which we have modified?
  928. // Collect them in correct winding order.
  929. S32 pId0 = -1;
  930. for ( S32 j = 0; j < curFace.winding.size(); j++ )
  931. {
  932. if ( face.points.contains( curFace.points[ curFace.winding[ j ] ] ) )
  933. {
  934. pId0 = j;
  935. break;
  936. }
  937. }
  938. if ( pId0 == -1 )
  939. continue;
  940. S32 pId1 = -1, pId2 = -1;
  941. pId1 = ( pId0 + 1 ) % curFace.winding.size();
  942. pId2 = ( pId0 + 2 ) % curFace.winding.size();
  943. const Point3F &p0 = pointList[ curFace.points[ curFace.winding[ pId0 ] ] ];
  944. const Point3F &p1 = pointList[ curFace.points[ curFace.winding[ pId1 ] ] ];
  945. const Point3F &p2 = pointList[ curFace.points[ curFace.winding[ pId2 ] ] ];
  946. PlaneF newPlane( p0, p1, p2 );
  947. Point3F uvec = newPlane.getNormal();
  948. Point3F fvec = curSurface.getForwardVector();
  949. Point3F rvec = curSurface.getRightVector();
  950. F32 dt0 = mDot( uvec, fvec );
  951. F32 dt1 = mDot( uvec, rvec );
  952. if ( mFabs( dt0 ) < mFabs( dt1 ) )
  953. {
  954. rvec = mCross( fvec, uvec );
  955. rvec.normalizeSafe();
  956. fvec = mCross( uvec, rvec );
  957. fvec.normalizeSafe();
  958. }
  959. else
  960. {
  961. fvec = mCross( uvec, rvec );
  962. fvec.normalizeSafe();
  963. rvec = mCross( fvec, uvec );
  964. rvec.normalizeSafe();
  965. }
  966. curSurface.setColumn( 0, rvec );
  967. curSurface.setColumn( 1, fvec );
  968. curSurface.setColumn( 2, uvec );
  969. curSurface.setPosition( newPlane.getPosition() );
  970. }
  971. updateShape( shape );
  972. }
  973. bool GuiConvexEditorCtrl::isShapeValid( ConvexShape *shape )
  974. {
  975. // Test for no-geometry.
  976. if ( shape->mGeometry.points.empty() )
  977. return false;
  978. const Vector<Point3F> &pointList = shape->mGeometry.points;
  979. const Vector<ConvexShape::Face> &faceList = shape->mGeometry.faces;
  980. // Test that all points are shared by at least 3 faces.
  981. for ( S32 i = 0; i < pointList.size(); i++ )
  982. {
  983. U32 counter = 0;
  984. for ( S32 j = 0; j < faceList.size(); j++ )
  985. {
  986. if ( faceList[j].points.contains( i ) )
  987. counter++;
  988. }
  989. if ( counter < 3 )
  990. return false;
  991. }
  992. // Test for co-planar faces.
  993. for ( S32 i = 0; i < shape->mPlanes.size(); i++ )
  994. {
  995. for ( S32 j = i + 1; j < shape->mPlanes.size(); j++ )
  996. {
  997. F32 d = mDot( shape->mPlanes[i], shape->mPlanes[j] );
  998. if ( d > 0.999f )
  999. return false;
  1000. }
  1001. }
  1002. // Test for faces with zero or negative area.
  1003. for ( S32 i = 0; i < shape->mGeometry.faces.size(); i++ )
  1004. {
  1005. if ( shape->mGeometry.faces[i].area < 0.0f )
  1006. return false;
  1007. if ( shape->mGeometry.faces[i].triangles.empty() )
  1008. return false;
  1009. }
  1010. return true;
  1011. }
  1012. void GuiConvexEditorCtrl::setupShape( ConvexShape *shape )
  1013. {
  1014. shape->setField( "material", mMaterialName );
  1015. shape->registerObject();
  1016. updateShape( shape );
  1017. SimGroup *group;
  1018. if ( Sim::findObject( "missionGroup", group ) )
  1019. group->addObject( shape );
  1020. }
  1021. void GuiConvexEditorCtrl::updateShape( ConvexShape *shape, S32 offsetFace )
  1022. {
  1023. shape->_updateGeometry( true );
  1024. /*
  1025. if ( offsetFace != -1 )
  1026. {
  1027. shape->mSurfaces[ offsetFace ].setPosition( mPivotPos );
  1028. }*/
  1029. synchClientObject( shape );
  1030. }
  1031. void GuiConvexEditorCtrl::synchClientObject( const ConvexShape *serverConvex )
  1032. {
  1033. if ( serverConvex->getClientObject() )
  1034. {
  1035. ConvexShape *clientConvex = static_cast< ConvexShape* >( serverConvex->getClientObject() );
  1036. clientConvex->setScale( serverConvex->getScale() );
  1037. clientConvex->setTransform( serverConvex->getTransform() );
  1038. clientConvex->mSurfaces.clear();
  1039. clientConvex->mSurfaces.merge( serverConvex->mSurfaces );
  1040. clientConvex->_updateGeometry(true);
  1041. }
  1042. }
  1043. void GuiConvexEditorCtrl::updateGizmoPos()
  1044. {
  1045. if ( mConvexSEL )
  1046. {
  1047. if ( mFaceSEL != -1 )
  1048. {
  1049. MatrixF surfMat = mConvexSEL->getSurfaceWorldMat( mFaceSEL );
  1050. MatrixF objToWorld( mConvexSEL->getTransform() );
  1051. objToWorld.scale( mConvexSEL->getScale() );
  1052. Point3F gizmoPos(0,0,0);
  1053. if ( mUsingPivot )
  1054. {
  1055. gizmoPos = mPivotPos;
  1056. }
  1057. else
  1058. {
  1059. Point3F faceCenterPnt = mConvexSEL->mSurfaces[ mFaceSEL ].getPosition();
  1060. objToWorld.mulP( faceCenterPnt );
  1061. mGizmoMatOffset = surfMat.getPosition() - faceCenterPnt;
  1062. gizmoPos = faceCenterPnt;
  1063. }
  1064. mGizmo->set( surfMat, gizmoPos, Point3F::One );
  1065. }
  1066. else
  1067. {
  1068. mGizmoMatOffset = Point3F::Zero;
  1069. mGizmo->set( mConvexSEL->getTransform(), mConvexSEL->getPosition(), mConvexSEL->getScale() );
  1070. }
  1071. }
  1072. }
  1073. bool GuiConvexEditorCtrl::setActiveTool( ConvexEditorTool *tool )
  1074. {
  1075. if ( mActiveTool == tool )
  1076. return false;
  1077. ConvexEditorTool *prevTool = mActiveTool;
  1078. ConvexEditorTool *newTool = tool;
  1079. if ( prevTool )
  1080. prevTool->onDeactivated( newTool );
  1081. mActiveTool = newTool;
  1082. if ( newTool )
  1083. newTool->onActivated( prevTool );
  1084. return true;
  1085. }
  1086. bool GuiConvexEditorCtrl::handleEscape()
  1087. {
  1088. if ( mActiveTool )
  1089. {
  1090. mActiveTool->onDeactivated( NULL );
  1091. mActiveTool = NULL;
  1092. return true;
  1093. }
  1094. if ( mFaceSEL != -1 )
  1095. {
  1096. setSelection( mConvexSEL, -1 );
  1097. return true;
  1098. }
  1099. if ( mConvexSEL )
  1100. {
  1101. setSelection( NULL, -1 );
  1102. return true;
  1103. }
  1104. return false;
  1105. }
  1106. bool GuiConvexEditorCtrl::handleDelete()
  1107. {
  1108. if ( mActiveTool )
  1109. {
  1110. mActiveTool->onDeactivated( NULL );
  1111. mActiveTool = NULL;
  1112. }
  1113. if ( mConvexSEL )
  1114. {
  1115. if ( mFaceSEL != -1 )
  1116. {
  1117. submitUndo( ModifyShape, mConvexSEL );
  1118. mConvexSEL->mSurfaces.erase_fast( mFaceSEL );
  1119. updateShape( mConvexSEL );
  1120. if ( !isShapeValid( mConvexSEL ) )
  1121. {
  1122. S32 selFace = mFaceSEL;
  1123. mLastUndo->undo();
  1124. mFaceSEL = selFace;
  1125. updateShape( mConvexSEL );
  1126. updateGizmoPos();
  1127. }
  1128. else
  1129. {
  1130. setSelection( mConvexSEL, -1 );
  1131. }
  1132. }
  1133. else
  1134. {
  1135. // Grab the mission editor undo manager.
  1136. UndoManager *undoMan = NULL;
  1137. if ( !Sim::findObject( "EUndoManager", undoMan ) )
  1138. {
  1139. Con::errorf( "GuiConvexEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
  1140. }
  1141. else
  1142. {
  1143. // Create the UndoAction.
  1144. MEDeleteUndoAction *action = new MEDeleteUndoAction("Deleted ConvexShape");
  1145. action->deleteObject( mConvexSEL );
  1146. mIsDirty = true;
  1147. mFaceHL = -1;
  1148. setSelection( NULL, -1 );
  1149. // Submit it.
  1150. undoMan->addAction( action );
  1151. }
  1152. }
  1153. }
  1154. return true;
  1155. }
  1156. bool GuiConvexEditorCtrl::hasSelection() const
  1157. {
  1158. return mConvexSEL != NULL;
  1159. }
  1160. void GuiConvexEditorCtrl::clearSelection()
  1161. {
  1162. mFaceHL = -1;
  1163. mConvexHL = NULL;
  1164. setSelection( NULL, -1 );
  1165. }
  1166. void GuiConvexEditorCtrl::handleDeselect()
  1167. {
  1168. if ( mActiveTool )
  1169. {
  1170. mActiveTool->onDeactivated( NULL );
  1171. mActiveTool = NULL;
  1172. }
  1173. mFaceHL = -1;
  1174. mConvexHL = NULL;
  1175. setSelection( NULL, -1 );
  1176. }
  1177. void GuiConvexEditorCtrl::setSelection( ConvexShape *shape, S32 faceId )
  1178. {
  1179. mFaceSEL = faceId;
  1180. mConvexSEL = shape;
  1181. updateGizmoPos();
  1182. Con::executef( this, "onSelectionChanged", shape ? shape->getIdString() : "", Con::getIntArg(faceId) );
  1183. }
  1184. void GuiConvexEditorCtrl::_prepRenderImage( SceneManager* sceneGraph, const SceneRenderState* state )
  1185. {
  1186. if ( !isAwake() )
  1187. return;
  1188. /*
  1189. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  1190. ri->type = RenderPassManager::RIT_Editor;
  1191. ri->renderDelegate.bind( this, &GuiConvexEditorCtrl::_renderObject );
  1192. ri->defaultKey = 100;
  1193. state->getRenderPass()->addInst( ri );
  1194. */
  1195. }
  1196. void GuiConvexEditorCtrl::_renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *matInst )
  1197. {
  1198. }
  1199. void GuiConvexEditorCtrl::submitUndo( UndoType type, ConvexShape *shape )
  1200. {
  1201. Vector< ConvexShape* > shapes;
  1202. shapes.push_back( shape );
  1203. submitUndo( type, shapes );
  1204. }
  1205. void GuiConvexEditorCtrl::submitUndo( UndoType type, const Vector<ConvexShape*> &shapes )
  1206. {
  1207. // Grab the mission editor undo manager.
  1208. Sim::findObject( "EUndoManager", mUndoManager );
  1209. if ( !mUndoManager )
  1210. {
  1211. Con::errorf( "GuiConvexEditorCtrl::submitUndo() - EUndoManager not found!" );
  1212. return;
  1213. }
  1214. if ( type == ModifyShape )
  1215. {
  1216. // Setup the action.
  1217. GuiConvexEditorUndoAction *action = new GuiConvexEditorUndoAction( "Modified a ConvexShape" );
  1218. ConvexShape *shape = shapes.first();
  1219. action->mObjId = shape->getId();
  1220. action->mEditor = this;
  1221. action->mSavedObjToWorld = shape->getTransform();
  1222. action->mSavedScale = shape->getScale();
  1223. action->mSavedSurfaces.merge( shape->mSurfaces );
  1224. action->mUndoManager = mUndoManager;
  1225. mUndoManager->addAction( action );
  1226. mLastUndo = action;
  1227. }
  1228. else if ( type == CreateShape )
  1229. {
  1230. MECreateUndoAction *action = new MECreateUndoAction( "Create ConvexShape" );
  1231. for ( S32 i = 0; i < shapes.size(); i++ )
  1232. action->addObject( shapes[i] );
  1233. mUndoManager->addAction( action );
  1234. mLastUndo = action;
  1235. }
  1236. else if ( type == DeleteShape )
  1237. {
  1238. MEDeleteUndoAction *action = new MEDeleteUndoAction( "Deleted ConvexShape" );
  1239. for ( S32 i = 0; i < shapes.size(); i++ )
  1240. action->deleteObject( shapes[i] );
  1241. mUndoManager->addAction( action );
  1242. mLastUndo = action;
  1243. }
  1244. else if ( type == HollowShape )
  1245. {
  1246. CompoundUndoAction *action = new CompoundUndoAction( "Hollow ConvexShape" );
  1247. MECreateUndoAction *createAction = new MECreateUndoAction();
  1248. MEDeleteUndoAction *deleteAction = new MEDeleteUndoAction();
  1249. deleteAction->deleteObject( shapes.first() );
  1250. for ( S32 i = 1; i < shapes.size(); i++ )
  1251. createAction->addObject( shapes[i] );
  1252. action->addAction( deleteAction );
  1253. action->addAction( createAction );
  1254. mUndoManager->addAction( action );
  1255. mLastUndo = action;
  1256. }
  1257. mIsDirty = true;
  1258. }
  1259. bool GuiConvexEditorCtrl::_cursorCastCallback( RayInfo* ri )
  1260. {
  1261. // Reject anything that's not a ConvexShape.
  1262. return dynamic_cast< ConvexShape* >( ri->object );
  1263. }
  1264. bool GuiConvexEditorCtrl::_cursorCast( const Gui3DMouseEvent &event, ConvexShape **hitShape, S32 *hitFace )
  1265. {
  1266. RayInfo ri;
  1267. if ( gServerContainer.castRay( event.pos, event.pos + event.vec * 10000.0f, StaticShapeObjectType, &ri, &GuiConvexEditorCtrl::_cursorCastCallback ) &&
  1268. dynamic_cast< ConvexShape* >( ri.object ) )
  1269. {
  1270. // Do not select or edit ConvexShapes that are within a Prefab.
  1271. if ( Prefab::getPrefabByChild( ri.object ) )
  1272. return false;
  1273. *hitShape = static_cast< ConvexShape* >( ri.object );
  1274. *hitFace = ri.face;
  1275. mLastRayInfo = ri;
  1276. return true;
  1277. }
  1278. return false;
  1279. }
  1280. void GuiConvexEditorCtrl::setPivotPos( ConvexShape *shape, S32 faceId, const Gui3DMouseEvent &event )
  1281. {
  1282. PlaneF plane;
  1283. mTransformPlane( shape->getTransform(), shape->getScale(), shape->mPlanes[ faceId ], &plane );
  1284. Point3F start( event.pos );
  1285. Point3F end( start + event.vec * 10000.0f );
  1286. F32 t = plane.intersect( start, end );
  1287. if ( t >= 0.0f && t <= 1.0f )
  1288. {
  1289. Point3F hitPos;
  1290. hitPos.interpolate( start, end, t );
  1291. mPivotPos = hitPos;
  1292. mUsingPivot = true;
  1293. MatrixF worldToObj( shape->getTransform() );
  1294. worldToObj.scale( shape->getScale() );
  1295. worldToObj.inverse();
  1296. Point3F objPivotPos( mPivotPos );
  1297. worldToObj.mulP( objPivotPos );
  1298. updateGizmoPos();
  1299. }
  1300. }
  1301. void GuiConvexEditorCtrl::cleanMatrix( MatrixF &mat )
  1302. {
  1303. if ( mat.isAffine() )
  1304. return;
  1305. VectorF col0 = mat.getColumn3F(0);
  1306. VectorF col1 = mat.getColumn3F(1);
  1307. VectorF col2 = mat.getColumn3F(2);
  1308. col0.normalize();
  1309. col1.normalize();
  1310. col2.normalize();
  1311. col2 = mCross( col0, col1 );
  1312. col2.normalize();
  1313. col1 = mCross( col2, col0 );
  1314. col1.normalize();
  1315. col0 = mCross( col1, col2 );
  1316. col0.normalize();
  1317. mat.setColumn(0,col0);
  1318. mat.setColumn(1,col1);
  1319. mat.setColumn(2,col2);
  1320. AssertFatal( mat.isAffine(), "GuiConvexEditorCtrl::cleanMatrix, non-affine matrix" );
  1321. }
  1322. S32 GuiConvexEditorCtrl::getEdgeByPoints( ConvexShape *shape, S32 faceId, S32 p0, S32 p1 )
  1323. {
  1324. const ConvexShape::Face &face = shape->mGeometry.faces[faceId];
  1325. for ( S32 i = 0; i < face.edges.size(); i++ )
  1326. {
  1327. const ConvexShape::Edge &edge = face.edges[i];
  1328. if ( edge.p0 != p0 && edge.p0 != p1 )
  1329. continue;
  1330. if ( edge.p1 != p0 && edge.p1 != p1 )
  1331. continue;
  1332. return i;
  1333. }
  1334. return -1;
  1335. }
  1336. bool GuiConvexEditorCtrl::getEdgesTouchingPoint( ConvexShape *shape, S32 faceId, S32 pId, Vector< U32 > &edgeIdxList, S32 excludeEdge )
  1337. {
  1338. const ConvexShape::Face &face = shape->mGeometry.faces[faceId];
  1339. const Vector< ConvexShape::Edge > &edgeList = face.edges;
  1340. for ( S32 i = 0; i < edgeList.size(); i++ )
  1341. {
  1342. if ( i == excludeEdge )
  1343. continue;
  1344. const ConvexShape::Edge &curEdge = edgeList[i];
  1345. if ( curEdge.p0 == pId || curEdge.p1 == pId )
  1346. edgeIdxList.push_back(i);
  1347. }
  1348. return !edgeIdxList.empty();
  1349. }
  1350. void GuiConvexEditorUndoAction::undo()
  1351. {
  1352. ConvexShape *object = NULL;
  1353. if ( !Sim::findObject( mObjId, object ) )
  1354. return;
  1355. // Temporarily save the ConvexShape current data.
  1356. Vector< MatrixF > tempSurfaces;
  1357. tempSurfaces.merge( object->mSurfaces );
  1358. MatrixF tempObjToWorld( object->getTransform() );
  1359. Point3F tempScale( object->getScale() );
  1360. // Restore the Object to the UndoAction state.
  1361. object->mSurfaces.clear();
  1362. object->mSurfaces.merge( mSavedSurfaces );
  1363. object->setScale( mSavedScale );
  1364. object->setTransform( mSavedObjToWorld );
  1365. // Regenerate the ConvexShape and synch the client object.
  1366. object->_updateGeometry();
  1367. GuiConvexEditorCtrl::synchClientObject( object );
  1368. // If applicable set the selected ConvexShape and face
  1369. // on the editor.
  1370. mEditor->setSelection( object, -1 );
  1371. mEditor->updateGizmoPos();
  1372. // Now save the previous ConvexShape data in this UndoAction
  1373. // since an undo action must become a redo action and vice-versa
  1374. mSavedObjToWorld = tempObjToWorld;
  1375. mSavedScale = tempScale;
  1376. mSavedSurfaces.clear();
  1377. mSavedSurfaces.merge( tempSurfaces );
  1378. }
  1379. ConvexEditorCreateTool::ConvexEditorCreateTool( GuiConvexEditorCtrl *editor )
  1380. : Parent( editor ),
  1381. mStage( -1 ),
  1382. mNewConvex( NULL )
  1383. {
  1384. }
  1385. void ConvexEditorCreateTool::onActivated( ConvexEditorTool *prevTool )
  1386. {
  1387. mEditor->clearSelection();
  1388. mStage = -1;
  1389. mNewConvex = NULL;
  1390. }
  1391. void ConvexEditorCreateTool::onDeactivated( ConvexEditorTool *newTool )
  1392. {
  1393. if ( mNewConvex )
  1394. mNewConvex->deleteObject();
  1395. mStage = -1;
  1396. mNewConvex = NULL;
  1397. mEditor->mouseUnlock();
  1398. }
  1399. ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseDown( const Gui3DMouseEvent &event )
  1400. {
  1401. if ( mStage == -1 )
  1402. {
  1403. mEditor->setFirstResponder();
  1404. mEditor->mouseLock();
  1405. Point3F start( event.pos );
  1406. Point3F end( event.pos + event.vec * 10000.0f );
  1407. RayInfo ri;
  1408. bool hit = gServerContainer.castRay( event.pos, end, STATIC_COLLISION_TYPEMASK, &ri );
  1409. MatrixF objMat( true );
  1410. // Calculate the orientation matrix of the new ConvexShape
  1411. // based on what has been clicked.
  1412. if ( !hit )
  1413. {
  1414. objMat.setPosition( event.pos + event.vec * 100.0f );
  1415. }
  1416. else
  1417. {
  1418. if ( dynamic_cast< ConvexShape* >( ri.object ) )
  1419. {
  1420. ConvexShape *hitShape = static_cast< ConvexShape* >( ri.object );
  1421. objMat = hitShape->getSurfaceWorldMat( ri.face );
  1422. objMat.setPosition( ri.point );
  1423. }
  1424. else
  1425. {
  1426. Point3F rvec;
  1427. Point3F fvec( mEditor->getCameraMat().getForwardVector() );
  1428. Point3F uvec( ri.normal );
  1429. rvec = mCross( fvec, uvec );
  1430. if ( rvec.isZero() )
  1431. {
  1432. fvec = mEditor->getCameraMat().getRightVector();
  1433. rvec = mCross( fvec, uvec );
  1434. }
  1435. rvec.normalizeSafe();
  1436. fvec = mCross( uvec, rvec );
  1437. fvec.normalizeSafe();
  1438. uvec = mCross( rvec, fvec );
  1439. uvec.normalizeSafe();
  1440. objMat.setColumn( 0, rvec );
  1441. objMat.setColumn( 1, fvec );
  1442. objMat.setColumn( 2, uvec );
  1443. objMat.setPosition( ri.point );
  1444. }
  1445. }
  1446. mNewConvex = new ConvexShape();
  1447. mNewConvex->setTransform( objMat );
  1448. mNewConvex->setField( "material", Parent::mEditor->mMaterialName );
  1449. mNewConvex->registerObject();
  1450. mPlaneSizes.set( 0.1f, 0.1f, 0.1f );
  1451. mNewConvex->resizePlanes( mPlaneSizes );
  1452. mEditor->updateShape( mNewConvex );
  1453. mTransform = objMat;
  1454. mCreatePlane.set( objMat.getPosition(), objMat.getUpVector() );
  1455. }
  1456. else if ( mStage == 0 )
  1457. {
  1458. // Handle this on mouseUp
  1459. }
  1460. return Handled;
  1461. }
  1462. ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseUp( const Gui3DMouseEvent &event )
  1463. {
  1464. if ( mNewConvex && mStage == -1 )
  1465. {
  1466. mStage = 0;
  1467. mCreatePlane = PlaneF( mNewConvex->getPosition(), mNewConvex->getTransform().getForwardVector() );
  1468. mTransform.setPosition( mNewConvex->getPosition() );
  1469. return Handled;
  1470. }
  1471. else if ( mStage == 0 )
  1472. {
  1473. SimGroup *mg;
  1474. Sim::findObject( "MissionGroup", mg );
  1475. mg->addObject( mNewConvex );
  1476. mStage = -1;
  1477. // Grab the mission editor undo manager.
  1478. UndoManager *undoMan = NULL;
  1479. if ( !Sim::findObject( "EUndoManager", undoMan ) )
  1480. {
  1481. Con::errorf( "ConvexEditorCreateTool::on3DMouseDown() - EUndoManager not found!" );
  1482. mNewConvex = NULL;
  1483. return Failed;
  1484. }
  1485. // Create the UndoAction.
  1486. MECreateUndoAction *action = new MECreateUndoAction("Create ConvexShape");
  1487. action->addObject( mNewConvex );
  1488. // Submit it.
  1489. undoMan->addAction( action );
  1490. mEditor->setField( "isDirty", "1" );
  1491. mEditor->setSelection( mNewConvex, -1 );
  1492. mNewConvex = NULL;
  1493. mEditor->mouseUnlock();
  1494. return Done;
  1495. }
  1496. return Done;
  1497. }
  1498. ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseMove( const Gui3DMouseEvent &event )
  1499. {
  1500. if ( mStage == 0 )
  1501. {
  1502. Point3F start( event.pos );
  1503. Point3F end( start + event.vec * 10000.0f );
  1504. F32 t = mCreatePlane.intersect( start, end );
  1505. Point3F hitPos;
  1506. if ( t < 0.0f || t > 1.0f )
  1507. return Handled;
  1508. hitPos.interpolate( start, end, t );
  1509. MatrixF worldToObj( mTransform );
  1510. worldToObj.inverse();
  1511. worldToObj.mulP( hitPos );
  1512. F32 delta = ( hitPos.z );
  1513. mPlaneSizes.z = getMax( 0.1f, delta );
  1514. mNewConvex->resizePlanes( mPlaneSizes );
  1515. mEditor->updateShape( mNewConvex );
  1516. Point3F pos( mTransform.getPosition() );
  1517. pos += mPlaneSizes.z * 0.5f * mTransform.getUpVector();
  1518. mNewConvex->setPosition( pos );
  1519. }
  1520. return Handled;
  1521. }
  1522. ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseDragged( const Gui3DMouseEvent &event )
  1523. {
  1524. if ( !mNewConvex || mStage != -1 )
  1525. return Handled;
  1526. Point3F start( event.pos );
  1527. Point3F end( event.pos + event.vec * 10000.0f );
  1528. F32 t = mCreatePlane.intersect( start, end );
  1529. if ( t < 0.0f || t > 1.0f )
  1530. return Handled;
  1531. Point3F hitPos;
  1532. hitPos.interpolate( start, end, t );
  1533. MatrixF xfm( mTransform );
  1534. xfm.inverse();
  1535. xfm.mulP( hitPos);
  1536. Point3F scale;
  1537. scale.x = getMax( mFabs( hitPos.x ), 0.1f );
  1538. scale.y = getMax( mFabs( hitPos.y ), 0.1f );
  1539. scale.z = 0.1f;
  1540. mNewConvex->resizePlanes( scale );
  1541. mPlaneSizes = scale;
  1542. mEditor->updateShape( mNewConvex );
  1543. Point3F pos( mTransform.getPosition() );
  1544. pos += mTransform.getRightVector() * hitPos.x * 0.5f;
  1545. pos += mTransform.getForwardVector() * hitPos.y * 0.5f;
  1546. mNewConvex->setPosition( pos );
  1547. return Handled;
  1548. }
  1549. void ConvexEditorCreateTool::renderScene( const RectI &updateRect )
  1550. {
  1551. }
  1552. ConvexShape* ConvexEditorCreateTool::extrudeShapeFromFace( ConvexShape *inShape, S32 inFaceId )
  1553. {
  1554. ConvexShape::Geometry &inShapeGeometry = inShape->getGeometry();
  1555. ConvexShape::Face &inFace = inShapeGeometry.faces[inFaceId];
  1556. Vector< Point3F > &inShapePointList = inShapeGeometry.points;
  1557. Vector< MatrixF > &inShapeSurfaces = inShape->getSurfaces();
  1558. S32 shapeFaceCount = inFace.edges.size() + 2;
  1559. MatrixF inShapeToWorld( inShape->getTransform() );
  1560. inShapeToWorld.scale( inShape->getScale() );
  1561. //MatrixF inWorldToShape( inShapeToWorld );
  1562. //inWorldToShape.inverse();
  1563. MatrixF shapeToWorld;
  1564. shapeToWorld.mul( inShape->getTransform(), inShapeSurfaces[inFaceId] );
  1565. Point3F tmp( inShapeSurfaces[inFaceId].getPosition() );
  1566. inShapeToWorld.mulP( tmp );
  1567. shapeToWorld.setPosition( tmp );
  1568. MatrixF worldToShape( shapeToWorld );
  1569. worldToShape.inverse();
  1570. MatrixF inShapeToNewShape;
  1571. inShapeToNewShape.mul( inShapeToWorld, worldToShape );
  1572. ConvexShape *newShape = new ConvexShape;
  1573. newShape->setTransform( shapeToWorld );
  1574. Vector< MatrixF > &shapeSurfaces = newShape->getSurfaces();
  1575. shapeSurfaces.setSize( shapeFaceCount );
  1576. //shapeSurfaces.setSize( 2 );
  1577. const Point3F &shapePos = shapeToWorld.getPosition();
  1578. shapeSurfaces[0].identity();
  1579. shapeSurfaces[1].identity();
  1580. shapeSurfaces[1].setColumn( 0, -shapeSurfaces[1].getColumn3F(0) );
  1581. shapeSurfaces[1].setColumn( 2, -shapeSurfaces[1].getColumn3F(2) );
  1582. for ( S32 i = 0; i < inFace.winding.size(); i++ )
  1583. {
  1584. Point3F p0 = inShapePointList[ inFace.points[ inFace.winding[ i ] ] ];
  1585. Point3F p1;
  1586. if ( i+1 < inFace.winding.size() )
  1587. p1 = inShapePointList[ inFace.points[ inFace.winding[ i+1 ] ] ];
  1588. else
  1589. p1 = inShapePointList[ inFace.points[ inFace.winding[ 0 ] ] ];
  1590. inShapeToWorld.mulP( p0 );
  1591. inShapeToWorld.mulP( p1 );
  1592. Point3F newPos = MathUtils::mClosestPointOnSegment( p0, p1, shapePos );
  1593. Point3F rvec = p0 - p1;
  1594. rvec.normalizeSafe();
  1595. Point3F fvec = shapeToWorld.getUpVector();
  1596. Point3F uvec = mCross( rvec, fvec );
  1597. if ( i + 2 >= shapeSurfaces.size() )
  1598. continue;
  1599. //F32 dt = mDot( shapeToWorld.getUpVector(), rvec );
  1600. //AssertFatal( mIsZero( dt ), "bad" );
  1601. MatrixF &surf = shapeSurfaces[i+2];
  1602. surf.identity();
  1603. surf.setColumn( 0, rvec );
  1604. surf.setColumn( 1, fvec );
  1605. surf.setColumn( 2, uvec );
  1606. surf.setPosition( newPos );
  1607. surf.mulL( worldToShape );
  1608. }
  1609. newShape->setField( "material", Parent::mEditor->mMaterialName );
  1610. newShape->registerObject();
  1611. mEditor->updateShape( newShape );
  1612. SimGroup *group;
  1613. if ( Sim::findObject( "missionGroup", group ) )
  1614. group->addObject( newShape );
  1615. return newShape;
  1616. }
  1617. void GuiConvexEditorCtrl::hollowShape( ConvexShape *shape, F32 thickness )
  1618. {
  1619. // Create a new Convex for each face of the original shape.
  1620. // This is the same as an extrude from face operation going inward by the thickness
  1621. // for every face.
  1622. Vector< ConvexShape* > convexList;
  1623. for ( S32 i = 0; i < shape->mGeometry.faces.size(); i++ )
  1624. {
  1625. ConvexShape *faceShape = mCreateTool->extrudeShapeFromFace( shape, i );
  1626. MatrixF &inwardFace = faceShape->mSurfaces[1];
  1627. //MatrixF &outwardFace = faceShape->mSurfaces[0];
  1628. Point3F invec = inwardFace.getUpVector();
  1629. inwardFace.setPosition( inwardFace.getPosition() + invec * thickness );
  1630. updateShape( faceShape );
  1631. convexList.push_back( faceShape );
  1632. }
  1633. convexList.push_front( shape );
  1634. submitUndo( HollowShape, convexList );
  1635. }
  1636. void GuiConvexEditorCtrl::hollowSelection()
  1637. {
  1638. if ( mConvexSEL )
  1639. {
  1640. hollowShape( mConvexSEL, 0.15f );
  1641. setSelection( NULL, -1 );
  1642. }
  1643. }
  1644. void GuiConvexEditorCtrl::recenterSelection()
  1645. {
  1646. if ( mConvexSEL )
  1647. {
  1648. recenterShape( mConvexSEL );
  1649. updateGizmoPos();
  1650. }
  1651. }
  1652. void GuiConvexEditorCtrl::recenterShape( ConvexShape *shape )
  1653. {
  1654. submitUndo( ModifyShape, shape );
  1655. shape->recenter();
  1656. synchClientObject( shape );
  1657. }
  1658. void GuiConvexEditorCtrl::dropSelectionAtScreenCenter()
  1659. {
  1660. // This code copied from WorldEditor.
  1661. // All the dropping code would be moved to somewhere common, but its not.
  1662. if ( !mConvexSEL )
  1663. return;
  1664. // Calculate the center of the screen (in global screen coordinates)
  1665. Point2I offset = localToGlobalCoord(Point2I(0,0));
  1666. Point3F sp(F32(offset.x + F32(getExtent().x / 2)), F32(offset.y + (getExtent().y / 2)), 1.0f);
  1667. // Calculate the view distance to fit the selection
  1668. // within the camera's view.
  1669. const Box3F bounds = mConvexSEL->getWorldBox();
  1670. F32 radius = bounds.len()*0.5f;
  1671. F32 viewdist = calculateViewDistance(radius);
  1672. // Be careful of infinite sized objects, or just large ones in general.
  1673. if(viewdist > 100.0f )
  1674. viewdist = 100.0f;
  1675. // Position the selection
  1676. mConvexSEL->setPosition( smCamPos + smCamMatrix.getForwardVector() * viewdist );
  1677. synchClientObject( mConvexSEL );
  1678. updateGizmoPos();
  1679. }
  1680. void GuiConvexEditorCtrl::splitSelectedFace()
  1681. {
  1682. if ( !mConvexSEL || mFaceSEL == -1 )
  1683. return;
  1684. if ( !isShapeValid( mConvexSEL ) )
  1685. return;
  1686. mLastValidShape = mConvexSEL->mSurfaces;
  1687. const F32 radians = mDegToRad( 15.0f );
  1688. Point3F rot( 0, 0, 0 );
  1689. MatrixF rotMat( true );
  1690. mConvexSEL->mSurfaces.increment();
  1691. MatrixF &dstMat = mConvexSEL->mSurfaces.last();
  1692. const MatrixF &srcMat = mConvexSEL->mSurfaces[mFaceSEL];
  1693. for ( S32 i = 0; i < 6; i++ )
  1694. {
  1695. F32 sign = i > 2 ? -1.0f : 1.0f;
  1696. U32 idx = i % 3;
  1697. rot.zero();
  1698. rot[idx] = sign * radians;
  1699. rotMat.set( (EulerF)rot );
  1700. dstMat = srcMat * rotMat;
  1701. updateShape( mConvexSEL );
  1702. if ( isShapeValid( mConvexSEL ) )
  1703. {
  1704. mSavedSurfaces = mConvexSEL->mSurfaces;
  1705. mConvexSEL->mSurfaces = mLastValidShape;
  1706. submitUndo( ModifyShape, mConvexSEL );
  1707. mConvexSEL->mSurfaces = mSavedSurfaces;
  1708. mLastValidShape = mSavedSurfaces;
  1709. setSelection( mConvexSEL, mConvexSEL->mSurfaces.size() - 1 );
  1710. return;
  1711. }
  1712. }
  1713. mConvexSEL->mSurfaces = mLastValidShape;
  1714. updateShape( mConvexSEL );
  1715. updateGizmoPos();
  1716. }
  1717. ConsoleMethod( GuiConvexEditorCtrl, hollowSelection, void, 2, 2, "" )
  1718. {
  1719. object->hollowSelection();
  1720. }
  1721. ConsoleMethod( GuiConvexEditorCtrl, recenterSelection, void, 2, 2, "" )
  1722. {
  1723. object->recenterSelection();
  1724. }
  1725. ConsoleMethod( GuiConvexEditorCtrl, hasSelection, S32, 2, 2, "" )
  1726. {
  1727. return object->hasSelection();
  1728. }
  1729. ConsoleMethod( GuiConvexEditorCtrl, handleDelete, void, 2, 2, "" )
  1730. {
  1731. object->handleDelete();
  1732. }
  1733. ConsoleMethod( GuiConvexEditorCtrl, handleDeselect, void, 2, 2, "" )
  1734. {
  1735. object->handleDeselect();
  1736. }
  1737. ConsoleMethod( GuiConvexEditorCtrl, dropSelectionAtScreenCenter, void, 2, 2, "" )
  1738. {
  1739. object->dropSelectionAtScreenCenter();
  1740. }
  1741. ConsoleMethod( GuiConvexEditorCtrl, selectConvex, void, 3, 3, "( ConvexShape )" )
  1742. {
  1743. ConvexShape *convex;
  1744. if ( Sim::findObject( argv[2], convex ) )
  1745. object->setSelection( convex, -1 );
  1746. }
  1747. ConsoleMethod( GuiConvexEditorCtrl, splitSelectedFace, void, 2, 2, "" )
  1748. {
  1749. object->splitSelectedFace();
  1750. }