guiRiverEditorCtrl.cpp 41 KB

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