guiRiverEditorCtrl.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  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 "environment/editors/guiRiverEditorCtrl.h"
  24. #include "console/consoleTypes.h"
  25. #include "environment/river.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 "T3D/prefab.h"
  42. IMPLEMENT_CONOBJECT(GuiRiverEditorCtrl);
  43. ConsoleDocClass( GuiRiverEditorCtrl,
  44. "@brief GUI tool that makes up the River Editor\n\n"
  45. "Editor use only.\n\n"
  46. "@internal"
  47. );
  48. GuiRiverEditorCtrl::GuiRiverEditorCtrl()
  49. : mDefaultNormal( 0, 0, 1 ),
  50. mDefaultWidth( 10.0f ),
  51. mDefaultDepth( 5.0f )
  52. {
  53. // Each of the mode names directly correlates with the River Editor's
  54. // tool palette
  55. mSelectRiverMode = "RiverEditorSelectMode";
  56. mAddRiverMode = "RiverEditorAddRiverMode";
  57. mMovePointMode = "RiverEditorMoveMode";
  58. mRotatePointMode = "RiverEditorRotateMode";
  59. mScalePointMode = "RiverEditorScaleMode";
  60. mAddNodeMode = "RiverEditorAddNodeMode";
  61. mInsertPointMode = "RiverEditorInsertPointMode";
  62. mRemovePointMode = "RiverEditorRemovePointMode";
  63. mMode = mSelectRiverMode;
  64. mRiverSet = NULL;
  65. mSelNode = -1;
  66. mSelRiver = NULL;
  67. mHoverRiver = NULL;
  68. mAddNodeIdx = 0;
  69. mHoverNode = -1;
  70. mInsertIdx = -1;
  71. mStartWidth = -1.0f;
  72. mStartHeight = -1.0f;
  73. mStartX = 0;
  74. mIsDirty = false;
  75. mNodeHalfSize.set(4,4);
  76. mNodeSphereRadius = 15.0f;
  77. mNodeSphereFillColor.set( 15,15,100,145 );
  78. mNodeSphereLineColor.set( 25,25,25,0 );
  79. mHoverSplineColor.set( 255,0,0,255 );
  80. mSelectedSplineColor.set( 0,255,0,255 );
  81. mHoverNodeColor.set( 255,255,255,255 );
  82. mStartDragMousePoint = InvalidMousePoint;
  83. //mMoveNodeCursor = NULL;
  84. //mAddNodeCursor = NULL;
  85. //mInsertNodeCursor = NULL;
  86. //mResizeNodeCursor = NULL;
  87. }
  88. GuiRiverEditorCtrl::~GuiRiverEditorCtrl()
  89. {
  90. // nothing to do
  91. }
  92. void GuiRiverEditorUndoAction::undo()
  93. {
  94. River *river = NULL;
  95. if ( !Sim::findObject( mObjId, river ) )
  96. return;
  97. // Temporarily save the Rivers current data.
  98. F32 metersPerSeg = river->mMetersPerSegment;
  99. Vector<RiverNode> nodes;
  100. nodes.merge( river->mNodes );
  101. // Restore the River properties saved in the UndoAction
  102. river->mMetersPerSegment = mMetersPerSegment;
  103. // Restore the Nodes saved in the UndoAction
  104. river->mNodes.clear();
  105. for ( U32 i = 0; i < mNodes.size(); i++ )
  106. {
  107. river->_addNode( mNodes[i].point, mNodes[i].width, mNodes[i].depth, mNodes[i].normal );
  108. }
  109. // Regenerate the River
  110. river->regenerate();
  111. // If applicable set the selected River and node
  112. mRiverEditor->mSelRiver = river;
  113. mRiverEditor->mSelNode = -1;
  114. // Now save the previous River data in this UndoAction
  115. // since an undo action must become a redo action and vice-versa
  116. mMetersPerSegment = metersPerSeg;
  117. mNodes.clear();
  118. mNodes.merge( nodes );
  119. }
  120. bool GuiRiverEditorCtrl::onAdd()
  121. {
  122. if( !Parent::onAdd() )
  123. return false;
  124. mRiverSet = River::getServerSet();
  125. GFXStateBlockDesc desc;
  126. desc.fillMode = GFXFillSolid;
  127. desc.setBlend( false );
  128. desc.setZReadWrite( false, false );
  129. desc.setCullMode( GFXCullNone );
  130. mZDisableSB = GFX->createStateBlock(desc);
  131. desc.setZReadWrite( true, true );
  132. mZEnableSB = GFX->createStateBlock(desc);
  133. SceneManager::getPreRenderSignal().notify( this, &GuiRiverEditorCtrl::_prepRenderImage );
  134. return true;
  135. }
  136. void GuiRiverEditorCtrl::initPersistFields()
  137. {
  138. addField( "DefaultWidth", TypeF32, Offset( mDefaultWidth, GuiRiverEditorCtrl ) );
  139. addField( "DefaultDepth", TypeF32, Offset( mDefaultDepth, GuiRiverEditorCtrl ) );
  140. addField( "DefaultNormal", TypePoint3F,Offset( mDefaultNormal, GuiRiverEditorCtrl ) );
  141. addField( "HoverSplineColor", TypeColorI, Offset( mHoverSplineColor, GuiRiverEditorCtrl ) );
  142. addField( "SelectedSplineColor", TypeColorI, Offset( mSelectedSplineColor, GuiRiverEditorCtrl ) );
  143. addField( "HoverNodeColor", TypeColorI, Offset( mHoverNodeColor, GuiRiverEditorCtrl ) );
  144. addField( "isDirty", TypeBool, Offset( mIsDirty, GuiRiverEditorCtrl ) );
  145. //addField( "MoveNodeCursor", TYPEID< SimObject >(), Offset( mMoveNodeCursor, GuiRiverEditorCtrl) );
  146. //addField( "AddNodeCursor", TYPEID< SimObject >(), Offset( mAddNodeCursor, GuiRiverEditorCtrl) );
  147. //addField( "InsertNodeCursor", TYPEID< SimObject >(), Offset( mInsertNodeCursor, GuiRiverEditorCtrl) );
  148. //addField( "ResizeNodeCursor", TYPEID< SimObject >(), Offset( mResizeNodeCursor, GuiRiverEditorCtrl) );
  149. Parent::initPersistFields();
  150. }
  151. void GuiRiverEditorCtrl::onSleep()
  152. {
  153. Parent::onSleep();
  154. mMode = mSelectRiverMode;
  155. mHoverNode = -1;
  156. mHoverRiver = NULL;
  157. setSelectedNode(-1);
  158. //mSelRiver = NULL;
  159. //mSelNode = -1;
  160. }
  161. void GuiRiverEditorCtrl::get3DCursor( GuiCursor *&cursor,
  162. bool &visible,
  163. const Gui3DMouseEvent &event_ )
  164. {
  165. //cursor = mAddNodeCursor;
  166. //visible = false;
  167. cursor = NULL;
  168. visible = false;
  169. GuiCanvas *root = getRoot();
  170. if ( !root )
  171. return;
  172. S32 currCursor = PlatformCursorController::curArrow;
  173. if ( root->mCursorChanged == currCursor )
  174. return;
  175. PlatformWindow *window = root->getPlatformWindow();
  176. PlatformCursorController *controller = window->getCursorController();
  177. // We've already changed the cursor,
  178. // so set it back before we change it again.
  179. if( root->mCursorChanged != -1)
  180. controller->popCursor();
  181. // Now change the cursor shape
  182. controller->pushCursor(currCursor);
  183. root->mCursorChanged = currCursor;
  184. }
  185. void GuiRiverEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
  186. {
  187. _process3DMouseDown( event );
  188. mGizmo->on3DMouseDown( event );
  189. if ( !isFirstResponder() )
  190. setFirstResponder();
  191. }
  192. void GuiRiverEditorCtrl::_process3DMouseDown( const Gui3DMouseEvent& event )
  193. {
  194. // Get the raycast collision position
  195. Point3F tPos;
  196. if ( !getStaticPos( event, tPos ) )
  197. return;
  198. mouseLock();
  199. // Construct a LineSegment from the camera position to 1000 meters away in
  200. // the direction clicked.
  201. // If that segment hits the terrain, truncate the ray to only be that length.
  202. // We will use a LineSegment/Sphere intersection test to determine if a RiverNode
  203. // was clicked.
  204. Point3F startPnt = event.pos;
  205. Point3F endPnt = event.pos + event.vec * 1000.0f;
  206. RayInfo ri;
  207. if ( gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri) )
  208. endPnt = ri.point;
  209. River *riverPtr = NULL;
  210. River *clickedRiverPtr = NULL;
  211. // Did we click on a river? check current selection first
  212. U32 insertNodeIdx = -1;
  213. Point3F collisionPnt;
  214. if ( mSelRiver != NULL && mSelRiver->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
  215. {
  216. clickedRiverPtr = mSelRiver;
  217. }
  218. else
  219. {
  220. for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
  221. {
  222. riverPtr = static_cast<River*>( *iter );
  223. // Do not select or edit a River within a Prefab.
  224. if ( Prefab::getPrefabByChild(riverPtr) )
  225. continue;
  226. if ( riverPtr->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
  227. {
  228. clickedRiverPtr = riverPtr;
  229. break;
  230. }
  231. }
  232. }
  233. // Did we click on a riverNode?
  234. bool nodeClicked = false;
  235. S32 clickedNodeIdx = -1;
  236. F32 clickedNodeDist = mNodeSphereRadius;
  237. // If we clicked on the currently selected river, only scan its nodes
  238. if ( mSelRiver != NULL && clickedRiverPtr == mSelRiver )
  239. {
  240. for ( U32 i = 0; i < mSelRiver->mNodes.size(); i++ )
  241. {
  242. const Point3F &nodePos = mSelRiver->mNodes[i].point;
  243. Point3F screenPos;
  244. project( nodePos, &screenPos );
  245. F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
  246. if ( dist < clickedNodeDist )
  247. {
  248. clickedNodeDist = dist;
  249. clickedNodeIdx = i;
  250. insertNodeIdx = i;
  251. nodeClicked = true;
  252. }
  253. }
  254. }
  255. else
  256. {
  257. for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
  258. {
  259. riverPtr = static_cast<River*>( *iter );
  260. // Do not select or edit a River within a Prefab.
  261. if ( Prefab::getPrefabByChild(riverPtr) )
  262. continue;
  263. for ( U32 i = 0; i < riverPtr->mNodes.size(); i++ )
  264. {
  265. const Point3F &nodePos = riverPtr->mNodes[i].point;
  266. Point3F screenPos;
  267. project( nodePos, &screenPos );
  268. F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
  269. if ( dist < clickedNodeDist )
  270. {
  271. // we found a hit!
  272. clickedNodeDist = dist;
  273. clickedNodeIdx = i;
  274. insertNodeIdx = i;
  275. nodeClicked = true;
  276. clickedRiverPtr = riverPtr;
  277. }
  278. }
  279. }
  280. }
  281. // shortcuts
  282. bool dblClick = ( event.mouseClickCount > 1 );
  283. if( dblClick )
  284. {
  285. if( mMode == mSelectRiverMode )
  286. {
  287. setMode( mAddRiverMode, true );
  288. return;
  289. }
  290. if( mMode == mAddNodeMode )
  291. {
  292. // Delete the node attached to the cursor.
  293. deleteSelectedNode();
  294. mMode = mAddRiverMode;
  295. return;
  296. }
  297. }
  298. //this check is here in order to bounce back from deleting a whole road with ctrl+z
  299. //this check places the editor back into addrivermode
  300. if ( mMode == mAddNodeMode )
  301. {
  302. if ( !mSelRiver )
  303. mMode = mAddRiverMode;
  304. }
  305. if ( mMode == mSelectRiverMode )
  306. {
  307. // Did not click on a River or a node.
  308. if ( !clickedRiverPtr )
  309. {
  310. setSelectedRiver( NULL );
  311. setSelectedNode( -1 );
  312. return;
  313. }
  314. // Clicked on a River that wasn't the currently selected River.
  315. if ( clickedRiverPtr != mSelRiver )
  316. {
  317. setSelectedRiver( clickedRiverPtr );
  318. setSelectedNode( clickedNodeIdx );
  319. return;
  320. }
  321. // Clicked on a node in the currently selected River that wasn't
  322. // the currently selected node.
  323. if ( nodeClicked )
  324. {
  325. setSelectedNode( clickedNodeIdx );
  326. return;
  327. }
  328. }
  329. else if ( mMode == mAddRiverMode )
  330. {
  331. if ( nodeClicked )
  332. {
  333. // A double-click on a node in Normal mode means set AddNode mode.
  334. if ( clickedNodeIdx == 0 )
  335. {
  336. setSelectedRiver( clickedRiverPtr );
  337. setSelectedNode( clickedNodeIdx );
  338. mAddNodeIdx = clickedNodeIdx;
  339. mMode = mAddNodeMode;
  340. mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
  341. mIsDirty = true;
  342. return;
  343. }
  344. else if ( clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
  345. {
  346. setSelectedRiver( clickedRiverPtr );
  347. setSelectedNode( clickedNodeIdx );
  348. mAddNodeIdx = U32_MAX;
  349. mMode = mAddNodeMode;
  350. mSelNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);
  351. mIsDirty = true;
  352. setSelectedNode( mSelNode );
  353. return;
  354. }
  355. }
  356. if ( !isMethod( "createRiver" ) )
  357. {
  358. Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method does not exist." );
  359. return;
  360. }
  361. const char *res = Con::executef( this, "createRiver" );
  362. River *newRiver;
  363. if ( !Sim::findObject( res, newRiver ) )
  364. {
  365. Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method did not return a river object." );
  366. return;
  367. }
  368. // Add to MissionGroup
  369. SimGroup *missionGroup;
  370. if ( !Sim::findObject( "MissionGroup", missionGroup ) )
  371. Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" );
  372. else
  373. missionGroup->addObject( newRiver );
  374. Point3F pos( endPnt );
  375. pos.z += mDefaultDepth * 0.5f;
  376. newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 0 );
  377. U32 newNode = newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 1 );
  378. // Always add to the end of the road, the first node is the start.
  379. mAddNodeIdx = U32_MAX;
  380. setSelectedRiver( newRiver );
  381. setSelectedNode( newNode );
  382. mMode = mAddNodeMode;
  383. // Disable the hover node while in addNodeMode, we
  384. // don't want some random node enlarged.
  385. mHoverNode = -1;
  386. // Grab the mission editor undo manager.
  387. UndoManager *undoMan = NULL;
  388. if ( !Sim::findObject( "EUndoManager", undoMan ) )
  389. {
  390. Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
  391. return;
  392. }
  393. // Create the UndoAction.
  394. MECreateUndoAction *action = new MECreateUndoAction("Create MeshRoad");
  395. action->addObject( newRiver );
  396. // Submit it.
  397. undoMan->addAction( action );
  398. return;
  399. }
  400. else if ( mMode == mAddNodeMode )
  401. {
  402. // Oops the road got deleted, maybe from an undo action?
  403. // Back to NormalMode.
  404. if ( mSelRiver )
  405. {
  406. // A double-click on a node in Normal mode means set AddNode mode.
  407. if ( clickedNodeIdx == 0 )
  408. {
  409. submitUndo( "Add Node" );
  410. mAddNodeIdx = clickedNodeIdx;
  411. mMode = mAddNodeMode;
  412. mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
  413. mIsDirty = true;
  414. setSelectedNode( mSelNode );
  415. return;
  416. }
  417. else
  418. {
  419. if( clickedRiverPtr && clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
  420. {
  421. submitUndo( "Add Node" );
  422. mAddNodeIdx = U32_MAX;
  423. mMode = mAddNodeMode;
  424. U32 newNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);
  425. mIsDirty = true;
  426. setSelectedNode( newNode );
  427. return;
  428. }
  429. else
  430. {
  431. submitUndo( "Insert Node" );
  432. // A single-click on empty space while in
  433. // AddNode mode means insert / add a node.
  434. //submitUndo( "Add Node" );
  435. //F32 width = mSelRiver->getNodeWidth( mSelNode );
  436. U32 newNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx);
  437. mIsDirty = true;
  438. setSelectedNode( newNode );
  439. return;
  440. }
  441. }
  442. }
  443. }
  444. else if ( mMode == mInsertPointMode && mSelRiver != NULL )
  445. {
  446. if ( clickedRiverPtr == mSelRiver )
  447. {
  448. // NOTE: I guess we have to determine the if the clicked ray intersects a road but not a specific node...
  449. // in order to handle inserting nodes in the same way as for DecalRoad
  450. U32 prevNodeIdx = insertNodeIdx;
  451. U32 nextNodeIdx = ( prevNodeIdx + 1 > mSelRiver->mNodes.size() - 1 ) ? prevNodeIdx : prevNodeIdx + 1;
  452. const RiverNode &prevNode = mSelRiver->mNodes[prevNodeIdx];
  453. const RiverNode &nextNode = mSelRiver->mNodes[nextNodeIdx];
  454. F32 width = ( prevNode.width + nextNode.width ) * 0.5f;
  455. F32 depth = ( prevNode.depth + nextNode.depth ) * 0.5f;
  456. Point3F normal = ( prevNode.normal + nextNode.normal ) * 0.5f;
  457. normal.normalize();
  458. submitUndo( "Insert Node" );
  459. U32 newNode = mSelRiver->insertNode( collisionPnt, width, depth, normal, insertNodeIdx + 1 );
  460. mIsDirty = true;
  461. setSelectedNode( newNode );
  462. return;
  463. }
  464. }
  465. else if ( mMode == mRemovePointMode && mSelRiver != NULL )
  466. {
  467. if ( nodeClicked && clickedRiverPtr == mSelRiver )
  468. {
  469. setSelectedNode( clickedNodeIdx );
  470. deleteSelectedNode();
  471. return;
  472. }
  473. }
  474. else if ( mMode == mMovePointMode )
  475. {
  476. if ( nodeClicked && clickedRiverPtr == mSelRiver )
  477. {
  478. setSelectedNode( clickedNodeIdx );
  479. return;
  480. }
  481. }
  482. else if ( mMode == mScalePointMode )
  483. {
  484. if ( nodeClicked && clickedRiverPtr == mSelRiver )
  485. {
  486. setSelectedNode( clickedNodeIdx );
  487. return;
  488. }
  489. }
  490. else if ( mMode == mRotatePointMode )
  491. {
  492. if ( nodeClicked && clickedRiverPtr == mSelRiver )
  493. {
  494. setSelectedNode( clickedNodeIdx );
  495. return;
  496. }
  497. }
  498. }
  499. void GuiRiverEditorCtrl::on3DRightMouseDown(const Gui3DMouseEvent & event)
  500. {
  501. //mIsPanning = true;
  502. }
  503. void GuiRiverEditorCtrl::on3DRightMouseUp(const Gui3DMouseEvent & event)
  504. {
  505. //mIsPanning = false;
  506. }
  507. void GuiRiverEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
  508. {
  509. // Keep the Gizmo up to date.
  510. mGizmo->on3DMouseUp( event );
  511. mStartWidth = -1.0f;
  512. mStartHeight = -1.0f;
  513. mSavedDrag = false;
  514. mouseUnlock();
  515. }
  516. void GuiRiverEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
  517. {
  518. if ( mSelRiver != NULL && mMode == mAddNodeMode )
  519. {
  520. Point3F pos;
  521. if ( getStaticPos( event, pos ) )
  522. {
  523. pos.z += mSelRiver->getNodeDepth(mSelNode) * 0.5f;
  524. mSelRiver->setNodePosition( mSelNode, pos );
  525. mIsDirty = true;
  526. }
  527. return;
  528. }
  529. if ( mSelRiver != NULL && mSelNode != -1 )
  530. mGizmo->on3DMouseMove( event );
  531. // Is cursor hovering over a river?
  532. if ( mMode == mSelectRiverMode )
  533. {
  534. mHoverRiver = NULL;
  535. Point3F startPnt = event.pos;
  536. Point3F endPnt = event.pos + event.vec * 1000.0f;
  537. RayInfo ri;
  538. if ( gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri) )
  539. endPnt = ri.point;
  540. River *pRiver = NULL;
  541. for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
  542. {
  543. pRiver = static_cast<River*>( *iter );
  544. // Do not select or edit a River within a Prefab.
  545. if ( Prefab::getPrefabByChild(pRiver) )
  546. continue;
  547. if ( pRiver->collideRay( event.pos, event.vec ) )
  548. {
  549. mHoverRiver = pRiver;
  550. break;
  551. }
  552. }
  553. }
  554. // Is cursor hovering over a RiverNode?
  555. if ( mHoverRiver )
  556. {
  557. River *pRiver = mHoverRiver;
  558. S32 hoverNodeIdx = -1;
  559. F32 hoverNodeDist = mNodeSphereRadius;
  560. //for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
  561. //{
  562. // River *pRiver = static_cast<River*>( *iter );
  563. for ( U32 i = 0; i < pRiver->mNodes.size(); i++ )
  564. {
  565. const Point3F &nodePos = pRiver->mNodes[i].point;
  566. Point3F screenPos;
  567. project( nodePos, &screenPos );
  568. F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
  569. if ( dist < hoverNodeDist )
  570. {
  571. // we found a hit!
  572. hoverNodeDist = dist;
  573. hoverNodeIdx = i;
  574. }
  575. }
  576. //}
  577. mHoverNode = hoverNodeIdx;
  578. }
  579. }
  580. void GuiRiverEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
  581. {
  582. // Drags are only used to transform nodes
  583. if ( !mSelRiver || mSelNode == -1 ||
  584. ( mMode != mMovePointMode && mMode != mScalePointMode && mMode != mRotatePointMode ) )
  585. return;
  586. // If we haven't already saved,
  587. // save an undo action to get back to this state,
  588. // before we make any modifications to the selected node.
  589. if ( !mSavedDrag )
  590. {
  591. submitUndo( "Modify Node" );
  592. mSavedDrag = true;
  593. }
  594. // Let the gizmo handle the drag, eg, modify its transforms
  595. mGizmo->on3DMouseDragged( event );
  596. if ( mGizmo->isDirty() )
  597. {
  598. Point3F pos = mGizmo->getPosition();
  599. Point3F scale = mGizmo->getScale();
  600. const MatrixF &mat = mGizmo->getTransform();
  601. VectorF normal;
  602. mat.getColumn( 2, &normal );
  603. mSelRiver->setNode( pos, scale.x, scale.z, normal, mSelNode );
  604. mIsDirty = true;
  605. }
  606. Con::executef( this, "onNodeModified", Con::getIntArg(mSelNode) );
  607. /*
  608. // If we are just starting a new drag,
  609. // we need to save the starting screen position of the mouse,
  610. // and the starting position of the selected node.
  611. if ( mStartDragMousePoint == InvalidMousePoint )
  612. {
  613. mStartDragMousePoint = event.mousePoint;
  614. mStartDragNodePos = mSelRiver->getNodePosition( mSelNode );
  615. }
  616. MathUtils::Line clickLine;
  617. clickLine.p = event.pos;
  618. clickLine.d = event.vec;
  619. MathUtils::Line axisLine;
  620. axisLine.p = mStartDragNodePos;
  621. axisLine.d = mGizmo.selectionToAxisVector( mGizmoSelection );
  622. MathUtils::LineSegment segment;
  623. MathUtils::mShortestSegmentBetweenLines( clickLine, axisLine, segment );
  624. // Segment.p1 is the closest point on the axis line,
  625. // We want to put the selected gizmo handle at that point,
  626. // So calculate the offset from the handle to the centerPoint to
  627. // determine the gizmo's position.
  628. mSelRiver->setNodePosition( mSelNode, segment.p1 );
  629. */
  630. /*
  631. // Convert the delta (dragged mouse distance) from screen space
  632. // into world space.
  633. Point2I deltaScreen = event.mousePoint - mStartDragMousePoint;
  634. F32 worldDist = ( event.pos - mStartDragNodePos ).len();
  635. Point2F deltaWorld;
  636. deltaWorld.x = GFX->unprojectRadius( worldDist, deltaScreen.x );
  637. deltaWorld.y = GFX->unprojectRadius( worldDist, deltaScreen.y );
  638. // Now modify the selected node depending on the kind of operation we are doing.
  639. if ( mGizmoSelection == Gizmo::Axis_X )
  640. {
  641. Point3F newPos = mStartDragNodePos;
  642. newPos.x += deltaWorld.x;
  643. mSelRiver->setNodePosition( mSelNode, newPos );
  644. }
  645. else if ( mGizmoSelection == Gizmo::Axis_Y )
  646. {
  647. Point3F newPos = mStartDragNodePos;
  648. newPos.y += deltaWorld.x;
  649. mSelRiver->setNodePosition( mSelNode, newPos );
  650. }
  651. else if ( mGizmoSelection == Gizmo::Axis_Z )
  652. {
  653. Point3F newPos = mStartDragNodePos;
  654. newPos.z += deltaWorld.y;
  655. mSelRiver->setNodePosition( mSelNode, newPos );
  656. }
  657. */
  658. /*
  659. F32 height = mStartHeight + deltaWorldX;
  660. Con::printf( "height = %g", height );
  661. mSelRiver->setNodeHeight( mSelNode, height );
  662. Con::executef( this, "onNodeHeightModified", Con::getFloatArg(height) );
  663. if ( event.modifier & SI_PRIMARY_CTRL )
  664. {
  665. //Point3F tPos;
  666. //if ( !getStaticPos( event, tPos ) )
  667. // return;
  668. if ( mStartHeight == -1.0f )
  669. {
  670. mStartHeight = mSelRiver->mNodes[mSelNode].point.z;
  671. mStartX = event.mousePoint.x;
  672. mStartWorld = mSelRiver->mNodes[mSelNode].point;
  673. }
  674. S32 deltaScreenX = event.mousePoint.x - mStartX;
  675. F32 worldDist = ( event.pos - mStartWorld ).len();
  676. F32 deltaWorldX = GFX->unprojectRadius( worldDist, deltaScreenX );
  677. F32 height = mStartHeight + deltaWorldX;
  678. Con::printf( "height = %g", height );
  679. mSelRiver->setNodeHeight( mSelNode, height );
  680. Con::executef( this, "onNodeHeightModified", Con::getFloatArg(height) );
  681. }
  682. else if ( event.modifier & SI_SHIFT )
  683. {
  684. Point3F tPos;
  685. if ( !getStaticPos( event, tPos ) )
  686. return;
  687. if ( mStartWidth == -1.0f )
  688. {
  689. mStartWidth = mSelRiver->mNodes[mSelNode].width;
  690. mStartX = event.mousePoint.x;
  691. mStartWorld = tPos;
  692. }
  693. S32 deltaScreenX = event.mousePoint.x - mStartX;
  694. F32 worldDist = ( event.pos - mStartWorld ).len();
  695. F32 deltaWorldX = GFX->unprojectRadius( worldDist, deltaScreenX );
  696. F32 width = mStartWidth + deltaWorldX;
  697. mSelRiver->setNodeWidth( mSelNode, width );
  698. Con::executef( this, "onNodeWidthModified", Con::getFloatArg(width) );
  699. }
  700. else
  701. {
  702. Point3F tPos;
  703. if ( !getStaticPos( event, tPos ) )
  704. return;
  705. else if ( mGizmoSelection == Gizmo::Axis_Y )
  706. {
  707. Point3F newPos = mStartDragNodePos;
  708. newPos.y += deltaWorld.x;
  709. mSelRiver->setNodePosition( mSelNode, newPos );
  710. }
  711. mSelRiver->setNodePosition( mSelNode, tPos );
  712. }
  713. */
  714. }
  715. void GuiRiverEditorCtrl::on3DMouseEnter(const Gui3DMouseEvent & event)
  716. {
  717. // nothing to do
  718. }
  719. void GuiRiverEditorCtrl::on3DMouseLeave(const Gui3DMouseEvent & event)
  720. {
  721. // nothing to do
  722. }
  723. bool GuiRiverEditorCtrl::onKeyDown(const GuiEvent& event)
  724. {
  725. if( event.keyCode == KEY_RETURN && mMode == mAddNodeMode )
  726. {
  727. // Delete the node attached to the cursor.
  728. deleteSelectedNode();
  729. mMode = mAddRiverMode;
  730. return true;
  731. }
  732. return false;
  733. }
  734. void GuiRiverEditorCtrl::updateGuiInfo()
  735. {
  736. // nothing to do
  737. }
  738. void GuiRiverEditorCtrl::onRender( Point2I offset, const RectI &updateRect )
  739. {
  740. PROFILE_SCOPE( GuiRiverEditorCtrl_OnRender );
  741. Parent::onRender( offset, updateRect );
  742. return;
  743. }
  744. void GuiRiverEditorCtrl::renderScene(const RectI & updateRect)
  745. {
  746. //GFXDrawUtil *drawer = GFX->getDrawUtil();
  747. GFX->setStateBlock( mZDisableSB );
  748. // get the projected size...
  749. GameConnection* connection = GameConnection::getConnectionToServer();
  750. if(!connection)
  751. return;
  752. // Grab the camera's transform
  753. MatrixF mat;
  754. connection->getControlCameraTransform(0, &mat);
  755. // Get the camera position
  756. Point3F camPos;
  757. mat.getColumn(3,&camPos);
  758. if ( mHoverRiver && mHoverRiver != mSelRiver )
  759. {
  760. _drawRiverSpline( mHoverRiver, mHoverSplineColor );
  761. }
  762. if ( mSelRiver )
  763. {
  764. _drawRiverSpline( mSelRiver, mSelectedSplineColor );
  765. // Render Gizmo for selected node if were in either of the three transform modes
  766. if ( mSelNode != -1 && ( mMode == mMovePointMode || mMode == mScalePointMode || mMode == mRotatePointMode ) )
  767. {
  768. if( mMode == mMovePointMode )
  769. {
  770. mGizmo->getProfile()->mode = MoveMode;
  771. }
  772. else if( mMode == mScalePointMode )
  773. {
  774. mGizmo->getProfile()->mode = ScaleMode;
  775. }
  776. else if( mMode == mRotatePointMode )
  777. {
  778. mGizmo->getProfile()->mode = RotateMode;
  779. }
  780. const RiverNode &node = mSelRiver->mNodes[mSelNode];
  781. MatrixF objMat = mSelRiver->getNodeTransform(mSelNode);
  782. Point3F objScale( node.width, 1.0f, node.depth );
  783. Point3F worldPos = node.point;
  784. mGizmo->set( objMat, worldPos, objScale );
  785. mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix, mLastCameraQuery.fov );
  786. // Render Gizmo text
  787. //mGizmo->renderText( mSaveViewport, mSaveModelview, mSaveProjection );
  788. }
  789. }
  790. // Now draw all the 2d stuff!
  791. GFX->setClipRect(updateRect);
  792. // Draw Control nodes for selecting and highlighted rivers
  793. if ( mHoverRiver )
  794. _drawRiverControlNodes( mHoverRiver, mHoverSplineColor );
  795. if ( mSelRiver )
  796. _drawRiverControlNodes( mSelRiver, mSelectedSplineColor );
  797. }
  798. void GuiRiverEditorCtrl::_drawRiverSpline( River *river, const ColorI &color )
  799. {
  800. if ( river->mSlices.size() <= 1 )
  801. return;
  802. if ( River::smShowSpline )
  803. {
  804. // Render the River center-line
  805. PrimBuild::color( color );
  806. PrimBuild::begin( GFXLineStrip, river->mSlices.size() );
  807. for ( U32 i = 0; i < river->mSlices.size(); i++ )
  808. {
  809. PrimBuild::vertex3fv( river->mSlices[i].p1 );
  810. }
  811. PrimBuild::end();
  812. }
  813. if ( River::smWireframe )
  814. {
  815. // Left-side line
  816. PrimBuild::color3i( 100, 100, 100 );
  817. PrimBuild::begin( GFXLineStrip, river->mSlices.size() );
  818. for ( U32 i = 0; i < river->mSlices.size(); i++ )
  819. {
  820. PrimBuild::vertex3fv( river->mSlices[i].p0 );
  821. }
  822. PrimBuild::end();
  823. // Right-side line
  824. PrimBuild::begin( GFXLineStrip, river->mSlices.size() );
  825. for ( U32 i = 0; i < river->mSlices.size(); i++ )
  826. {
  827. PrimBuild::vertex3fv( river->mSlices[i].p2 );
  828. }
  829. PrimBuild::end();
  830. // Cross-sections
  831. PrimBuild::begin( GFXLineList, river->mSlices.size() * 2 );
  832. for ( U32 i = 0; i < river->mSlices.size(); i++ )
  833. {
  834. PrimBuild::vertex3fv( river->mSlices[i].p0 );
  835. PrimBuild::vertex3fv( river->mSlices[i].p2 );
  836. }
  837. PrimBuild::end();
  838. }
  839. // Segment
  840. }
  841. void GuiRiverEditorCtrl::_drawRiverControlNodes( River *river, const ColorI &color )
  842. {
  843. if ( !River::smShowSpline )
  844. return;
  845. RectI bounds = getBounds();
  846. GFXDrawUtil *drawer = GFX->getDrawUtil();
  847. bool isSelected = ( river == mSelRiver );
  848. bool isHighlighted = ( river == mHoverRiver );
  849. for ( U32 i = 0; i < river->mNodes.size(); i++ )
  850. {
  851. if ( false && isSelected && mSelNode == i )
  852. continue;
  853. const Point3F &wpos = river->mNodes[i].point;
  854. Point3F spos;
  855. project( wpos, &spos );
  856. if ( spos.z > 1.0f )
  857. continue;
  858. Point2I posi;
  859. posi.x = spos.x;
  860. posi.y = spos.y;
  861. if ( !bounds.pointInRect( posi ) )
  862. continue;
  863. ColorI theColor = color;
  864. Point2I nodeHalfSize = mNodeHalfSize;
  865. if ( isHighlighted && mHoverNode == i )
  866. {
  867. //theColor = mHoverNodeColor;
  868. nodeHalfSize += Point2I(2,2);
  869. }
  870. if ( isSelected )
  871. {
  872. if ( mSelNode == i )
  873. {
  874. theColor.set(0,0,255);
  875. }
  876. else if ( i == 0 )
  877. {
  878. theColor.set(0,255,0);
  879. }
  880. else if ( i == river->mNodes.size() - 1 )
  881. {
  882. theColor.set(255,0,0);
  883. }
  884. }
  885. drawer->drawRectFill( posi - nodeHalfSize, posi + nodeHalfSize, theColor );
  886. }
  887. }
  888. bool GuiRiverEditorCtrl::getStaticPos( const Gui3DMouseEvent & event, Point3F &tpos )
  889. {
  890. // Find clicked point on the terrain
  891. Point3F startPnt = event.pos;
  892. Point3F endPnt = event.pos + event.vec * 1000.0f;
  893. RayInfo ri;
  894. bool hit;
  895. hit = gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri);
  896. tpos = ri.point;
  897. return hit;
  898. }
  899. void GuiRiverEditorCtrl::deleteSelectedNode()
  900. {
  901. if ( !mSelRiver || mSelNode == -1 )
  902. return;
  903. // If the River has only two nodes remaining,
  904. // delete the whole River.
  905. if ( mSelRiver->mNodes.size() <= 2 )
  906. {
  907. deleteSelectedRiver( mMode != mAddNodeMode );
  908. }
  909. else
  910. {
  911. if ( mMode != mAddNodeMode )
  912. submitUndo( "Delete Node" );
  913. // Delete the SelectedNode of the SelectedRiver
  914. mSelRiver->deleteNode(mSelNode);
  915. mIsDirty = true;
  916. // We deleted the Node but not the River (it has nodes left)
  917. // so decrement the currently selected node.
  918. if ( mSelRiver->mNodes.size() <= mSelNode )
  919. setSelectedNode( mSelNode - 1 );
  920. else
  921. {
  922. // force gizmo to update to the selected nodes position
  923. // the index didn't change but the node it refers to did.
  924. U32 i = mSelNode;
  925. mSelNode = -1;
  926. setSelectedNode( i );
  927. }
  928. }
  929. // If you were in addNodeMode,
  930. // deleting a node should ends it.
  931. //mMode = smNormalMode;
  932. }
  933. void GuiRiverEditorCtrl::deleteSelectedRiver( bool undoAble )
  934. {
  935. AssertFatal( mSelRiver != NULL, "GuiRiverEditorCtrl::deleteSelectedRiver() - No River IS selected" );
  936. // Not undoAble? Just delete it.
  937. if ( !undoAble )
  938. {
  939. mSelRiver->deleteObject();
  940. mIsDirty = true;
  941. Con::executef( this, "onRiverSelected" );
  942. mSelNode = -1;
  943. return;
  944. }
  945. // Grab the mission editor undo manager.
  946. UndoManager *undoMan = NULL;
  947. if ( !Sim::findObject( "EUndoManager", undoMan ) )
  948. {
  949. // Couldn't find it? Well just delete the River.
  950. Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
  951. return;
  952. }
  953. else
  954. {
  955. // Create the UndoAction.
  956. MEDeleteUndoAction *action = new MEDeleteUndoAction("Deleted River");
  957. action->deleteObject( mSelRiver );
  958. mIsDirty = true;
  959. // Submit it.
  960. undoMan->addAction( action );
  961. }
  962. // ScriptCallback with 'NULL' parameter for no River currently selected.
  963. Con::executef( this, "onRiverSelected" );
  964. // Clear the SelectedNode (it has been deleted along with the River).
  965. setSelectedNode( -1 );
  966. mSelNode = -1;
  967. // SelectedRiver is a SimObjectPtr and will be NULL automatically.
  968. }
  969. void GuiRiverEditorCtrl::setMode( String mode, bool sourceShortcut = false )
  970. {
  971. mMode = mode;
  972. if( sourceShortcut )
  973. Con::executef( this, "paletteSync", mode );
  974. }
  975. void GuiRiverEditorCtrl::setSelectedRiver( River *river )
  976. {
  977. mSelRiver = river;
  978. if ( mSelRiver != NULL )
  979. Con::executef( this, "onRiverSelected", river->getIdString() );
  980. else
  981. Con::executef( this, "onRiverSelected" );
  982. if ( mSelRiver != river )
  983. setSelectedNode(-1);
  984. }
  985. void GuiRiverEditorCtrl::setNodeWidth( F32 width )
  986. {
  987. if ( mSelRiver && mSelNode != -1 )
  988. {
  989. mSelRiver->setNodeWidth( mSelNode, width );
  990. mIsDirty = true;
  991. }
  992. }
  993. F32 GuiRiverEditorCtrl::getNodeWidth()
  994. {
  995. if ( mSelRiver && mSelNode != -1 )
  996. return mSelRiver->getNodeWidth( mSelNode );
  997. return 0.0f;
  998. }
  999. void GuiRiverEditorCtrl::setNodeDepth(F32 depth)
  1000. {
  1001. if ( mSelRiver && mSelNode != -1 )
  1002. {
  1003. mSelRiver->setNodeDepth( mSelNode, depth );
  1004. mIsDirty = true;
  1005. }
  1006. }
  1007. F32 GuiRiverEditorCtrl::getNodeDepth()
  1008. {
  1009. if ( mSelRiver && mSelNode != -1 )
  1010. return mSelRiver->getNodeDepth( mSelNode );
  1011. return 0.0f;
  1012. }
  1013. void GuiRiverEditorCtrl::setNodePosition( Point3F pos )
  1014. {
  1015. if ( mSelRiver && mSelNode != -1 )
  1016. {
  1017. mSelRiver->setNodePosition( mSelNode, pos );
  1018. mIsDirty = true;
  1019. }
  1020. }
  1021. Point3F GuiRiverEditorCtrl::getNodePosition()
  1022. {
  1023. if ( mSelRiver && mSelNode != -1 )
  1024. return mSelRiver->getNodePosition( mSelNode );
  1025. return Point3F( 0, 0, 0 );
  1026. }
  1027. void GuiRiverEditorCtrl::setNodeNormal( const VectorF &normal )
  1028. {
  1029. if ( mSelRiver && mSelNode != -1 )
  1030. {
  1031. mSelRiver->setNodeNormal( mSelNode, normal );
  1032. mIsDirty = true;
  1033. }
  1034. }
  1035. VectorF GuiRiverEditorCtrl::getNodeNormal()
  1036. {
  1037. if ( mSelRiver && mSelNode != -1 )
  1038. return mSelRiver->getNodeNormal( mSelNode );
  1039. return VectorF::Zero;
  1040. }
  1041. void GuiRiverEditorCtrl::setSelectedNode( S32 node )
  1042. {
  1043. //if ( mSelNode == node )
  1044. // return;
  1045. mSelNode = node;
  1046. if ( mSelNode != -1 )
  1047. {
  1048. const RiverNode &node = mSelRiver->mNodes[mSelNode];
  1049. MatrixF objMat = mSelRiver->getNodeTransform(mSelNode);
  1050. Point3F objScale( node.width, 1.0f, node.depth );
  1051. Point3F worldPos = node.point;
  1052. mGizmo->set( objMat, worldPos, objScale );
  1053. }
  1054. if ( mSelNode != -1 )
  1055. Con::executef( this, "onNodeSelected", Con::getIntArg(mSelNode) );
  1056. else
  1057. Con::executef( this, "onNodeSelected", Con::getIntArg(-1) );
  1058. }
  1059. void GuiRiverEditorCtrl::submitUndo( const UTF8 *name )
  1060. {
  1061. // Grab the mission editor undo manager.
  1062. UndoManager *undoMan = NULL;
  1063. if ( !Sim::findObject( "EUndoManager", undoMan ) )
  1064. {
  1065. Con::errorf( "GuiRiverEditorCtrl::submitUndo() - EUndoManager not found!" );
  1066. return;
  1067. }
  1068. // Setup the action.
  1069. GuiRiverEditorUndoAction *action = new GuiRiverEditorUndoAction( name );
  1070. action->mObjId = mSelRiver->getId();
  1071. action->mMetersPerSegment = mSelRiver->mMetersPerSegment;
  1072. action->mSegmentsPerBatch = mSelRiver->mSegmentsPerBatch;
  1073. action->mRiverEditor = this;
  1074. for( U32 i = 0; i < mSelRiver->mNodes.size(); i++ )
  1075. {
  1076. action->mNodes.push_back( mSelRiver->mNodes[i] );
  1077. }
  1078. undoMan->addAction( action );
  1079. }
  1080. void GuiRiverEditorCtrl::_prepRenderImage( SceneManager* sceneGraph, const SceneRenderState* state )
  1081. {
  1082. if ( isAwake() && River::smEditorOpen && mSelRiver )
  1083. {
  1084. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  1085. ri->type = RenderPassManager::RIT_Editor;
  1086. ri->renderDelegate.bind( this, &GuiRiverEditorCtrl::_renderSelectedRiver );
  1087. ri->defaultKey = 100;
  1088. state->getRenderPass()->addInst( ri );
  1089. }
  1090. }
  1091. void GuiRiverEditorCtrl::_renderSelectedRiver( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *matInst )
  1092. {
  1093. if ( !mSelRiver || !River::smEditorOpen)
  1094. return;
  1095. GFXTransformSaver saver;
  1096. GFX->setStateBlock( mZEnableSB );
  1097. if ( River::smShowWalls && mSelRiver->mSlices.size() > 1 )
  1098. {
  1099. Point3F offset(0,0,1);
  1100. // Render the River volume
  1101. PrimBuild::begin( GFXTriangleList, 18 * mSelRiver->mSlices.size() - 1 );
  1102. for ( U32 i = 0; i < mSelRiver->mSlices.size() - 1; i++ )
  1103. {
  1104. const RiverSlice &slice = mSelRiver->mSlices[i];
  1105. const RiverSlice &nextSlice = mSelRiver->mSlices[i+1];
  1106. // Top face
  1107. //drawer->drawQuad( slice.p0, nextSlice.p0, nextSlice.p2, slice.p2, colorRed, true );
  1108. //PrimBuild::color3i( 0, 0, 255 );
  1109. //PrimBuild::vertex3fv( slice.p0 );
  1110. //PrimBuild::vertex3fv( nextSlice.p0 );
  1111. //PrimBuild::vertex3fv( nextSlice.p2 );
  1112. //PrimBuild::vertex3fv( slice.p0 );
  1113. //PrimBuild::vertex3fv( nextSlice.p2 );
  1114. //PrimBuild::vertex3fv( slice.p2 );
  1115. // Bottom face
  1116. PrimBuild::color3i( 0, 255, 0 );
  1117. PrimBuild::vertex3fv( slice.pb0 );
  1118. PrimBuild::vertex3fv( nextSlice.pb0 );
  1119. PrimBuild::vertex3fv( nextSlice.pb2 );
  1120. PrimBuild::vertex3fv( slice.pb0 );
  1121. PrimBuild::vertex3fv( nextSlice.pb2 );
  1122. PrimBuild::vertex3fv( slice.pb2 );
  1123. // Left face
  1124. PrimBuild::color3i( 255, 0, 0 );
  1125. PrimBuild::vertex3fv( slice.pb0 );
  1126. PrimBuild::vertex3fv( nextSlice.pb0 );
  1127. PrimBuild::vertex3fv( nextSlice.p0 );
  1128. PrimBuild::vertex3fv( slice.pb0 );
  1129. PrimBuild::vertex3fv( nextSlice.p0 );
  1130. PrimBuild::vertex3fv( slice.p0 );
  1131. // Right face
  1132. PrimBuild::color3i( 255, 0, 0 );
  1133. PrimBuild::vertex3fv( slice.p2 );
  1134. PrimBuild::vertex3fv( nextSlice.p2 );
  1135. PrimBuild::vertex3fv( nextSlice.pb2 );
  1136. PrimBuild::vertex3fv( slice.p2 );
  1137. PrimBuild::vertex3fv( nextSlice.pb2 );
  1138. PrimBuild::vertex3fv( slice.pb2 );
  1139. }
  1140. PrimBuild::end();
  1141. }
  1142. }
  1143. ConsoleMethod( GuiRiverEditorCtrl, deleteNode, void, 2, 2, "deleteNode()" )
  1144. {
  1145. object->deleteSelectedNode();
  1146. }
  1147. ConsoleMethod( GuiRiverEditorCtrl, getMode, const char*, 2, 2, "" )
  1148. {
  1149. return object->getMode();
  1150. }
  1151. ConsoleMethod( GuiRiverEditorCtrl, setMode, void, 3, 3, "setMode( String mode )" )
  1152. {
  1153. String newMode = ( argv[2] );
  1154. object->setMode( newMode );
  1155. }
  1156. ConsoleMethod( GuiRiverEditorCtrl, getNodeWidth, F32, 2, 2, "" )
  1157. {
  1158. return object->getNodeWidth();
  1159. }
  1160. ConsoleMethod( GuiRiverEditorCtrl, setNodeWidth, void, 3, 3, "" )
  1161. {
  1162. object->setNodeWidth( dAtof(argv[2]) );
  1163. }
  1164. ConsoleMethod( GuiRiverEditorCtrl, getNodeDepth, F32, 2, 2, "" )
  1165. {
  1166. return object->getNodeDepth();
  1167. }
  1168. ConsoleMethod( GuiRiverEditorCtrl, setNodeDepth, void, 3, 3, "" )
  1169. {
  1170. object->setNodeDepth( dAtof(argv[2]) );
  1171. }
  1172. ConsoleMethod( GuiRiverEditorCtrl, getNodePosition, const char*, 2, 2, "" )
  1173. {
  1174. char* returnBuffer = Con::getReturnBuffer(256);
  1175. dSprintf(returnBuffer, 256, "%f %f %f",
  1176. object->getNodePosition().x, object->getNodePosition().y, object->getNodePosition().z);
  1177. return returnBuffer;
  1178. }
  1179. ConsoleMethod( GuiRiverEditorCtrl, setNodePosition, void, 3, 3, "" )
  1180. {
  1181. Point3F pos;
  1182. S32 count = dSscanf( argv[2], "%f %f %f",
  1183. &pos.x, &pos.y, &pos.z);
  1184. if ( (count != 3) )
  1185. {
  1186. Con::printf("Failed to parse node information \"px py pz\" from '%s'", argv[3]);
  1187. return;
  1188. }
  1189. object->setNodePosition( pos );
  1190. }
  1191. ConsoleMethod( GuiRiverEditorCtrl, getNodeNormal, const char*, 2, 2, "" )
  1192. {
  1193. char* returnBuffer = Con::getReturnBuffer(256);
  1194. dSprintf(returnBuffer, 256, "%f %f %f",
  1195. object->getNodeNormal().x, object->getNodeNormal().y, object->getNodeNormal().z);
  1196. return returnBuffer;
  1197. }
  1198. ConsoleMethod( GuiRiverEditorCtrl, setNodeNormal, void, 3, 3, "" )
  1199. {
  1200. VectorF normal;
  1201. S32 count = dSscanf( argv[2], "%f %f %f",
  1202. &normal.x, &normal.y, &normal.z);
  1203. if ( (count != 3) )
  1204. {
  1205. Con::printf("Failed to parse node information \"px py pz\" from '%s'", argv[3]);
  1206. return;
  1207. }
  1208. object->setNodeNormal( normal );
  1209. }
  1210. ConsoleMethod( GuiRiverEditorCtrl, setSelectedRiver, void, 2, 3, "" )
  1211. {
  1212. if ( argc == 2 )
  1213. object->setSelectedRiver(NULL);
  1214. else
  1215. {
  1216. River *river = NULL;
  1217. if ( Sim::findObject( argv[2], river ) )
  1218. object->setSelectedRiver(river);
  1219. }
  1220. }
  1221. ConsoleMethod( GuiRiverEditorCtrl, getSelectedRiver, const char*, 2, 2, "" )
  1222. {
  1223. River *river = object->getSelectedRiver();
  1224. if ( !river )
  1225. return NULL;
  1226. return river->getIdString();
  1227. }
  1228. ConsoleMethod( GuiRiverEditorCtrl, regenerate, void, 2, 2, "" )
  1229. {
  1230. River *river = object->getSelectedRiver();
  1231. if ( river )
  1232. river->regenerate();
  1233. }