guiRiverEditorCtrl.cpp 41 KB

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