2
0

guiRiverEditorCtrl.cpp 41 KB

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