WaypathNode.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/Tools/LevelEdit/WaypathNode.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 7/03/01 2:35p $*
  29. * *
  30. * $Revision:: 17 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "waypathnode.h"
  37. #include "sceneeditor.h"
  38. #include "collisiongroups.h"
  39. #include "persistfactory.h"
  40. #include "editorchunkids.h"
  41. #include "preset.h"
  42. #include "chunkio.h"
  43. #include "nodemgr.h"
  44. #include "segline.h"
  45. #include "waypointnode.h"
  46. #include "waypath.h"
  47. #include "waypoint.h"
  48. #include "pathfind.h"
  49. #include "nodeinfopage.h"
  50. #include "positionpage.h"
  51. #include "editorpropsheet.h"
  52. #include "pathfindportal.h"
  53. //////////////////////////////////////////////////////////////////////////////
  54. // Persist factory
  55. //////////////////////////////////////////////////////////////////////////////
  56. SimplePersistFactoryClass<WaypathNodeClass, CHUNKID_NODE_WAYPATH> _WaypathNodePersistFactory;
  57. enum
  58. {
  59. CHUNKID_VARIABLES = 0x02291130,
  60. CHUNKID_BASE_CLASS,
  61. CHUNKID_WAYPOINTS
  62. };
  63. enum
  64. {
  65. VARID_WAYPOINT_PTR = 0x01,
  66. VARID_OLD_PTR = 0x02,
  67. VARID_FLAGS = 0x03,
  68. };
  69. //////////////////////////////////////////////////////////////////////////////
  70. //
  71. // WaypathNodeClass
  72. //
  73. //////////////////////////////////////////////////////////////////////////////
  74. WaypathNodeClass::WaypathNodeClass (PresetClass *preset)
  75. : m_PhysObj (NULL),
  76. m_Flags (FLAG_HUMAN | FLAG_GROUND_VEHICLE),
  77. m_RuntimeWaypath (NULL),
  78. m_HasLoadCompleted (true),
  79. NodeClass (preset)
  80. {
  81. return ;
  82. }
  83. //////////////////////////////////////////////////////////////////////////////
  84. //
  85. // WaypathNodeClass
  86. //
  87. //////////////////////////////////////////////////////////////////////////////
  88. WaypathNodeClass::WaypathNodeClass (const WaypathNodeClass &src)
  89. : m_PhysObj (NULL),
  90. m_Flags (FLAG_HUMAN | FLAG_GROUND_VEHICLE),
  91. m_RuntimeWaypath (NULL),
  92. m_HasLoadCompleted (true),
  93. NodeClass (NULL)
  94. {
  95. *this = src;
  96. return ;
  97. }
  98. //////////////////////////////////////////////////////////////////////////////
  99. //
  100. // ~WaypathNodeClass
  101. //
  102. //////////////////////////////////////////////////////////////////////////////
  103. WaypathNodeClass::~WaypathNodeClass (void)
  104. {
  105. Remove_From_Scene ();
  106. MEMBER_RELEASE (m_PhysObj);
  107. Free_Waypoints ();
  108. return ;
  109. }
  110. //////////////////////////////////////////////////////////////////////////////
  111. //
  112. // Initialize
  113. //
  114. // Note: This may be called more than once. It is used as an 'initialize'
  115. // and a 're-initialize'.
  116. //
  117. //////////////////////////////////////////////////////////////////////////////
  118. void
  119. WaypathNodeClass::Initialize (void)
  120. {
  121. MEMBER_RELEASE (m_PhysObj);
  122. SegmentedLineClass *line = new SegmentedLineClass;
  123. line->Set_Width (0.075F);
  124. line->Set_Color (Vector3 (0, 0.75F, 0));
  125. line->Set_Opacity (1.0F);
  126. //line->Set_Shader (ShaderClass::_PresetOpaqueSolidShader);
  127. // Create the new physics object
  128. m_PhysObj = new DecorationPhysClass;
  129. //
  130. // Configure the physics object with information about
  131. // its new render object and collision data.
  132. //
  133. m_PhysObj->Set_Model (line);
  134. m_PhysObj->Set_Transform (Matrix3D(1));
  135. m_PhysObj->Set_Collision_Group (EDITOR_COLLISION_GROUP);
  136. m_PhysObj->Peek_Model ()->Set_Collision_Type (COLLISION_TYPE_6);
  137. m_PhysObj->Peek_Model ()->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE);
  138. m_PhysObj->Set_Transform (m_Transform);
  139. // Release our hold on the render object pointer
  140. MEMBER_RELEASE (line);
  141. //
  142. // Make sure the path has at least one waypoint
  143. //
  144. if (m_PointList.Count () == 0) {
  145. Add_Point (m_Transform.Get_Translation ());
  146. }
  147. if (m_HasLoadCompleted) {
  148. Update_Line ();
  149. }
  150. return ;
  151. }
  152. ////////////////////////////////////////////////////////////////
  153. //
  154. // Get_Factory
  155. //
  156. ////////////////////////////////////////////////////////////////
  157. const PersistFactoryClass &
  158. WaypathNodeClass::Get_Factory (void) const
  159. {
  160. return _WaypathNodePersistFactory;
  161. }
  162. /////////////////////////////////////////////////////////////////
  163. //
  164. // Save
  165. //
  166. /////////////////////////////////////////////////////////////////
  167. bool
  168. WaypathNodeClass::Save (ChunkSaveClass &csave)
  169. {
  170. csave.Begin_Chunk (CHUNKID_BASE_CLASS);
  171. NodeClass::Save (csave);
  172. csave.End_Chunk ();
  173. csave.Begin_Chunk (CHUNKID_VARIABLES);
  174. WaypathNodeClass *this_ptr = this;
  175. WRITE_MICRO_CHUNK (csave, VARID_OLD_PTR, this_ptr);
  176. WRITE_MICRO_CHUNK (csave, VARID_FLAGS, m_Flags);
  177. csave.End_Chunk ();
  178. //
  179. // Save the waypoints in their own chunk
  180. //
  181. csave.Begin_Chunk (CHUNKID_WAYPOINTS);
  182. NODE_LIST node_list;
  183. for (int index = 0; index < m_PointList.Count (); index ++) {
  184. node_list.Add (m_PointList[index]);
  185. }
  186. NodeMgrClass::Save_Node_List (csave, node_list);
  187. csave.End_Chunk ();
  188. return true;
  189. }
  190. /////////////////////////////////////////////////////////////////
  191. //
  192. // Load
  193. //
  194. /////////////////////////////////////////////////////////////////
  195. bool
  196. WaypathNodeClass::Load (ChunkLoadClass &cload)
  197. {
  198. m_OldStylePointList.Delete_All ();
  199. Free_Waypoints ();
  200. m_HasLoadCompleted = false;
  201. while (cload.Open_Chunk ()) {
  202. switch (cload.Cur_Chunk_ID ()) {
  203. case CHUNKID_BASE_CLASS:
  204. NodeClass::Load (cload);
  205. break;
  206. case CHUNKID_VARIABLES:
  207. Load_Variables (cload);
  208. break;
  209. case CHUNKID_WAYPOINTS:
  210. {
  211. //
  212. // Load the list of nodes
  213. //
  214. NODE_LIST node_list;
  215. NodeMgrClass::Load_Node_List (cload, node_list);
  216. //
  217. // Store each node (as a waypoint) in our list
  218. //
  219. for (int index = 0; index < node_list.Count (); index ++) {
  220. WaypointNodeClass *node = node_list[index]->As_WaypointNodeClass ();
  221. if (node != NULL) {
  222. m_PointList.Add (node);
  223. }
  224. }
  225. }
  226. break;
  227. }
  228. cload.Close_Chunk ();
  229. }
  230. SaveLoadSystemClass::Register_Post_Load_Callback (this);
  231. return true;
  232. }
  233. ///////////////////////////////////////////////////////////////////////
  234. //
  235. // Load_Variables
  236. //
  237. ///////////////////////////////////////////////////////////////////////
  238. bool
  239. WaypathNodeClass::Load_Variables (ChunkLoadClass &cload)
  240. {
  241. //
  242. // Loop through all the microchunks that define the variables
  243. //
  244. while (cload.Open_Micro_Chunk ()) {
  245. switch (cload.Cur_Micro_Chunk_ID ()) {
  246. READ_MICRO_CHUNK (cload, VARID_FLAGS, m_Flags);
  247. case VARID_WAYPOINT_PTR:
  248. {
  249. //
  250. // Read the old waypoint ptr from the chunk and add it to our
  251. // list. We will remap it later.
  252. //
  253. WaypointNodeClass *waypoint = NULL;
  254. cload.Read (&waypoint, sizeof (waypoint));
  255. m_OldStylePointList.Add (waypoint);
  256. }
  257. break;
  258. case VARID_OLD_PTR:
  259. {
  260. //
  261. // Read the old pointer from the chunk and submit it
  262. // to the remapping system.
  263. //
  264. WaypathNodeClass *old_ptr = NULL;
  265. cload.Read (&old_ptr, sizeof (old_ptr));
  266. SaveLoadSystemClass::Register_Pointer (old_ptr, this);
  267. }
  268. break;
  269. }
  270. cload.Close_Micro_Chunk ();
  271. }
  272. //
  273. // Register each of the pointers in our waypoint list for remapping
  274. //
  275. for (int index = 0; index < m_OldStylePointList.Count (); index ++) {
  276. REQUEST_POINTER_REMAP ((void **)&m_OldStylePointList[index]);
  277. }
  278. return true;
  279. }
  280. ///////////////////////////////////////////////////////////////////////
  281. //
  282. // On_Post_Load
  283. //
  284. ///////////////////////////////////////////////////////////////////////
  285. void
  286. WaypathNodeClass::On_Post_Load (void)
  287. {
  288. //
  289. // Do we need to import any waypoints from an old-style save?
  290. //
  291. if (m_OldStylePointList.Count () > 0) {
  292. Free_Waypoints ();
  293. //
  294. // Add a ref-count to each of the waypoints and remove it from the node manager
  295. //
  296. DynamicVectorClass<WaypointNodeClass *> new_point_list;
  297. for (int index = 0; index < m_OldStylePointList.Count (); index ++) {
  298. WaypointNodeClass *waypoint = m_OldStylePointList[index];
  299. if (waypoint != NULL) {
  300. new_point_list.Add (waypoint);
  301. SAFE_ADD_REF (waypoint);
  302. //
  303. // Remove the node from the manager (we'll manage the waypoints)
  304. //
  305. NodeMgrClass::Remove_Node (waypoint);
  306. }
  307. }
  308. m_PointList = new_point_list;
  309. m_OldStylePointList.Delete_All ();
  310. }
  311. //
  312. // Add a reference count to each of the points
  313. //
  314. /*for (int index = 0; index < m_PointList.Count (); index ++) {
  315. WaypointNodeClass *waypoint = m_PointList[index];
  316. SAFE_ADD_REF (waypoint);
  317. }*/
  318. //
  319. // Make sure the line is refreshed
  320. //
  321. Update_Line ();
  322. m_HasLoadCompleted = true;
  323. return ;
  324. }
  325. ///////////////////////////////////////////////////////////////////////
  326. //
  327. // Set_Transform
  328. //
  329. ///////////////////////////////////////////////////////////////////////
  330. void
  331. WaypathNodeClass::Set_Transform (const Matrix3D &tm)
  332. {
  333. SegmentedLineClass *line = Peek_Line ();
  334. if (line != NULL) {
  335. //
  336. // Transform all the points in the path
  337. //
  338. int index = m_PointList.Count ();
  339. while (index --) {
  340. //
  341. // Get this point's object space location
  342. //
  343. Vector3 point_loc (0, 0, 0);
  344. line->Get_Point_Location (index, point_loc);
  345. //
  346. // Reposition the point relative to the new path transform
  347. //
  348. Vector3 new_pos = tm * point_loc;
  349. m_PointList[index]->Parent_Set_Position ((new_pos - Vector3 (0, 0, 0.2F)));
  350. }
  351. }
  352. NodeClass::Set_Transform (tm);
  353. return ;
  354. }
  355. /////////////////////////////////////////////////////////////////
  356. //
  357. // operator=
  358. //
  359. /////////////////////////////////////////////////////////////////
  360. const WaypathNodeClass &
  361. WaypathNodeClass::operator= (const WaypathNodeClass &src)
  362. {
  363. //
  364. // Allow the base class to process
  365. //
  366. NodeClass::operator= (src);
  367. Free_Waypoints ();
  368. //
  369. // Copy the src waypath's list of waypoints...
  370. //
  371. int count = src.m_PointList.Count ();
  372. for (int index = 0; index < count; index ++) {
  373. WaypointNodeClass *waypoint = src.m_PointList[index];
  374. WaypointNodeClass *new_waypoint = (WaypointNodeClass *)waypoint->Clone ();
  375. new_waypoint->Set_Waypath (this);
  376. m_PointList.Add (new_waypoint);
  377. //NodeMgrClass::Add_Node (new_waypoint);
  378. }
  379. //
  380. // Copy the flags
  381. //
  382. m_Flags = src.m_Flags;
  383. //
  384. // Refresh the line
  385. //
  386. Update_Line ();
  387. return *this;
  388. }
  389. //////////////////////////////////////////////////////////////////////
  390. //
  391. // Pre_Export
  392. //
  393. //////////////////////////////////////////////////////////////////////
  394. void
  395. WaypathNodeClass::Pre_Export (void)
  396. {
  397. //
  398. // Remove ourselves from the 'system' so we don't get accidentally
  399. // saved during the export.
  400. //
  401. Add_Ref ();
  402. if (m_PhysObj != NULL && m_IsInScene) {
  403. ::Get_Scene_Editor ()->Remove_Object (m_PhysObj);
  404. }
  405. //
  406. // Create a runtime waypath object and register it with
  407. // the system so it gets exported with the game.
  408. //
  409. m_RuntimeWaypath = new WaypathClass;
  410. m_RuntimeWaypath->Set_ID (Get_ID ());
  411. m_RuntimeWaypath->Set_Flags (m_Flags);
  412. //
  413. // Add all the waypoints to the new waypath
  414. //
  415. Vector3 last_pos (0, 0, 0);
  416. for (int index = 0; index < m_PointList.Count (); index ++) {
  417. Vector3 curr_pos (0, 0, 0);
  418. WaypointNodeClass *waypoint = m_PointList[index];
  419. if (waypoint != NULL) {
  420. //
  421. // Calculate the position of this waypoint
  422. //
  423. curr_pos = waypoint->Get_Position () + Vector3 (0, 0, 0.2F);
  424. //
  425. // Check to see if the line segment formed by the last point and this point
  426. // intersects any pathfind-action portals (transition zones)
  427. //
  428. if (index > 0) {
  429. DynamicVectorClass<PathfindPortalClass *> list;
  430. PathfindClass::Get_Instance ()->Find_Portals (last_pos, curr_pos, list, true);
  431. //
  432. // Now add new nodes for any portals this segment intersects
  433. //
  434. for (int list_index = 0; list_index < list.Count (); list_index ++) {
  435. PathfindActionPortalClass *portal = list[list_index]->As_PathfindActionPortalClass ();
  436. AABoxClass portal_box;
  437. portal->Get_Bounding_Box (portal_box);
  438. //
  439. // Create a runtime waypoint and add it to the runtime
  440. // waypath.
  441. //
  442. WaypointClass *new_waypoint = new WaypointClass;
  443. new_waypoint->Set_ID (NodeMgrClass::Get_Node_ID (NODE_TYPE_WAYPOINT));
  444. new_waypoint->Set_Position (portal_box.Center);
  445. new_waypoint->Set_Action_Portal (portal);
  446. m_RuntimeWaypath->Add_Point (*new_waypoint);
  447. MEMBER_RELEASE (new_waypoint);
  448. }
  449. }
  450. //
  451. // Create a runtime waypoint and add it to the runtime
  452. // waypath.
  453. //
  454. WaypointClass *runtime_waypoint = new WaypointClass;
  455. runtime_waypoint->Set_ID (waypoint->Get_ID ());
  456. runtime_waypoint->Set_Position (curr_pos);
  457. runtime_waypoint->Set_Flags (0);
  458. runtime_waypoint->Set_Flag (WaypointClass::FLAG_REQUIRES_JUMP, waypoint->Get_Flag (WaypointNodeClass::FLAG_REQUIRES_JUMP));
  459. m_RuntimeWaypath->Add_Point (*runtime_waypoint);
  460. MEMBER_RELEASE (runtime_waypoint);
  461. }
  462. last_pos = curr_pos;
  463. }
  464. PathfindClass::Get_Instance ()->Add_Waypath (m_RuntimeWaypath);
  465. return ;
  466. }
  467. //////////////////////////////////////////////////////////////////////
  468. //
  469. // Post_Export
  470. //
  471. //////////////////////////////////////////////////////////////////////
  472. void
  473. WaypathNodeClass::Post_Export (void)
  474. {
  475. //
  476. // Put ourselves back into the system
  477. //
  478. if (m_PhysObj != NULL && m_IsInScene) {
  479. ::Get_Scene_Editor ()->Add_Dynamic_Object (m_PhysObj);
  480. }
  481. Release_Ref ();
  482. //
  483. // Remove the waypath object we just exported from the system
  484. //
  485. if (m_RuntimeWaypath != NULL) {
  486. PathfindClass::Get_Instance ()->Remove_Waypath (m_RuntimeWaypath);
  487. MEMBER_RELEASE (m_RuntimeWaypath);
  488. }
  489. return ;
  490. }
  491. //////////////////////////////////////////////////////////////////////
  492. //
  493. // Free_Waypoints
  494. //
  495. //////////////////////////////////////////////////////////////////////
  496. void
  497. WaypathNodeClass::Free_Waypoints (void)
  498. {
  499. //
  500. // Free our hold on each of the waypoints
  501. //
  502. for (int index = 0; index < m_PointList.Count (); index ++) {
  503. WaypointNodeClass *waypoint = m_PointList[index];
  504. if (waypoint != NULL) {
  505. waypoint->Set_Waypath (NULL);
  506. waypoint->Remove_From_Scene ();
  507. }
  508. MEMBER_RELEASE (waypoint);
  509. }
  510. m_PointList.Delete_All ();
  511. return ;
  512. }
  513. //////////////////////////////////////////////////////////////////////////////
  514. //
  515. // Add_To_Scene
  516. //
  517. //////////////////////////////////////////////////////////////////////////////
  518. void
  519. WaypathNodeClass::Add_To_Scene (void)
  520. {
  521. SceneEditorClass *scene = ::Get_Scene_Editor ();
  522. //
  523. // Add all the waypoints to the scene
  524. //
  525. for (int index = 0; index < m_PointList.Count (); index ++) {
  526. WaypointNodeClass *waypoint = m_PointList[index];
  527. if (waypoint != NULL) {
  528. waypoint->Add_To_Scene ();
  529. }
  530. }
  531. NodeClass::Add_To_Scene ();
  532. return ;
  533. }
  534. //////////////////////////////////////////////////////////////////////////////
  535. //
  536. // Remove_From_Scene
  537. //
  538. //////////////////////////////////////////////////////////////////////////////
  539. void
  540. WaypathNodeClass::Remove_From_Scene (void)
  541. {
  542. SceneEditorClass *scene = ::Get_Scene_Editor ();
  543. if (scene != NULL && m_IsInScene) {
  544. //
  545. // Remove all the waypoints from the scene
  546. //
  547. for (int index = 0; index < m_PointList.Count (); index ++) {
  548. WaypointNodeClass *waypoint = m_PointList[index];
  549. if (waypoint != NULL) {
  550. waypoint->Remove_From_Scene ();
  551. }
  552. }
  553. }
  554. NodeClass::Remove_From_Scene ();
  555. return ;
  556. }
  557. //////////////////////////////////////////////////////////////////////////////
  558. //
  559. // Delete_Point
  560. //
  561. //////////////////////////////////////////////////////////////////////////////
  562. void
  563. WaypathNodeClass::Delete_Point (int index)
  564. {
  565. SANITY_CHECK(index >= 0 && index < m_PointList.Count ()) {
  566. return ;
  567. }
  568. //
  569. // Remove the point from this path
  570. //
  571. WaypointNodeClass *waypoint = m_PointList[index];
  572. waypoint->Set_Waypath (NULL);
  573. waypoint->Remove_From_Scene ();
  574. //NodeMgrClass::Remove_Node (waypoint);
  575. MEMBER_RELEASE (waypoint);
  576. m_PointList.Delete (index);
  577. if (m_PointList.Count () > 0) {
  578. //
  579. // Refresh the line
  580. //
  581. Update_Line ();
  582. } else {
  583. //
  584. // Delete this path if there are no more points left
  585. //
  586. ::Get_Scene_Editor ()->Delete_Node (this, false);
  587. }
  588. return ;
  589. }
  590. //////////////////////////////////////////////////////////////////////////////
  591. //
  592. // Insert_Point
  593. //
  594. //////////////////////////////////////////////////////////////////////////////
  595. void
  596. WaypathNodeClass::Insert_Point (int index, const Vector3 &point)
  597. {
  598. SANITY_CHECK(index >= 0 && index <= m_PointList.Count ()) {
  599. return ;
  600. }
  601. //
  602. // Create a new waypoint and insert it into the list
  603. //
  604. WaypointNodeClass *waypoint = Create_Waypoint (point);
  605. m_PointList.Insert (index, waypoint);
  606. //
  607. // Refresh the line
  608. //
  609. Update_Line ();
  610. return ;
  611. }
  612. //////////////////////////////////////////////////////////////////////////////
  613. //
  614. // Find_Index
  615. //
  616. //////////////////////////////////////////////////////////////////////////////
  617. int
  618. WaypathNodeClass::Find_Index (WaypointNodeClass *waypoint)
  619. {
  620. int retval = -1;
  621. //
  622. // Loop over all the waypoints in our list until
  623. // we have found the matching pointer...
  624. //
  625. int index = m_PointList.Count ();
  626. while (index --) {
  627. if (waypoint == m_PointList[index]) {
  628. retval = index;
  629. break;
  630. }
  631. }
  632. return index;
  633. }
  634. //////////////////////////////////////////////////////////////////////////////
  635. //
  636. // Add_Point
  637. //
  638. //////////////////////////////////////////////////////////////////////////////
  639. int
  640. WaypathNodeClass::Add_Point (const Vector3 &point)
  641. {
  642. //
  643. // Create a new waypoint and add it to the end of our list...
  644. //
  645. WaypointNodeClass *waypoint = Create_Waypoint (point);
  646. m_PointList.Add (waypoint);
  647. //
  648. // Refresh the line
  649. //
  650. Update_Line ();
  651. return (m_PointList.Count () - 1);
  652. }
  653. //////////////////////////////////////////////////////////////////////////////
  654. //
  655. // On_Point_Moved
  656. //
  657. //////////////////////////////////////////////////////////////////////////////
  658. void
  659. WaypathNodeClass::On_Point_Moved (int index, const Vector3 &new_pos)
  660. {
  661. SegmentedLineClass *line = Peek_Line ();
  662. if (line != NULL) {
  663. //
  664. // Convert the position from world-space to object-space
  665. //
  666. Vector3 obj_space_pos (0, 0, 0);
  667. Vector3 line_pos = new_pos + Vector3 (0, 0, 0.2F);
  668. Matrix3D::Inverse_Transform_Vector (line->Get_Transform (), line_pos, &obj_space_pos);
  669. //
  670. // Pass the new position onto the line...
  671. //
  672. line->Set_Point_Location (index, obj_space_pos);
  673. if (index == 0 && (Get_Flag (FLAG_LOOPING) || m_PointList.Count () == 1)) {
  674. line->Set_Point_Location (m_PointList.Count (), obj_space_pos);
  675. }
  676. m_PhysObj->Update_Cull_Box ();
  677. }
  678. return ;
  679. }
  680. //////////////////////////////////////////////////////////////////////////////
  681. //
  682. // Update_Line
  683. //
  684. //////////////////////////////////////////////////////////////////////////////
  685. void
  686. WaypathNodeClass::Update_Line (void)
  687. {
  688. SegmentedLineClass *line = Peek_Line ();
  689. if (line != NULL) {
  690. //
  691. // Allocate a new array of points for the line render object
  692. //
  693. int count = m_PointList.Count ();
  694. Vector3 *points = new Vector3[count + 1];
  695. //
  696. // Fill in the array of points with our waypoint locations
  697. //
  698. for (int index = 0; index < count; index ++) {
  699. WaypointNodeClass *waypoint = m_PointList[index];
  700. //
  701. // Determine which model this waypoint should use...
  702. //
  703. if (index == 0) {
  704. waypoint->Set_Model (WaypointNodeClass::MODEL_START_PT);
  705. } else if (index == count-1) {
  706. if (Get_Flag (FLAG_TWO_WAY) == false) {
  707. waypoint->Set_Model (WaypointNodeClass::MODEL_END_PT);
  708. } else {
  709. waypoint->Set_Model (WaypointNodeClass::MODEL_START_PT);
  710. }
  711. } else {
  712. waypoint->Set_Model (WaypointNodeClass::MODEL_MIDDLE_PT);
  713. }
  714. //
  715. // Convert the world space position of this waypoint into
  716. // a local coordinate system for the path.
  717. //
  718. Vector3 world_pos = waypoint->Get_Position () + Vector3 (0, 0, 0.2F);
  719. Matrix3D::Inverse_Transform_Vector (m_Transform, world_pos, &points[index]);
  720. }
  721. //
  722. // Handle the single point path or a looping path
  723. //
  724. if (count == 1 || Get_Flag (FLAG_LOOPING)) {
  725. points[index++] = points[0];
  726. count ++;
  727. }
  728. //
  729. // Pass the new point list onto the line render object
  730. //
  731. line->Set_Points (count, points);
  732. SAFE_DELETE_ARRAY (points);
  733. m_PhysObj->Update_Cull_Box ();
  734. }
  735. return ;
  736. }
  737. //////////////////////////////////////////////////////////////////////////////
  738. //
  739. // Create_Waypoint
  740. //
  741. //////////////////////////////////////////////////////////////////////////////
  742. WaypointNodeClass *
  743. WaypathNodeClass::Create_Waypoint (const Vector3 &point)
  744. {
  745. //
  746. // Create the new waypoint
  747. //
  748. WaypointNodeClass *waypoint = new WaypointNodeClass;
  749. waypoint->Set_Waypath (this);
  750. waypoint->Parent_Set_Transform (Matrix3D (point));
  751. waypoint->Initialize ();
  752. NodeMgrClass::Setup_Node_Identity (*waypoint);
  753. //
  754. // Insert the new waypoint into the scene if the
  755. // path is supposed to be in the scene...
  756. //
  757. if (m_IsInScene) {
  758. waypoint->Add_To_Scene ();
  759. }
  760. //NodeMgrClass::Add_Node (waypoint);
  761. return waypoint;
  762. }
  763. //////////////////////////////////////////////////////////////////////////////
  764. //
  765. // Peek_Line
  766. //
  767. //////////////////////////////////////////////////////////////////////////////
  768. SegmentedLineClass *
  769. WaypathNodeClass::Peek_Line (void)
  770. {
  771. SegmentedLineClass *line = NULL;
  772. if (m_PhysObj != NULL) {
  773. line = (SegmentedLineClass *)m_PhysObj->Peek_Model ();
  774. }
  775. return line;
  776. }
  777. //////////////////////////////////////////////////////////////////////////////
  778. //
  779. // Set_Flags
  780. //
  781. //////////////////////////////////////////////////////////////////////////////
  782. void
  783. WaypathNodeClass::Set_Flags (int flags)
  784. {
  785. m_Flags = flags;
  786. return ;
  787. }
  788. //////////////////////////////////////////////////////////////////////////////
  789. //
  790. // Set_Flag
  791. //
  792. //////////////////////////////////////////////////////////////////////////////
  793. void
  794. WaypathNodeClass::Set_Flag (int flag, bool onoff)
  795. {
  796. m_Flags &= ~flag;
  797. if (onoff) {
  798. m_Flags |= flag;
  799. }
  800. return ;
  801. }
  802. //////////////////////////////////////////////////////////////////////////////
  803. //
  804. // Get_Flag
  805. //
  806. //////////////////////////////////////////////////////////////////////////////
  807. bool
  808. WaypathNodeClass::Get_Flag (int flag)
  809. {
  810. return bool((m_Flags & flag) == flag);
  811. }
  812. //////////////////////////////////////////////////////////////////////////////
  813. //
  814. // Hide
  815. //
  816. //////////////////////////////////////////////////////////////////////////////
  817. void
  818. WaypathNodeClass::Hide (bool hide)
  819. {
  820. //
  821. // Apply the same operation to all the points along the path
  822. //
  823. for (int index = 0; index < m_PointList.Count (); index ++) {
  824. WaypointNodeClass *waypoint = m_PointList[index];
  825. if (waypoint != NULL) {
  826. waypoint->Hide (hide);
  827. }
  828. }
  829. NodeClass::Hide (hide);
  830. return ;
  831. }
  832. //////////////////////////////////////////////////////////////////////////////
  833. //
  834. // Show_Settings_Dialog
  835. //
  836. //////////////////////////////////////////////////////////////////////////////
  837. bool
  838. WaypathNodeClass::Show_Settings_Dialog (void)
  839. {
  840. NodeInfoPageClass info_tab (this);
  841. PositionPageClass pos_tab (this);
  842. //
  843. // Add each tab to the property sheet
  844. //
  845. EditorPropSheetClass prop_sheet;
  846. prop_sheet.Add_Page (&info_tab);
  847. prop_sheet.Add_Page (&pos_tab);
  848. // Show the property sheet
  849. UINT ret_code = prop_sheet.DoModal ();
  850. // Return true if the user clicked OK
  851. return (ret_code == IDOK);
  852. }
  853. //////////////////////////////////////////////////////////////////////////////
  854. //
  855. // On_Delete
  856. //
  857. //////////////////////////////////////////////////////////////////////////////
  858. void
  859. WaypathNodeClass::On_Delete (void)
  860. {
  861. //
  862. // Apply the same operation to all the points along the path
  863. //
  864. for (int index = 0; index < m_PointList.Count (); index ++) {
  865. WaypointNodeClass *waypoint = m_PointList[index];
  866. //NodeMgrClass::Remove_Node (waypoint);
  867. }
  868. return ;
  869. }
  870. //////////////////////////////////////////////////////////////////////////////
  871. //
  872. // On_Restore
  873. //
  874. //////////////////////////////////////////////////////////////////////////////
  875. void
  876. WaypathNodeClass::On_Restore (void)
  877. {
  878. //
  879. // Apply the same operation to all the points along the path
  880. //
  881. for (int index = 0; index < m_PointList.Count (); index ++) {
  882. WaypointNodeClass *waypoint = m_PointList[index];
  883. //NodeMgrClass::Add_Node (waypoint);
  884. }
  885. return ;
  886. }