nodeRelation.cxx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. // Filename: nodeRelation.cxx
  2. // Created by: drose (26Oct98)
  3. //
  4. #include "nodeRelation.h"
  5. #include "node.h"
  6. #include "config_graph.h"
  7. #include <boundingSphere.h>
  8. #include <notify.h>
  9. TypeHandle NodeRelation::_type_handle;
  10. LastGraphUpdate last_graph_update;
  11. Factory<NodeRelation> *NodeRelation::_factory = NULL;
  12. // Following are a handful of local template functions that provide
  13. // support for manipulating the list of arcs on nodes. They are
  14. // template functions because they work as well on UpRelationArcs as
  15. // as they do on DownRelationArcs, which are slightly different things
  16. // (DownRelationArcs are reference-counting).
  17. ////////////////////////////////////////////////////////////////////
  18. // Function: verify_arc_list
  19. // Description: A local template function that verifies that the list
  20. // of arcs (either UpRelationArcs or DownRelationArcs)
  21. // is correctly sorted, if paranoid_graph is set.
  22. // Otherwise, it does nothing.
  23. ////////////////////////////////////////////////////////////////////
  24. #ifdef NDEBUG
  25. template<class Iterator>
  26. INLINE void
  27. verify_arc_list(Iterator, Iterator) {
  28. }
  29. #else // NDEBUG
  30. template<class Iterator>
  31. static void
  32. verify_arc_list(Iterator begin, Iterator end) {
  33. if (paranoid_graph) {
  34. if (begin < end) {
  35. Iterator i = begin;
  36. int sort = (*i)->get_sort();
  37. ++i;
  38. while (i < end) {
  39. nassertv(sort <= (*i)->get_sort());
  40. sort = (*i)->get_sort();
  41. ++i;
  42. }
  43. }
  44. }
  45. }
  46. #endif // NDEBUG
  47. ////////////////////////////////////////////////////////////////////
  48. // Function: find_insert_position
  49. // Description: A local template function that performs a binary
  50. // search on the arcs list (either UpRelationArcs or
  51. // DownRelationArcs) and finds the place to insert the
  52. // indicated arc.
  53. //
  54. // This place will be at the end of the similarly-sorted
  55. // arcs.
  56. ////////////////////////////////////////////////////////////////////
  57. template<class Iterator>
  58. static Iterator
  59. r_find_insert_position(Iterator begin, Iterator end, NodeRelation *arc) {
  60. if (begin == end) {
  61. // The list is empty; the insert position is the end of the list.
  62. return end;
  63. }
  64. Iterator center = begin + (end - begin) / 2;
  65. nassertr(center < end, end);
  66. if ((*center)->get_sort() > arc->get_sort()) {
  67. // Insert before the center.
  68. return r_find_insert_position(begin, center, arc);
  69. } else { // (*center)->get_sort() <= arc->get_sort();
  70. // Insert after the center.
  71. return r_find_insert_position(center + 1, end, arc);
  72. }
  73. }
  74. template<class Iterator>
  75. static Iterator
  76. find_insert_position(Iterator begin, Iterator end, NodeRelation *arc) {
  77. Iterator result = r_find_insert_position(begin, end, arc);
  78. #ifndef NDEBUG
  79. // Verify the result.
  80. if (paranoid_graph) {
  81. // If there is a node before the indicated position, it must have
  82. // a sort value either less than or equal to this arc's value.
  83. if (begin < result) {
  84. nassertr((*(result - 1))->get_sort() <= arc->get_sort(), result);
  85. }
  86. // If there is a node after the indicated position, it must have a
  87. // sort value greater than this arc's value.
  88. if (result < end) {
  89. nassertr((*result)->get_sort() > arc->get_sort(), result);
  90. }
  91. }
  92. #endif
  93. return result;
  94. }
  95. ////////////////////////////////////////////////////////////////////
  96. // Function: find_arc
  97. // Description: A local template function that performs a binary
  98. // search on the arcs list (either UpRelationArcs or
  99. // DownRelationArcs) and finds the arc's position within
  100. // the list. It returns end if the arc is not within
  101. // the list.
  102. ////////////////////////////////////////////////////////////////////
  103. template<class Iterator>
  104. static Iterator
  105. find_arc(Iterator begin, Iterator end, NodeRelation *arc) {
  106. if (begin == end) {
  107. // The list is empty; the arc is not on the list.
  108. return end;
  109. }
  110. Iterator center = begin + (end - begin) / 2;
  111. nassertr(center < end, end);
  112. if ((*center)->get_sort() > arc->get_sort()) {
  113. // It must be before the center.
  114. return find_arc(begin, center, arc);
  115. } else if ((*center)->get_sort() < arc->get_sort()) {
  116. // It must be after the center.
  117. return find_arc(center + 1, end, arc);
  118. } else {
  119. // The center's sort matches the arc's sort. It could be either
  120. // before or after the center. First try after.
  121. Iterator i = center;
  122. while (i < end && (*i)->get_sort() == arc->get_sort()) {
  123. if ((*i) == arc) {
  124. return i;
  125. }
  126. ++i;
  127. }
  128. // No, try before.
  129. i = center;
  130. --i;
  131. while (i >= begin && (*i)->get_sort() == arc->get_sort()) {
  132. if ((*i) == arc) {
  133. return i;
  134. }
  135. --i;
  136. }
  137. // No such arc!
  138. return end;
  139. }
  140. }
  141. ////////////////////////////////////////////////////////////////////
  142. // Function: internal_insert_arc
  143. // Description: A local template function that inserts the arc into
  144. // its appropriate place in the list and returns true if
  145. // successful, false if there was some kind of error.
  146. ////////////////////////////////////////////////////////////////////
  147. template<class ArcList>
  148. static bool
  149. internal_insert_arc(ArcList &alist, NodeRelation *arc) {
  150. nassertr(arc != (NodeRelation *)NULL, false);
  151. TYPENAME ArcList::iterator position =
  152. find_insert_position(alist.begin(), alist.end(), arc);
  153. nassertr(position >= alist.begin() && position <= alist.end(), false);
  154. /*
  155. if (graph_cat.is_debug()) {
  156. if (position == alist.end()) {
  157. graph_cat.debug()
  158. << "Inserting " << *arc << " at end\n";
  159. } else {
  160. graph_cat.debug()
  161. << "Inserting " << *arc << " before " << *(*position) << "\n";
  162. }
  163. }
  164. */
  165. alist.insert(position, arc);
  166. verify_arc_list(alist.begin(), alist.end());
  167. return true;
  168. }
  169. ////////////////////////////////////////////////////////////////////
  170. // Function: internal_remove_arc
  171. // Description: A local template function that removes the arc from
  172. // its place in the list and returns true if successful,
  173. // false if there was some kind of error.
  174. ////////////////////////////////////////////////////////////////////
  175. template<class ArcList>
  176. static bool
  177. internal_remove_arc(ArcList &alist, NodeRelation *arc) {
  178. nassertr(arc != (NodeRelation *)NULL, false);
  179. TYPENAME ArcList::iterator position =
  180. find_arc(alist.begin(), alist.end(), arc);
  181. nassertr(position >= alist.begin() && position <= alist.end(), false);
  182. nassertr(position != alist.end(), false);
  183. /*
  184. if (graph_cat.is_debug()) {
  185. TYPENAME ArcList::iterator next = position + 1;
  186. if (next == list.end()) {
  187. graph_cat.debug()
  188. << "Removing " << *arc << " from end\n";
  189. } else {
  190. graph_cat.debug()
  191. << "Removing " << *arc << " from before " << *(*next) << "\n";
  192. }
  193. }
  194. */
  195. alist.erase(position);
  196. verify_arc_list(alist.begin(), alist.end());
  197. return true;
  198. }
  199. ////////////////////////////////////////////////////////////////////
  200. // Function: NodeRelation::Copy Constructor
  201. // Access: Private
  202. // Description: It's not legal to copy a NodeRelation.
  203. ////////////////////////////////////////////////////////////////////
  204. NodeRelation::
  205. NodeRelation(const NodeRelation &) {
  206. graph_cat.error()
  207. << "NodeRelation copy constructor called!\n";
  208. }
  209. ////////////////////////////////////////////////////////////////////
  210. // Function: NodeRelation::Copy Assignment Operator
  211. // Access: Private
  212. // Description: It's not legal to copy a NodeRelation.
  213. ////////////////////////////////////////////////////////////////////
  214. void NodeRelation::
  215. operator = (const NodeRelation &) {
  216. graph_cat.error()
  217. << "NodeRelation copy assignment operator called!\n";
  218. }
  219. ////////////////////////////////////////////////////////////////////
  220. // Function: NodeRelation::Destructor
  221. // Access: Public, Virtual
  222. // Description:
  223. ////////////////////////////////////////////////////////////////////
  224. NodeRelation::
  225. ~NodeRelation() {
  226. // An attached arc should never be deleted. If this assertion
  227. // fails, it's most likely that someone attempted to explicitly
  228. // delete an arc. You should use remove_arc() instead.
  229. nassertv(!_attached);
  230. _transitions.remove_all_from_arc(this);
  231. }
  232. ////////////////////////////////////////////////////////////////////
  233. // Function: NodeRelation::output
  234. // Access: Public
  235. // Description: Writes a brief description of the arc to the
  236. // indicated output stream. This function is called by
  237. // the << operator.
  238. ////////////////////////////////////////////////////////////////////
  239. void NodeRelation::
  240. output(ostream &out) const {
  241. if (_parent == (Node*)NULL) {
  242. out << "(null)";
  243. } else {
  244. out << *_parent;
  245. }
  246. out << " -> ";
  247. if (_child == (Node*)NULL) {
  248. out << "(null)";
  249. } else {
  250. out << *_child;
  251. }
  252. if (!_attached) {
  253. out << " (unattached)";
  254. }
  255. }
  256. ////////////////////////////////////////////////////////////////////
  257. // Function: NodeRelation::copy_transitions_from
  258. // Access: Public
  259. // Description: Copies all of the transitions stored on the other arc
  260. // to this arc. Any existing transitions on this arc,
  261. // for which there was not a corresponding transition of
  262. // the same type on the other arc, are left undisturbed.
  263. ////////////////////////////////////////////////////////////////////
  264. void NodeRelation::
  265. copy_transitions_from(const NodeRelation *arc) {
  266. copy_transitions_from(arc->_transitions);
  267. }
  268. ////////////////////////////////////////////////////////////////////
  269. // Function: NodeRelation::compose_transitions_from
  270. // Access: Public
  271. // Description: Similar to copy_transitions_from(), except that if
  272. // the same type of transition exists on both arcs, the
  273. // composition of the two is stored. The result
  274. // represents the same set of transitions that would
  275. // result from composing the two individual sets of
  276. // transitions.
  277. ////////////////////////////////////////////////////////////////////
  278. void NodeRelation::
  279. compose_transitions_from(const NodeRelation *arc) {
  280. compose_transitions_from(arc->_transitions);
  281. }
  282. ////////////////////////////////////////////////////////////////////
  283. // Function: NodeRelation::copy_transitions_from
  284. // Access: Public
  285. // Description: Copies all of the transitions stored in the indicated
  286. // set to this arc. Any existing transitions on this
  287. // arc, for which there was not a corresponding
  288. // transition of the same type on the other arc, are
  289. // left undisturbed.
  290. ////////////////////////////////////////////////////////////////////
  291. void NodeRelation::
  292. copy_transitions_from(const NodeTransitions &trans) {
  293. if (!trans.is_empty()) {
  294. _transitions.copy_transitions_from(trans, this);
  295. // Now mark that *all* transitions have changed, even though many
  296. // of them might not have, because we're not really sure.
  297. _net_transitions.clear();
  298. NodeTransitions::const_iterator ti;
  299. for (ti = _transitions.begin(); ti != _transitions.end(); ++ti) {
  300. changed_transition((*ti).first);
  301. }
  302. }
  303. }
  304. ////////////////////////////////////////////////////////////////////
  305. // Function: NodeRelation::compose_transitions_from
  306. // Access: Public
  307. // Description: Similar to copy_transitions_from(), except that if
  308. // the same type of transition exists in both places,
  309. // the composition of the two is stored. The result
  310. // represents the same set of transitions that would
  311. // result from composing the two individual sets of
  312. // transitions.
  313. ////////////////////////////////////////////////////////////////////
  314. void NodeRelation::
  315. compose_transitions_from(const NodeTransitions &trans) {
  316. if (!trans.is_empty()) {
  317. _transitions.compose_transitions_from(trans, this);
  318. // Now mark that *all* transitions have changed, even though many
  319. // of them might not have, because we're not really sure.
  320. _net_transitions.clear();
  321. NodeTransitions::const_iterator ti;
  322. for (ti = _transitions.begin(); ti != _transitions.end(); ++ti) {
  323. changed_transition((*ti).first);
  324. }
  325. }
  326. }
  327. ////////////////////////////////////////////////////////////////////
  328. // Function: NodeRelation::sub_render_trans
  329. // Access: Public
  330. // Description: Calls sub_render() on each transition assigned to the
  331. // arc. Returns true if all transitions returned true,
  332. // false if any returned false.
  333. ////////////////////////////////////////////////////////////////////
  334. bool NodeRelation::
  335. sub_render_trans(const AllAttributesWrapper &attrib,
  336. AllTransitionsWrapper &trans,
  337. GraphicsStateGuardianBase *gsgbase) {
  338. bool all_true = true;
  339. NodeTransitions::const_iterator ti;
  340. for (ti = _transitions.begin(); ti != _transitions.end(); ++ti) {
  341. if (!(*ti).second->sub_render(this, attrib, trans, gsgbase)) {
  342. all_true = false;
  343. }
  344. }
  345. return all_true;
  346. }
  347. ////////////////////////////////////////////////////////////////////
  348. // Function: NodeRelation::has_sub_render_trans
  349. // Access: Public
  350. // Description: Returns true if any transition on the arc has a
  351. // sub_render() function.
  352. ////////////////////////////////////////////////////////////////////
  353. bool NodeRelation::
  354. has_sub_render_trans() const {
  355. NodeTransitions::const_iterator ti;
  356. for (ti = _transitions.begin(); ti != _transitions.end(); ++ti) {
  357. if ((*ti).second->has_sub_render()) {
  358. return true;
  359. }
  360. }
  361. return false;
  362. }
  363. ////////////////////////////////////////////////////////////////////
  364. // Function: NodeRelation::make_arc
  365. // Access: Public, Static
  366. // Description: This function is passed to the Factory to make a new
  367. // NodeRelation by type. Don't try to call this
  368. // function directly.
  369. ////////////////////////////////////////////////////////////////////
  370. NodeRelation *NodeRelation::
  371. make_arc(const FactoryParams &) {
  372. return new NodeRelation(NodeRelation::get_class_type());
  373. }
  374. ////////////////////////////////////////////////////////////////////
  375. // Function: NodeRelation::attach
  376. // Access: Protected
  377. // Description: Makes the arc an official part of the graph by
  378. // informing the nodes that it connects of its
  379. // existence. It is an error to attach an arc that has
  380. // already been attached.
  381. //
  382. // It is also an error to attach an arc that is not
  383. // grounded at both ends.
  384. ////////////////////////////////////////////////////////////////////
  385. void NodeRelation::
  386. attach() {
  387. nassertv(_parent != (Node*)NULL);
  388. nassertv(_child != (Node*)NULL);
  389. nassertv(!_attached);
  390. _attached = true;
  391. bool inserted_one = internal_insert_arc(_parent->_children[_type], this);
  392. bool inserted_two = internal_insert_arc(_child->_parents[_type], this);
  393. nassertv(inserted_one && inserted_two);
  394. // Blow out the cache and increment the current update sequence.
  395. _net_transitions.clear();
  396. ++last_graph_update[_type];
  397. _parent->force_bound_stale();
  398. mark_bound_stale();
  399. }
  400. ////////////////////////////////////////////////////////////////////
  401. // Function: NodeRelation::detach
  402. // Access: Protected
  403. // Description: Removes the arc from the graph. The arc remains and
  404. // still refers to its connected nodes, but the nodes
  405. // themselves no longer know about the arc. It is an
  406. // error to detach an arc that is not already attached.
  407. //
  408. // detach() returns a PointerTo for the arc itself.
  409. // This is useful not so much for the return value
  410. // itself, but more to prevent the arc from destructing
  411. // until detach() returns, since the arc will destruct
  412. // when its last reference count is removed, and it is
  413. // generally a bad idea to destruct a class within its
  414. // own method.
  415. ////////////////////////////////////////////////////////////////////
  416. PT(NodeRelation) NodeRelation::
  417. detach() {
  418. PT(NodeRelation) result = this;
  419. nassertr(_parent != (Node*)NULL, result);
  420. nassertr(_child != (Node*)NULL, result);
  421. nassertr(_attached, result);
  422. force_bound_stale();
  423. bool removed_one = internal_remove_arc(_parent->_children[_type], this);
  424. bool removed_two = internal_remove_arc(_child->_parents[_type], this);
  425. nassertr(removed_one, result);
  426. nassertr(removed_two, result);
  427. _attached = false;
  428. // Blow out the cache and increment the current update sequence.
  429. _net_transitions.clear();
  430. ++last_graph_update[_type];
  431. return result;
  432. }
  433. ////////////////////////////////////////////////////////////////////
  434. // Function: NodeRelation::detach_below
  435. // Access: Protected
  436. // Description: This is a special method that is only called from the
  437. // Node destructor. It detaches the arc, but does not
  438. // remove it from its parent's arc list, which is
  439. // presumably about to be destroyed anyway.
  440. ////////////////////////////////////////////////////////////////////
  441. PT(NodeRelation) NodeRelation::
  442. detach_below() {
  443. PT(NodeRelation) result = this;
  444. nassertr(_parent != (Node*)NULL, result);
  445. nassertr(_child != (Node*)NULL, result);
  446. nassertr(_attached, result);
  447. force_bound_stale();
  448. bool removed = internal_remove_arc(_child->_parents[_type], this);
  449. nassertr(removed, result);
  450. _attached = false;
  451. // Blow out the cache and increment the current update sequence.
  452. _net_transitions.clear();
  453. ++last_graph_update[_type];
  454. return result;
  455. }
  456. ////////////////////////////////////////////////////////////////////
  457. // Function: NodeRelation::changed_transition
  458. // Access: Public, Virtual
  459. // Description: This is called by set_transition() or
  460. // clear_transition() whenever a transition is added,
  461. // updated, or removed from the arc. It is just a
  462. // callback to the arc so it can decide whether it needs
  463. // to update any internal data as a response to this
  464. // adjustment (for instance, by marking the bounding
  465. // sphere stale).
  466. ////////////////////////////////////////////////////////////////////
  467. void NodeRelation::
  468. changed_transition(TypeHandle trans_type) {
  469. if (_net_transitions != (NodeTransitionCache *)NULL) {
  470. _net_transitions->clear_transition(trans_type);
  471. }
  472. last_graph_update[get_type()]++;
  473. }
  474. ////////////////////////////////////////////////////////////////////
  475. // Function: NodeRelation::propagate_stale_bound
  476. // Access: Protected, Virtual
  477. // Description: Called by BoundedObject::mark_bound_stale(), this
  478. // should make sure that all bounding volumes that
  479. // depend on this one are marked stale also.
  480. ////////////////////////////////////////////////////////////////////
  481. void NodeRelation::
  482. propagate_stale_bound() {
  483. // Mark all of our parent arcs stale as well.
  484. Node *node = _parent;
  485. nassertv(node != (Node*)NULL);
  486. UpRelations::const_iterator uri;
  487. uri = node->_parents.find(get_type());
  488. if (uri != node->_parents.end()) {
  489. const UpRelationPointers &urp = (*uri).second;
  490. UpRelationPointers::const_iterator urpi;
  491. for (urpi = urp.begin(); urpi != urp.end(); ++urpi) {
  492. (*urpi)->mark_bound_stale();
  493. }
  494. }
  495. }
  496. ////////////////////////////////////////////////////////////////////
  497. // Function: NodeRelation::recompute_bound
  498. // Access: Protected, Virtual
  499. // Description: Recomputes the dynamic bounding volume for this arc
  500. // (and all of its descendants).
  501. ////////////////////////////////////////////////////////////////////
  502. void NodeRelation::
  503. recompute_bound() {
  504. // First, get ourselves a fresh, empty bounding volume.
  505. BoundedObject::recompute_bound();
  506. nassertv(_bound != (BoundingVolume*)NULL);
  507. // Now actually compute the bounding volume by putting it around all
  508. // of our child bounding volumes.
  509. vector<const BoundingVolume *> child_volumes;
  510. Node *node = _child;
  511. nassertv(node != (Node*)NULL);
  512. child_volumes.push_back(&node->get_bound());
  513. DownRelations::const_iterator dri;
  514. dri = node->_children.find(get_type());
  515. if (dri != node->_children.end()) {
  516. const DownRelationPointers &drp = (*dri).second;
  517. DownRelationPointers::const_iterator drpi;
  518. for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
  519. child_volumes.push_back(&(*drpi)->get_bound());
  520. }
  521. }
  522. bool success =
  523. _bound->around(child_volumes.begin(), child_volumes.end());
  524. #ifndef NDEBUG
  525. if (!success) {
  526. graph_cat.error()
  527. << "Unable to recompute bounding volume for " << *this << ":\n"
  528. << "Cannot put " << _bound->get_type() << " around:\n";
  529. for (int i = 0; i < (int)child_volumes.size(); i++) {
  530. graph_cat.error(false)
  531. << " " << *child_volumes[i] << "\n";
  532. }
  533. }
  534. #endif
  535. }
  536. ////////////////////////////////////////////////////////////////////
  537. // Function: NodeRelation::write_datagram
  538. // Access: Public
  539. // Description: Function to write the important information in
  540. // the particular object to a Datagram
  541. ////////////////////////////////////////////////////////////////////
  542. void NodeRelation::
  543. write_datagram(BamWriter *manager, Datagram &me)
  544. {
  545. //Write out the "dynamic" type
  546. manager->write_handle(me, _type);
  547. //We should always be attached if we are trying to write out
  548. nassertv(_attached);
  549. //Neither the Child nor the Parent should be NULL
  550. nassertv(get_parent() != Node::Null && get_child() != Node::Null);
  551. //Write out the pointer to my parent
  552. manager->write_pointer(me, _parent);
  553. //Write out the pointer to my child
  554. manager->write_pointer(me, _child);
  555. //Write out the sort relation for this object
  556. me.add_uint16(_sort);
  557. //Now write out all the Transitions on this arc
  558. me.add_uint16(_transitions.size());
  559. NodeTransitions::iterator ci;
  560. for(ci = _transitions.begin(); ci != _transitions.end(); ci++)
  561. {
  562. manager->write_pointer(me, (*ci).second);
  563. }
  564. }
  565. ////////////////////////////////////////////////////////////////////
  566. // Function: NodeRelation::complete_pointers
  567. // Access: Public
  568. // Description: Takes in a vector of pointes to TypedWriteable
  569. // objects that correspond to all the requests for
  570. // pointers that this object made to BamReader.
  571. ////////////////////////////////////////////////////////////////////
  572. int NodeRelation::
  573. complete_pointers(vector_typedWriteable &plist, BamReader*)
  574. {
  575. nassertr(plist[0] != TypedWriteable::Null &&
  576. plist[1] != TypedWriteable::Null, 0);
  577. _parent = DCAST(Node, plist[0]);
  578. _child = DCAST(Node, plist[1]);
  579. //Let attach do the work of connecting to the
  580. //parent and child nodes, and telling them about
  581. //myself
  582. attach();
  583. //The rest of this is the list of Transitions
  584. for(int i = 2; i < _num_transitions + 2; i++)
  585. {
  586. //Ignore Null pointers. This SHOULD mean that
  587. //we have received a Transition that the current
  588. //version doesn't know about, so we want to be able
  589. //to gracefully handle new functionality being thrown
  590. //at old code
  591. if (plist[i] == TypedWriteable::Null)
  592. {
  593. graph_cat->warning() << get_type().get_name()
  594. << "Ignoring null Transition" << endl;
  595. }
  596. else
  597. {
  598. //Let set_transition do the work for storing
  599. //a reference to this transition, determing it's
  600. //exact type, telling the transition about me, etc...
  601. set_transition(DCAST(NodeTransition, plist[i]));
  602. }
  603. }
  604. return _num_transitions+2;
  605. }
  606. ////////////////////////////////////////////////////////////////////
  607. // Function: NodeRelation::make_NodeRelation
  608. // Access: Protected
  609. // Description: Factory method to generate a NodeRelation object
  610. ////////////////////////////////////////////////////////////////////
  611. TypedWriteable* NodeRelation::
  612. make_NodeRelation(const FactoryParams &params)
  613. {
  614. NodeRelation *me = new NodeRelation;
  615. BamReader *manager;
  616. Datagram packet;
  617. parse_params(params, manager, packet);
  618. DatagramIterator scan(packet);
  619. me->fillin(scan, manager);
  620. return me;
  621. }
  622. ////////////////////////////////////////////////////////////////////
  623. // Function: NodeRelation::fillin
  624. // Access: Protected
  625. // Description: Function that reads out of the datagram (or asks
  626. // manager to read) all of the data that is needed to
  627. // re-create this object and stores it in the appropiate
  628. // place
  629. ////////////////////////////////////////////////////////////////////
  630. void NodeRelation::
  631. fillin(DatagramIterator& scan, BamReader* manager)
  632. {
  633. _type = manager->read_handle(scan);
  634. //Read in my parent
  635. manager->read_pointer(scan, this);
  636. //Read in my child
  637. manager->read_pointer(scan, this);
  638. //Get my sort relation
  639. _sort = scan.get_uint16();
  640. //Now read in all of my transitions
  641. _num_transitions = scan.get_uint16();
  642. for(int i = 0; i < _num_transitions; i++)
  643. {
  644. manager->read_pointer(scan, this);
  645. }
  646. }
  647. ////////////////////////////////////////////////////////////////////
  648. // Function: NodeRelation::register_with_factory
  649. // Access: Public, Static
  650. // Description: Factory method to generate a NodeRelation object
  651. ////////////////////////////////////////////////////////////////////
  652. void NodeRelation::
  653. register_with_read_factory(void)
  654. {
  655. BamReader::get_factory()->register_factory(get_class_type(), make_NodeRelation);
  656. }