Node.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  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/Node.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/18/02 11:54a $*
  29. * *
  30. * $Revision:: 49 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "stdafx.h"
  36. #include "node.h"
  37. #include "phys.h"
  38. #include "sceneeditor.h"
  39. #include "utils.h"
  40. #include "selectionbox.h"
  41. #include "mover.h"
  42. #include "chunkio.h"
  43. #include "preset.h"
  44. #include "wwstring.h"
  45. #include "presetmgr.h"
  46. #include "vispointgenerator.h"
  47. #include "mesh.h"
  48. #include "preset.h"
  49. #include "staticphys.h"
  50. #include "NodeInfoPage.h"
  51. #include "EditorPropSheet.h"
  52. #include "LevelEditView.h"
  53. #include "NodeMgr.h"
  54. #include "PositionPage.h"
  55. ///////////////////////////////////////////////////////////////////////
  56. // Constants
  57. ///////////////////////////////////////////////////////////////////////
  58. const Vector3 SEL_COLOR_NORMAL = Vector3 (0.8F, 0.8F, 0.8F);
  59. const Vector3 SEL_COLOR_LOCKED = Vector3 (0.0F, 0.0F, 0.8F);
  60. const Vector3 SEL_COLOR_INVALID = Vector3 (1.0F, 0.0F, 0.0F);
  61. enum
  62. {
  63. CHUNKID_VARIABLES = 0x00000100,
  64. CHUNKID_COMMENTS
  65. };
  66. enum
  67. {
  68. VARID_NAME = 0x01,
  69. VARID_IS_LOCKED,
  70. VARID_PRESETID,
  71. VARID_ID,
  72. VARID_ROT_RESTRICT,
  73. VARID_THISPTR,
  74. VARID_TRANSFORM,
  75. VARID_VISID,
  76. VARID_COMMENTS,
  77. VARID_VISSECTORID,
  78. VARID_CULLLINK,
  79. VARID_NEEDS_SAVE,
  80. VARID_CONTAINER_ID,
  81. VARID_IS_PROXIED
  82. };
  83. //////////////////////////////////////////////////////////////////////
  84. //
  85. // NodeClass
  86. //
  87. //////////////////////////////////////////////////////////////////////
  88. NodeClass::NodeClass (PresetClass *preset)
  89. : m_Preset (NULL),
  90. m_PresetID (0),
  91. m_ID (0),
  92. m_SelectionBox (NULL),
  93. m_IsLocked (false),
  94. m_RotationRestricted (false),
  95. m_Orientation (true),
  96. m_IsInScene (false),
  97. m_SelColor (SEL_COLOR_NORMAL),
  98. m_NextNode (NULL),
  99. m_PrevNode (NULL),
  100. m_HitTestInfo (this),
  101. m_NeedsSave (true),
  102. m_IsProxied (false),
  103. m_Transform (1),
  104. m_CullLink (-1),
  105. m_ContainerPresetID (0)
  106. {
  107. Set_Preset (preset);
  108. return ;
  109. }
  110. //////////////////////////////////////////////////////////////////////
  111. //
  112. // NodeClass
  113. //
  114. //////////////////////////////////////////////////////////////////////
  115. NodeClass::NodeClass (const NodeClass &src)
  116. : m_Preset (NULL),
  117. m_PresetID (0),
  118. m_ID (0),
  119. m_SelectionBox (NULL),
  120. m_IsLocked (false),
  121. m_RotationRestricted (false),
  122. m_Orientation (true),
  123. m_IsInScene (false),
  124. m_SelColor (SEL_COLOR_NORMAL),
  125. m_NextNode (NULL),
  126. m_PrevNode (NULL),
  127. m_HitTestInfo (this),
  128. m_NeedsSave (true),
  129. m_IsProxied (false),
  130. m_Transform (1),
  131. m_CullLink (-1),
  132. m_ContainerPresetID (0)
  133. {
  134. *this = src;
  135. return ;
  136. }
  137. //////////////////////////////////////////////////////////////////////
  138. //
  139. // ~NodeClass
  140. //
  141. //////////////////////////////////////////////////////////////////////
  142. NodeClass::~NodeClass (void)
  143. {
  144. SAFE_DELETE (m_SelectionBox);
  145. return ;
  146. }
  147. //////////////////////////////////////////////////////////////////////
  148. //
  149. // Add_To_Scene
  150. //
  151. //////////////////////////////////////////////////////////////////////
  152. void
  153. NodeClass::Add_To_Scene (void)
  154. {
  155. PhysClass *phys_obj = Peek_Physics_Obj ();
  156. if (phys_obj != NULL && phys_obj->Get_Culling_System () == NULL) {
  157. //
  158. // Add the object to either the static or dynamic culling system
  159. //
  160. SceneEditorClass *scene = ::Get_Scene_Editor ();
  161. if (Is_Static ()) {
  162. scene->Add_Static_Object ((StaticPhysClass *)phys_obj, Get_Cull_Link ());
  163. } else {
  164. scene->Add_Dynamic_Object (phys_obj);
  165. }
  166. }
  167. m_IsInScene = true;
  168. return ;
  169. }
  170. //////////////////////////////////////////////////////////////////////
  171. //
  172. // Remove_From_Scene
  173. //
  174. //////////////////////////////////////////////////////////////////////
  175. void
  176. NodeClass::Remove_From_Scene (void)
  177. {
  178. PhysClass *phys_obj = Peek_Physics_Obj ();
  179. if (phys_obj != NULL && phys_obj->Get_Culling_System () != NULL) {
  180. //
  181. // Record the cull-link index (if necessary)
  182. //
  183. Update_Cached_Cull_Link ();
  184. //
  185. // Remove this object from either the static or dynamic culling system
  186. //
  187. SceneEditorClass *scene = ::Get_Scene_Editor ();
  188. if (Is_Static ()) {
  189. scene->Remove_Object ((StaticPhysClass *)phys_obj);
  190. } else {
  191. scene->Remove_Object (phys_obj);
  192. }
  193. }
  194. m_IsInScene = false;
  195. return ;
  196. }
  197. //////////////////////////////////////////////////////////////////////
  198. //
  199. // Update_Cached_Cull_Link
  200. //
  201. //////////////////////////////////////////////////////////////////////
  202. void
  203. NodeClass::Update_Cached_Cull_Link (void)
  204. {
  205. //
  206. // We can only do this if the physics object is currently in the scene
  207. //
  208. PhysClass *phys_obj = Peek_Physics_Obj ();
  209. if (phys_obj != NULL && phys_obj->Get_Culling_System () != NULL) {
  210. //
  211. // Make sure this is a static physics object
  212. //
  213. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  214. if (static_phys_obj != NULL) {
  215. //
  216. // Dig the cull link out from the culling system structure
  217. //
  218. AABTreeLinkClass *link = (AABTreeLinkClass *)static_phys_obj->Get_Cull_Link ();
  219. if (link != NULL) {
  220. m_CullLink = link->Node->Index;
  221. }
  222. }
  223. }
  224. return ;
  225. }
  226. //////////////////////////////////////////////////////////////////////
  227. //
  228. // Peek_Render_Obj
  229. //
  230. //////////////////////////////////////////////////////////////////////
  231. RenderObjClass *
  232. NodeClass::Peek_Render_Obj (void) const
  233. {
  234. RenderObjClass *render_obj = NULL;
  235. PhysClass *phys_obj = Peek_Physics_Obj ();
  236. if (phys_obj != NULL) {
  237. render_obj = phys_obj->Peek_Model ();
  238. }
  239. return render_obj;
  240. }
  241. //////////////////////////////////////////////////////////////////////
  242. //
  243. // Hide
  244. //
  245. //////////////////////////////////////////////////////////////////////
  246. void
  247. NodeClass::Hide (bool hide)
  248. {
  249. RenderObjClass *render_obj = Peek_Render_Obj ();
  250. if (render_obj != NULL) {
  251. render_obj->Set_Hidden (hide);
  252. }
  253. return ;
  254. }
  255. //////////////////////////////////////////////////////////////////////
  256. //
  257. // Is_Hidden
  258. //
  259. //////////////////////////////////////////////////////////////////////
  260. bool
  261. NodeClass::Is_Hidden (void) const
  262. {
  263. bool is_hidden = false;
  264. RenderObjClass *render_obj = Peek_Render_Obj ();
  265. if (render_obj != NULL) {
  266. is_hidden = (render_obj->Is_Not_Hidden_At_All () == false);
  267. }
  268. return is_hidden;
  269. }
  270. //////////////////////////////////////////////////////////////////////
  271. //
  272. // Show_Selection_Box
  273. //
  274. //////////////////////////////////////////////////////////////////////
  275. void
  276. NodeClass::Show_Selection_Box (bool show)
  277. {
  278. if (show) {
  279. //
  280. // Create the selection box if necessary
  281. //
  282. if (m_SelectionBox == NULL) {
  283. m_SelectionBox = new SelectionBoxClass;
  284. }
  285. Update_Selection_Color ();
  286. m_SelectionBox->Display_Around_Node (*this);
  287. } else {
  288. //
  289. // Hide and destroy the selection box
  290. //
  291. if (m_SelectionBox != NULL) {
  292. m_SelectionBox->Remove_From_Scene ();
  293. SAFE_DELETE (m_SelectionBox);
  294. }
  295. }
  296. return ;
  297. }
  298. /////////////////////////////////////////////////////////////////
  299. //
  300. // Update_Selection_Color
  301. //
  302. /////////////////////////////////////////////////////////////////
  303. void
  304. NodeClass::Update_Selection_Color (void)
  305. {
  306. m_SelColor = m_IsLocked ? SEL_COLOR_LOCKED : SEL_COLOR_NORMAL;
  307. //
  308. // Only perform the bounding box check if we have a valid phys obj pointer
  309. //
  310. PhysClass *collision_obj = Peek_Collision_Obj ();
  311. if (collision_obj != NULL) {
  312. AABoxClass aabox;
  313. OBBoxClass obbox;
  314. bool is_aabox = ::Get_Collision_Box (collision_obj->Peek_Model (), aabox, obbox);
  315. if (is_aabox) {
  316. Vector3 move (0, 0, 0);
  317. //
  318. // See if the AABox intersects anything
  319. //
  320. collision_obj->Inc_Ignore_Counter();
  321. CastResultStruct res;
  322. PhysAABoxCollisionTestClass boxtest (aabox, move, &res, GAME_COLLISION_GROUP);
  323. PhysicsSceneClass::Get_Instance()->Cast_AABox (boxtest);
  324. collision_obj->Dec_Ignore_Counter();
  325. if (boxtest.Result->StartBad) {
  326. m_SelColor = SEL_COLOR_INVALID;
  327. }
  328. } else {
  329. Vector3 move (0, 0, 0);
  330. //
  331. // See if the OBBox intersects anything
  332. //
  333. collision_obj->Inc_Ignore_Counter();
  334. CastResultStruct res;
  335. PhysOBBoxCollisionTestClass boxtest (obbox, move, &res, GAME_COLLISION_GROUP);
  336. PhysicsSceneClass::Get_Instance()->Cast_OBBox (boxtest);
  337. collision_obj->Dec_Ignore_Counter();
  338. if (boxtest.Result->StartBad) {
  339. m_SelColor = SEL_COLOR_INVALID;
  340. }
  341. }
  342. }
  343. //
  344. // Update the selection box if it exists
  345. //
  346. if (m_SelectionBox != NULL) {
  347. m_SelectionBox->Set_Color (m_SelColor);
  348. }
  349. return ;
  350. }
  351. /////////////////////////////////////////////////////////////////
  352. //
  353. // Update_Selection_Box
  354. //
  355. /////////////////////////////////////////////////////////////////
  356. void
  357. NodeClass::Update_Selection_Box (void)
  358. {
  359. //
  360. // If we have a selection box, then update its color and position
  361. //
  362. if (m_SelectionBox != NULL) {
  363. Update_Selection_Color ();
  364. m_SelectionBox->Display_Around_Node (*this);
  365. }
  366. return ;
  367. }
  368. /////////////////////////////////////////////////////////////////
  369. //
  370. // Lock
  371. //
  372. /////////////////////////////////////////////////////////////////
  373. void
  374. NodeClass::Lock (bool lock)
  375. {
  376. m_IsLocked = lock;
  377. Update_Selection_Color ();
  378. return ;
  379. }
  380. /////////////////////////////////////////////////////////////////
  381. //
  382. // Is_Locked
  383. //
  384. /////////////////////////////////////////////////////////////////
  385. bool
  386. NodeClass::Is_Locked (void) const
  387. {
  388. return m_IsLocked;
  389. }
  390. /////////////////////////////////////////////////////////////////
  391. //
  392. // Translate
  393. //
  394. /////////////////////////////////////////////////////////////////
  395. void
  396. NodeClass::Translate (const Vector3 &vector)
  397. {
  398. MoverClass::Translate_Node (this, vector);
  399. return ;
  400. }
  401. /////////////////////////////////////////////////////////////////
  402. //
  403. // Rotate
  404. //
  405. /////////////////////////////////////////////////////////////////
  406. void
  407. NodeClass::Rotate
  408. (
  409. const Matrix3D &rotation_matrix,
  410. const Matrix3D &coord_system
  411. )
  412. {
  413. MoverClass::Rotate_Node (this, rotation_matrix, coord_system);
  414. return ;
  415. }
  416. /////////////////////////////////////////////////////////////////
  417. //
  418. // On_Rotate
  419. //
  420. /////////////////////////////////////////////////////////////////
  421. void
  422. NodeClass::On_Rotate (void)
  423. {
  424. m_Orientation = ::Build_Quaternion (Get_Transform ());
  425. return ;
  426. }
  427. /////////////////////////////////////////////////////////////////
  428. //
  429. // On_Translate
  430. //
  431. /////////////////////////////////////////////////////////////////
  432. void
  433. NodeClass::On_Translate (void)
  434. {
  435. m_Orientation = ::Build_Quaternion (Get_Transform ());
  436. return ;
  437. }
  438. /////////////////////////////////////////////////////////////////
  439. //
  440. // On_Transform
  441. //
  442. /////////////////////////////////////////////////////////////////
  443. void
  444. NodeClass::On_Transform (void)
  445. {
  446. m_Orientation = ::Build_Quaternion (Get_Transform ());
  447. return ;
  448. }
  449. /////////////////////////////////////////////////////////////////
  450. //
  451. // Save
  452. //
  453. /////////////////////////////////////////////////////////////////
  454. bool
  455. NodeClass::Save (ChunkSaveClass &csave)
  456. {
  457. //
  458. // Update the preset-id
  459. //
  460. if (m_Preset != NULL) {
  461. m_PresetID = m_Preset->Get_ID ();
  462. }
  463. //
  464. // Make sure we've got the latest cull-link information
  465. //
  466. Update_Cached_Cull_Link ();
  467. Update_Cached_Vis_IDs ();
  468. //
  469. // Save the comments to their own chunk
  470. //
  471. WRITE_WWSTRING_CHUNK (csave, CHUNKID_COMMENTS, m_Comments);
  472. //
  473. // Save the variables
  474. //
  475. csave.Begin_Chunk (CHUNKID_VARIABLES);
  476. WRITE_MICRO_CHUNK_STRING (csave, VARID_NAME, (LPCTSTR)m_Name);
  477. WRITE_MICRO_CHUNK (csave, VARID_IS_LOCKED, m_IsLocked);
  478. WRITE_MICRO_CHUNK (csave, VARID_ID, m_ID);
  479. WRITE_MICRO_CHUNK (csave, VARID_ROT_RESTRICT, m_RotationRestricted);
  480. WRITE_MICRO_CHUNK (csave, VARID_TRANSFORM, m_Transform);
  481. WRITE_MICRO_CHUNK (csave, VARID_PRESETID, m_PresetID);
  482. WRITE_MICRO_CHUNK (csave, VARID_CULLLINK, m_CullLink);
  483. WRITE_MICRO_CHUNK (csave, VARID_NEEDS_SAVE, m_NeedsSave);
  484. WRITE_MICRO_CHUNK (csave, VARID_IS_PROXIED, m_IsProxied);
  485. WRITE_MICRO_CHUNK (csave, VARID_CONTAINER_ID, m_ContainerPresetID);
  486. //
  487. // Save the node's vis ID (if it has one)
  488. //
  489. PhysClass *phys_obj = Peek_Physics_Obj ();
  490. if (phys_obj != NULL) {
  491. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  492. if (static_phys_obj != NULL) {
  493. uint32 vis_id = static_phys_obj->Get_Vis_Object_ID ();
  494. WRITE_MICRO_CHUNK (csave, VARID_VISID, vis_id);
  495. vis_id = static_phys_obj->Get_Vis_Sector_ID();
  496. WRITE_MICRO_CHUNK (csave, VARID_VISSECTORID, vis_id);
  497. }
  498. }
  499. //
  500. // For pointer remapping
  501. //
  502. NodeClass *this_ptr = this;
  503. WRITE_MICRO_CHUNK (csave, VARID_THISPTR, this_ptr);
  504. csave.End_Chunk ();
  505. return true;
  506. }
  507. /////////////////////////////////////////////////////////////////
  508. //
  509. // Load
  510. //
  511. /////////////////////////////////////////////////////////////////
  512. bool
  513. NodeClass::Load (ChunkLoadClass &cload)
  514. {
  515. while (cload.Open_Chunk ()) {
  516. switch (cload.Cur_Chunk_ID ()) {
  517. READ_WWSTRING_CHUNK (cload, CHUNKID_COMMENTS, m_Comments);
  518. case CHUNKID_VARIABLES:
  519. Load_Variables (cload);
  520. break;
  521. }
  522. cload.Close_Chunk ();
  523. }
  524. return true;
  525. }
  526. /////////////////////////////////////////////////////////////////
  527. //
  528. // Load_Variables
  529. //
  530. /////////////////////////////////////////////////////////////////
  531. bool
  532. NodeClass::Load_Variables (ChunkLoadClass &cload)
  533. {
  534. PresetClass *old_this_ptr = NULL;
  535. while (cload.Open_Micro_Chunk ()) {
  536. switch (cload.Cur_Micro_Chunk_ID ()) {
  537. READ_MICRO_CHUNK (cload, VARID_IS_LOCKED, m_IsLocked);
  538. READ_MICRO_CHUNK (cload, VARID_ID, m_ID);
  539. READ_MICRO_CHUNK (cload, VARID_ROT_RESTRICT, m_RotationRestricted);
  540. READ_MICRO_CHUNK (cload, VARID_PRESETID, m_PresetID);
  541. READ_MICRO_CHUNK (cload, VARID_THISPTR, old_this_ptr)
  542. READ_MICRO_CHUNK (cload, VARID_TRANSFORM, m_Transform)
  543. READ_MICRO_CHUNK_WWSTRING (cload, VARID_NAME, m_Name);
  544. READ_MICRO_CHUNK_WWSTRING (cload, VARID_COMMENTS, m_Comments);
  545. READ_MICRO_CHUNK (cload, VARID_CULLLINK, m_CullLink);
  546. READ_MICRO_CHUNK (cload, VARID_NEEDS_SAVE, m_NeedsSave);
  547. READ_MICRO_CHUNK (cload, VARID_IS_PROXIED, m_IsProxied);
  548. READ_MICRO_CHUNK (cload, VARID_CONTAINER_ID, m_ContainerPresetID);
  549. case VARID_VISID:
  550. {
  551. uint32 vis_id = 0;
  552. cload.Read (&vis_id, sizeof (vis_id));
  553. //
  554. // Pass the vis-object-id onto the physics object (if it needs one)
  555. //
  556. PhysClass *phys_obj = Peek_Physics_Obj ();
  557. if (phys_obj != NULL) {
  558. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  559. if (static_phys_obj != NULL) {
  560. static_phys_obj->Set_Vis_Object_ID (vis_id);
  561. }
  562. }
  563. }
  564. case VARID_VISSECTORID:
  565. {
  566. uint32 vis_id = 0;
  567. cload.Read (&vis_id, sizeof (vis_id));
  568. //
  569. // Pass the vis-sector-id onto the physics object (if it needs one)
  570. //
  571. PhysClass *phys_obj = Peek_Physics_Obj ();
  572. if (phys_obj != NULL) {
  573. StaticPhysClass *static_phys_obj = phys_obj->As_StaticPhysClass ();
  574. if (static_phys_obj != NULL) {
  575. static_phys_obj->Set_Vis_Sector_ID (vis_id);
  576. }
  577. }
  578. }
  579. break;
  580. }
  581. cload.Close_Micro_Chunk ();
  582. }
  583. //
  584. // Handle pointer remapping
  585. //
  586. WWASSERT (old_this_ptr != NULL);
  587. SaveLoadSystemClass::Register_Pointer (old_this_ptr, this);
  588. //
  589. // Get the preset pointer from its ID
  590. //
  591. m_Preset = PresetMgrClass::Find_Preset (m_PresetID);
  592. return true;
  593. }
  594. /////////////////////////////////////////////////////////////////
  595. //
  596. // Has_Vis_Sectors
  597. //
  598. /////////////////////////////////////////////////////////////////
  599. bool
  600. NodeClass::Has_Vis_Sectors (RenderObjClass *render_obj)
  601. {
  602. bool retval = false;
  603. //
  604. // Start with the parent render obj if none is supplied.
  605. //
  606. if (render_obj == NULL) {
  607. render_obj = Peek_Render_Obj ();
  608. }
  609. if (render_obj != NULL) {
  610. //
  611. // Loop through all the render objects sub-objects
  612. //
  613. int count = render_obj->Get_Num_Sub_Objects ();
  614. for (int index = 0; (index < count) && !retval; index ++) {
  615. // Get a pointer to this subobject
  616. RenderObjClass *sub_object = render_obj->Get_Sub_Object (index);
  617. if (sub_object != NULL) {
  618. retval |= Has_Vis_Sectors (sub_object);
  619. MEMBER_RELEASE (sub_object);
  620. }
  621. }
  622. //
  623. // Is this render object a mesh?
  624. //
  625. if ((render_obj->Class_ID () == RenderObjClass::CLASSID_MESH) &&
  626. (render_obj->Get_Collision_Type () & COLLISION_TYPE_VIS))
  627. {
  628. retval = true;
  629. }
  630. }
  631. return retval;
  632. }
  633. /////////////////////////////////////////////////////////////////
  634. //
  635. // Add_Vis_Points
  636. //
  637. /////////////////////////////////////////////////////////////////
  638. void
  639. NodeClass::Add_Vis_Points
  640. (
  641. VisPointGeneratorClass & generator,
  642. RenderObjClass * render_obj
  643. )
  644. {
  645. //
  646. // Let the generator know which node its processing
  647. //
  648. generator.Set_Current_Node (this);
  649. //
  650. // Start with the parent render obj if none is supplied.
  651. //
  652. if (render_obj == NULL) {
  653. render_obj = Peek_Render_Obj ();
  654. }
  655. //
  656. // Loop through all the render objects sub-objects
  657. //
  658. int count = render_obj->Get_Num_Sub_Objects ();
  659. for (int index = 0; index < count; index ++) {
  660. // Get a pointer to this subobject
  661. RenderObjClass *sub_object = render_obj->Get_Sub_Object (index);
  662. if (sub_object != NULL) {
  663. Add_Vis_Points (generator, sub_object);
  664. MEMBER_RELEASE (sub_object);
  665. }
  666. }
  667. //
  668. // Is this render object a mesh?
  669. //
  670. if ((render_obj->Class_ID () == RenderObjClass::CLASSID_MESH) &&
  671. (render_obj->Get_Collision_Type () & COLLISION_TYPE_VIS))
  672. {
  673. //
  674. // Pass this mesh off to the generator
  675. //
  676. MeshClass *mesh = static_cast<MeshClass *> (render_obj);
  677. generator.Submit_Mesh (*mesh);
  678. }
  679. return ;
  680. }
  681. /////////////////////////////////////////////////////////////////
  682. //
  683. // Reload
  684. //
  685. /////////////////////////////////////////////////////////////////
  686. void
  687. NodeClass::Reload (void)
  688. {
  689. CLevelEditView::Allow_Repaint (false);
  690. bool in_scene = m_IsInScene;
  691. if (in_scene) {
  692. Remove_From_Scene ();
  693. }
  694. //
  695. // Reinitialize the node from its preset
  696. //
  697. //m_Preset = PresetMgrClass::Find_Preset (m_PresetID);
  698. Initialize ();
  699. if (in_scene) {
  700. Add_To_Scene ();
  701. }
  702. CLevelEditView::Allow_Repaint (true);
  703. return ;
  704. }
  705. /////////////////////////////////////////////////////////////////
  706. //
  707. // Show_Settings_Dialog
  708. //
  709. /////////////////////////////////////////////////////////////////
  710. bool
  711. NodeClass::Show_Settings_Dialog (void)
  712. {
  713. NodeInfoPageClass info_tab (this);
  714. PositionPageClass pos_tab (this);
  715. EditorPropSheetClass prop_sheet;
  716. prop_sheet.Add_Page (&info_tab);
  717. prop_sheet.Add_Page (&pos_tab);
  718. // Show the property sheet
  719. UINT ret_code = prop_sheet.DoModal ();
  720. // Return true if the user clicked OK
  721. return (ret_code == IDOK);
  722. }
  723. /////////////////////////////////////////////////////////////////
  724. //
  725. // operator=
  726. //
  727. /////////////////////////////////////////////////////////////////
  728. const NodeClass &
  729. NodeClass::operator= (const NodeClass &src)
  730. {
  731. //
  732. // Copy the data that makes sense to copy.
  733. //
  734. m_Comments = src.m_Comments;
  735. m_PresetID = src.m_PresetID;
  736. m_IsLocked = src.m_IsLocked;
  737. m_RotationRestricted = src.m_RotationRestricted;
  738. m_Preset = src.m_Preset;
  739. m_Orientation = src.m_Orientation;
  740. m_SelColor = src.m_SelColor;
  741. m_Transform = src.m_Transform;
  742. //
  743. // Make sure the node has a unique id and name
  744. //
  745. NodeMgrClass::Setup_Node_Identity (*this);
  746. //
  747. // Give the node a chance to create any internal
  748. // data (game objects, phys objects, etc) it needs.
  749. //
  750. Initialize ();
  751. return *this;
  752. }
  753. /////////////////////////////////////////////////////////////////
  754. //
  755. // Set_ID
  756. //
  757. /////////////////////////////////////////////////////////////////
  758. void
  759. NodeClass::Set_ID (uint32 id)
  760. {
  761. m_ID = id;
  762. NodeMgrClass::Setup_Node_Identity (*this);
  763. return ;
  764. }
  765. /////////////////////////////////////////////////////////////////
  766. //
  767. // Get_Model_Name
  768. //
  769. /////////////////////////////////////////////////////////////////
  770. LPCTSTR
  771. NodeClass::Get_Model_Name (void) const
  772. {
  773. LPCTSTR name = NULL;
  774. RenderObjClass *render_obj = Peek_Render_Obj ();
  775. if (render_obj != NULL) {
  776. name = render_obj->Get_Name ();
  777. }
  778. return name;
  779. }