Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/trackManager/src/track_manager.cc @ 3515

Last change on this file since 3515 was 3515, checked in by bensch, 19 years ago

orxonox/branches/trackManager: now ability to set LEFT-RIGHT decision for nodes

File size: 21.4 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16
17#include "track_manager.h"
18
19#include "p_node.h"
20
21#include <stdarg.h>
22#include "p_node.h"
23
24using namespace std;
25
26/**
27   \brief initializes a TrackElement (sets the default values)
28*/
29TrackElement::TrackElement(void)
30{
31  this->isFresh = true;
32  this->isHotPoint = false;
33  this->isSavePoint = false;
34  this->isFork = false;
35  this->isJoined = false;
36  this->mainJoin = false;
37  this->cond; //!< todo think!!
38  this->ID = -1;
39  this->startingTime = 0; //!< \todo eventually set this to the max time of TrackManager.
40  this->duration = 1;
41  this->endTime = 1;
42  this->jumpTime = 0;
43  this->curveType = BEZIERCURVE;
44  this->nodeCount = 0;
45  this->childCount = 0;
46  this->name = NULL;
47  this->curve = NULL;
48  this->children = NULL;
49  this->condFunc = &TrackElement::random;
50}
51
52/**
53    \brief destroys all alocated memory)
54    \todo eventually when deleting a TrackElement you would not like to delete all its preceding TrackElements
55*/
56TrackElement::~TrackElement(void)
57{
58  if (this->name)
59    delete []name;
60  if (this->curve)
61    delete this->curve;
62  if ((!this->isJoined &&this->childCount > 0) || (this->isJoined && this->mainJoin))
63    {
64      for (int i=0; i < this->childCount; i++)
65        delete this->children[i];
66      delete this->children;
67    }
68}
69
70/**
71   \brief Searches through all the TrackElements for trackID.
72   \param trackID The ID to search for.
73   \returns The TrackElement if Found, NULL otherwise.
74   
75   \todo make this more modular, to search for different things
76*/
77TrackElement* TrackElement::findByID(unsigned int trackID)
78{
79  // return if Found.
80  if (this->ID == trackID)
81    return this;
82  // search on.
83  if (this->childCount > 0)
84    for (int i=0; i < this->childCount; i++)
85      {
86        TrackElement* tmpElem;
87        if ((tmpElem = this->children[i]->findByID(trackID)))
88          return tmpElem;
89      }
90  else return NULL;
91}
92
93
94/**
95   \brief checks if there are any BackLoops in the Track
96   \param trackElem the trackElement to check about
97   it simply does this by looking if the current trackElem is found again somewhere else in the Track
98*/
99bool TrackElement::backLoopCheck(TrackElement* trackElem)
100{
101  if (this->childCount == 0)
102    return true;
103  else
104    {
105      for (int i = 0; i < this->childCount; i++)
106        if(!this->children[i]->backLoopCheck(trackElem))
107          return false;
108     
109      return true;
110    }
111}
112
113int TrackElement::lowest(void* nothing)
114{
115  return 0;
116}
117
118int TrackElement::highest(void* nothing)
119{ 
120  return this->childCount-1;
121}
122
123int TrackElement::random(void* nothing)
124{
125  int i = (int)floor ((float)rand()/(float)RAND_MAX * (float)this->childCount);
126  if (i >= this->childCount)
127    return this->childCount-1;
128  else 
129    return i;
130}
131
132
133int TrackElement::leftRight(void* node)
134{
135  PNode* tmpNode = (PNode*)node;
136
137  if (tmpNode->relCoordinate.z < 0)
138    return 0;
139  else 
140    return 1;
141}
142
143
144// todo
145int TrackElement::nearest(void* node)
146{
147  PNode* tmpNode = (PNode*)node;
148
149  Vector nodeRelCoord = tmpNode->relCoordinate;
150
151  if (nodeRelCoord.z < 0)
152    return 0;
153  else 
154    return 1;
155}
156
157
158
159/////////////////////////////////////
160///// TRACKMANAGER //////////////////
161/////////////////////////////////////
162/**
163   \brief standard constructor
164
165*/
166TrackManager::TrackManager(void)
167{
168  this->setClassName ("TrackManager");
169
170  PRINTF(3)("Initializing the TrackManager\n");
171  this->firstTrackElem = new TrackElement();
172  this->firstTrackElem->ID = 1;
173  this->currentTrackElem = firstTrackElem;
174  this->localTime = 0;
175  this->maxTime = 0;
176  this->trackElemCount = 1;
177  this->bindSlave = NULL;
178}
179
180
181/**
182   \brief standard destructor
183
184*/
185TrackManager::~TrackManager(void)
186{
187  PRINTF(3)("Destruct TrackManager\n");
188
189  PRINTF(3)("Deleting all the TrackElements\n");
190  delete this->firstTrackElem;
191
192  // we do not have a TrackManager anymore
193  singletonRef = NULL;
194}
195
196TrackManager* TrackManager::singletonRef = NULL;
197
198/**
199   \returns The reference on the TrackManager.
200
201   If the TrackManager does not exist, it will be created.
202*/
203TrackManager* TrackManager::getInstance(void) 
204{
205  if (TrackManager::singletonRef)
206    return TrackManager::singletonRef;
207  else
208    return TrackManager::singletonRef = new TrackManager();
209}
210
211/**
212   \brief reserves Space for childCount children
213   \param childCount The Count of children to make space for.
214*/
215void TrackManager::initChildren(unsigned int childCount)
216{
217  this->currentTrackElem->childCount = childCount;
218  this->currentTrackElem->mainJoin = true;
219  this->currentTrackElem->children = new TrackElement*[childCount];
220  for (int i=0; i<childCount; i++)
221    {
222      this->currentTrackElem->children[i] = new TrackElement();
223      this->currentTrackElem->children[i]->ID = ++trackElemCount;
224      this->currentTrackElem->children[i]->startingTime = this->currentTrackElem->endTime + this->currentTrackElem->jumpTime;
225      this->addPoint(this->currentTrackElem->curve->getNode(this->currentTrackElem->curve->getNodeCount()), this->currentTrackElem->children[i]);
226    }
227}
228
229/**
230   \brief Searches for a given trackID.
231   \param trackID the trackID to search for.
232   \returns The TrackElement #trackID if found, NULL otherwise.
233*/
234TrackElement* TrackManager::findTrackElementByID(unsigned int trackID) const
235{
236  return firstTrackElem->findByID(trackID);
237}
238
239// INITIALIZE //
240
241/**
242   \brief Sets the trackID we are working on.
243   \param trackID the trackID we are working on
244*/
245void TrackManager::workOn(unsigned int trackID)
246{
247  TrackElement* tmpElem = findTrackElementByID(trackID);
248  if (tmpElem)
249    this->currentTrackElem = tmpElem;
250  else
251    printf("TrackElement not Found, leaving unchanged\n");
252  printf("now Working on %d\n", this->currentTrackElem->ID);
253
254}
255
256/**
257   \brief Sets the Type of the Curve
258   \brief curveType The Type to set
259*/
260void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
261{
262  if (!trackElem->isFresh)
263    {
264      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
265      return;
266    }
267  trackElem->curveType = curveType;
268  switch (curveType)
269    {
270    case BEZIERCURVE:
271      trackElem->curve = new BezierCurve();
272      break;
273    case UPOINTCURVE:
274      trackElem->curve = new UPointCurve();
275      break;
276    }
277}
278
279/**
280   \brief Sets the duration of the current path in seconds.
281   \param time The duration in seconds.
282*/
283
284void TrackManager::setDuration(float time)
285{
286  this->currentTrackElem->duration = time;
287  this->currentTrackElem->endTime = this->currentTrackElem->startingTime + time;
288}
289
290/**
291   \brief adds a point to the current TrackElement
292   \param newPoint The point to add.
293*/
294bool TrackManager::addPoint(Vector newPoint)
295{
296  return this->addPoint(newPoint, this->currentTrackElem);
297}
298
299/**
300   \brief adds a point to trackElem
301   \param newPoint The point to add.
302   \param trackElem The TrackElement to add the Point to
303*/
304bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
305{
306  if (trackElem->isFresh)
307    {
308      this->setCurveType(BEZIERCURVE, trackElem);
309      trackElem->isFresh = false;
310    }
311  trackElem->curve->addNode(newPoint);
312  trackElem->nodeCount++;
313}
314
315/**
316   \brief adds save/splitpoint.
317   \param newPoint The point to add.
318   \returns A Pointer to a newly appended Curve
319*/
320int TrackManager::addHotPoint(Vector newPoint)
321{
322  printf("setting up a HotPoint\n");
323  if (this->currentTrackElem->isFresh)
324    {
325      this->setCurveType(BEZIERCURVE);
326      this->currentTrackElem->isFresh = false;
327    }
328
329  // \todo HotPoint Handling.
330  this->currentTrackElem->curve->addNode(newPoint);
331  this->currentTrackElem->nodeCount++;
332  this->initChildren(1);
333  this->currentTrackElem = this->currentTrackElem->children[0];
334}
335
336/**
337   \brief Sets the last HotPoint into a savePoint.
338   \returns A Pointer to a newly appended Curve
339   
340   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
341   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
342*/
343int TrackManager::setSavePoint(void)
344{
345  printf("setting up a SavePoint.\n");
346  if (this->currentTrackElem->isFork || this->currentTrackElem->isSavePoint)
347    return this->currentTrackElem->children[1]->ID;
348  this->currentTrackElem->isSavePoint = true;
349  this->currentTrackElem->isHotPoint = true;
350
351  this->initChildren(1);
352  this->currentTrackElem = this->currentTrackElem->children[0];
353}
354
355/**
356   \brief adds some interessting non-linear movments through the level.
357   \param count The Count of childrens the current HotPoint will have.
358
359   If no HotPoint was defined the last added Point will be rendered into a fork. \n
360   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
361*/
362void TrackManager::fork(unsigned int count, ...)
363{
364  int* trackIDs = new int[count];
365  this->forkV(count, trackIDs);
366  va_list ID;
367  va_start (ID, count);
368  for(int i = 0; i < count; i++)
369    {
370      *va_arg (ID, int*) = trackIDs[i];
371    }
372  va_end(ID); 
373  delete []trackIDs;
374}
375
376/**
377   \brief adds some interessting non-linear movments through the level.
378   \param count The Count of childrens the current HotPoint will have.
379   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
380
381   \see void TrackManager::fork(int count, ...)
382
383   \todo initialisation is wrong!! also in setSavePoint.
384*/
385void TrackManager::forkV(unsigned int count, int* trackIDs)
386{
387  printf("Forking with %d children\n", count);
388  if (this->currentTrackElem->isSavePoint)
389    return;
390  this->currentTrackElem->isFork = true;
391  this->currentTrackElem->isHotPoint = true;
392  for(int i = 0; i < count; i++)
393    trackIDs[i]=this->trackElemCount+1+i;
394  this->initChildren(count);
395}
396
397/**
398   \brief decides under what condition a certain Path will be chosen.
399   \param cond the CONDITION of the decision
400   \param subject the Subject that will be decided upon with CONDITION cond.
401*/
402void TrackManager::condition(CONDITION cond, void* subject)
403{
404  this->condition(this->currentTrackElem->ID, cond, subject);
405}
406/**
407   \brief decides under what condition a certain Path will be chosen.
408   \param groupID the ID on which to choose the preceding move
409   \param cond the CONDITION of the decision
410   \param subject the Subject that will be decided upon with CONDITION cond.
411*/
412void TrackManager::condition(unsigned int groupID, CONDITION cond, void* subject)
413{
414  TrackElement* tmpElem = this->findTrackElementByID(groupID);
415 
416  switch (cond)
417    {
418    case LOWEST:
419      tmpElem->condFunc = &TrackElement::lowest;
420      break;
421    case HIGHEST:
422      tmpElem->condFunc = &TrackElement::highest;
423      break;
424    case RANDOM: 
425      tmpElem->condFunc = &TrackElement::random;
426      break;
427    case LEFTRIGHT:
428      tmpElem->condFunc = &TrackElement::leftRight;
429      break;
430    case NEAREST:
431      tmpElem->condFunc = &TrackElement::nearest;
432      break;
433    case ENEMYKILLED:
434      break;
435    default: // same as LOWEST
436      tmpElem->condFunc = &TrackElement::lowest;
437      break;
438    }
439  tmpElem->subject=subject;
440}
441
442
443/**
444   \brief joins some tracks together again.
445   \param count The count of Paths to join.
446
447   Join will set the localTime to the longest time a Path has to get to this Point. \n
448   Join will join all curves to the first curve, meaning that all the tangents will be matched.
449*/
450void TrackManager::join(unsigned int count, ...)
451{
452  int* trackIDs = new int [count];
453  va_list ID;
454  va_start (ID, count);
455  for(int i = 0; i < count; i++)
456    {
457      trackIDs[i] = va_arg (ID, int);
458    }
459  va_end(ID);
460  this->joinV(count, trackIDs);
461  delete []trackIDs;
462}
463
464/**
465   \brief joins some tracks together again.
466   \param count The count of Paths to join.
467   \param trackIDs an Array with the trackID's to join
468
469   \see void TrackManager::join(int count, ...)
470*/
471void TrackManager::joinV(unsigned int count, int* trackIDs)
472{
473  printf("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
474
475  // checking if there is a back-loop-connection and ERROR if it is.
476  TrackElement* tmpTrackElem = this->findTrackElementByID(trackIDs[0]);
477  if (!tmpTrackElem->backLoopCheck(tmpTrackElem))
478    PRINTF(1)("Backloop connection detected at joining trackElements\n");
479
480  // chanching work-on to temporary value. going back at the end.
481  int tmpCurrentWorkingID = this->currentTrackElem->ID;
482  this->workOn(trackIDs[0]);
483  TrackElement* firstJoint = this->currentTrackElem;
484  float tmpLatestTime = firstJoint->endTime;
485
486  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
487  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
488  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
489  firstJoint->isJoined = true;
490  //  firstJoint->mainJoin = true;
491  if(!firstJoint->isHotPoint)
492    this->setSavePoint();
493  // Timing:
494  for (int i = 0; i < count; i++)
495    {
496      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
497      if (tmpJoinElem->childCount == 0
498          && tmpJoinElem->endTime > tmpLatestTime)
499        tmpLatestTime = tmpJoinElem->endTime;
500    }
501  // time the main Join.
502  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
503 
504  // Joining:
505  for (int i = 1; i < count; i++)
506    {
507      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
508      if (tmpJoinElem->childCount > 0)
509        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
510      else
511        {
512          this->addPoint(tmpc2Point, tmpJoinElem);
513          this->addPoint(tmpTangentPoint, tmpJoinElem);
514          this->addPoint(tmpEndPoint, tmpJoinElem);
515          // time all other Joins
516          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
517         
518          //Copying Joint-Info
519          tmpJoinElem->children = firstJoint->children;
520          tmpJoinElem->childCount = firstJoint->childCount;
521          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
522          tmpJoinElem->isFork = firstJoint->isFork;
523
524          tmpJoinElem->isJoined = true;
525        }
526    }
527  if(firstJoint->childCount > 0)
528    for(int i = 0; i < firstJoint->childCount; i++)
529      {
530        printf("Setting startingTime of %d to %f.\n", firstJoint->children[i]->ID, tmpLatestTime);
531        firstJoint->children[i]->startingTime = tmpLatestTime;
532        firstJoint->children[i]->endTime = tmpLatestTime+firstJoint->children[i]->duration;
533      } 
534
535  // returning to the TrackElement we were working on.
536  this->workOn(tmpCurrentWorkingID);
537}
538
539/**
540   \brief finalizes the TrackSystem. after this it will not be editable anymore
541
542   \todo check for any inconsistencies, output errors
543*/
544void TrackManager::finalize(void)
545{
546  for (int i = 1; i<= trackElemCount ;i++)
547    {
548      TrackElement* tmpElem = findTrackElementByID(i);
549      if (tmpElem->childCount>0 && tmpElem->mainJoin)
550        {
551          for (int j = 0; j < tmpElem->childCount; j++)
552            {
553             
554              // c1-continuity
555              tmpElem->children[j]->curve->addNode(tmpElem->children[j]->curve->getNode(0) +
556                                                   ((tmpElem->children[j]->curve->getNode(0) - 
557                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
558                                                    ),2);
559              tmpElem->children[j]->nodeCount++;
560              // c2-continuity
561              tmpElem->children[j]->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
562                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
563                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
564              tmpElem->children[j]->nodeCount++;                                                   
565              printf("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
566                     tmpElem->ID, tmpElem->nodeCount,
567                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
568                     tmpElem->children[j]->ID, tmpElem->children[j]->nodeCount,
569                     tmpElem->children[j]->curve->calcAcc(0).x, tmpElem->children[j]->curve->calcAcc(0).y, tmpElem->children[j]->curve->calcAcc(0).z);
570            }
571        }
572    }
573}
574
575
576// RUNTIME //
577
578/**
579   \brief calculates the Position for the localTime of the Track.
580   \returns the calculated Position
581*/
582Vector TrackManager::calcPos() const
583{
584  //  PRINTF(0)("TrackElement:%d, localTime: %f\n",this->currentTrackElem->ID, this->localTime);
585  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
586}
587
588/**
589   \brief calculates the Rotation for the localTime of the Track.
590   \returns the calculated Rotation
591*/
592Vector TrackManager::calcDir() const
593{
594  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
595}
596
597/**
598   \brief Advances the local-time of the Track around dt
599   \param dt The time about which to advance.
600
601   This function also checks, if the TrackElement has to be changed.
602*/
603void TrackManager::tick(float dt)
604{
605  dt /= 1000;
606  printf("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
607  if (this->localTime <= this->firstTrackElem->duration)
608    this->jumpTo(this->localTime);
609  this->localTime += dt;
610  if (this->localTime > this->currentTrackElem->endTime
611      && this->currentTrackElem->children)
612    {
613      if (this->currentTrackElem->jumpTime > 0)
614        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
615      this->currentTrackElem = this->currentTrackElem->children[this->choosePath(this->currentTrackElem)];
616    }
617  if (this->bindSlave)
618    {
619      Vector tmp = this->calcPos();
620      Quaternion quat = Quaternion(this->calcDir(), Vector(this->currentTrackElem->curve->calcAcc((localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration).x,1,this->currentTrackElem->curve->calcAcc((localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration).z)); 
621      this->bindSlave->setAbsCoor(&tmp);
622      this->bindSlave->setAbsDir(&quat);
623    }
624}
625
626/**
627   \brief Jumps to a certain point on the Track.
628   \param time The time on the Track to jump to.
629
630   This should be used to Jump backwards on a Track, because moving forward means to change between the Path. (it then tries to choose the default.)
631   Max is trackLengthMax.
632*/
633void TrackManager::jumpTo(float time)
634{
635  if (time == 0)
636    this->currentTrackElem = this->firstTrackElem;
637  this->localTime = time;
638}
639
640/**
641   \brief a Function that decides which Path we should follow.
642   \param trackElem The Path to choose.
643   
644*/
645int TrackManager::choosePath(TrackElement* trackElem)
646{
647  return (trackElem->*(trackElem->condFunc))(trackElem->subject);
648}
649
650/**
651   \brief Sets the PNode, that should be moved along the Tack
652   \param bindSlave the PNode to set
653*/
654void TrackManager::setBindSlave(PNode* bindSlave)
655{
656  if (!this->bindSlave)
657    this->bindSlave = bindSlave;
658}
659
660
661// DEBUG //
662
663/**
664   \brief Imports a model of the Graph into the OpenGL-environment.
665   \param dt The Iterator used in seconds for Painting the Graph.
666
667   This is for testing facility only. Do this if you want to see the Path inside the Level.
668   eventually this will all be packed into a gl-list.
669*/
670void TrackManager::drawGraph(float dt) const
671{
672
673  for (int i = 1; i <= trackElemCount; i++)
674    {
675      glBegin(GL_LINE_STRIP);
676      TrackElement* tmpElem = this->findTrackElementByID(i);
677      if (tmpElem->curve)
678        for(float f = 0.0; f < 1.0; f+=dt)
679          {
680            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
681            Vector tmpVector = tmpElem->curve->calcPos(f);
682            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
683          }
684  glEnd();
685    }
686}
687
688/**
689   \brief outputs debug information about the trackManager
690   \param level how much debug
691*/
692void TrackManager::debug(unsigned int level) const
693{
694  PRINT(0)("=========================================\n");
695  PRINT(0)("= CLASS TRACKMANAGER::debug information =\n");
696  PRINT(0)("=========================================\n");
697  //  PRINT(0)("Status is: %
698  PRINT(0)(" Consists of %d elements\n", this->trackElemCount);
699  PRINT(0)(" localTime is: %f\n", this->localTime);
700  if (level >= 2)
701    {
702      for (int i = 1; i <= trackElemCount; i++)
703        {
704          TrackElement* tmpElem = this->findTrackElementByID(i);
705          PRINT(0)("--== TrackElement:%i ==--", tmpElem->ID);
706          if(tmpElem->name)
707            PRINT(0)("Name: %s::", tmpElem->name);
708          if(tmpElem->isFresh)
709            PRINT(0)("  -- has not jet eddited in any way --\n");
710          PRINT(0)("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
711          PRINT(0)("   consists of %d Points\n", tmpElem->nodeCount);
712          if (tmpElem->childCount == 0)
713            PRINT(0)("   has no child\n");
714          else if (tmpElem->childCount == 1)
715            PRINT(0)("   has 1 child: =%d=\n", tmpElem->children[0]->ID);
716          else if (tmpElem->childCount > 1)
717            {
718              PRINT(0)("   has %d children: ", tmpElem->childCount);
719              for(int i = 0; i < tmpElem->childCount; i++)
720                PRINT(0)("=%d= ", tmpElem->children[i]->ID);
721              PRINT(0)("\n");
722            }
723
724          if(tmpElem->isHotPoint)
725            PRINT(0)("   is a special Point:\n");
726          if(tmpElem->isSavePoint)
727            PRINT(0)("    is a SavePoint\n");
728          if(tmpElem->isFork)
729            {
730              PRINT(0)("    is A Fork with with %d children.\n", tmpElem->childCount);
731            }
732          if(tmpElem->isJoined)
733            PRINT(0)("   is Joined at the End\n");
734
735          if(!tmpElem->backLoopCheck(tmpElem)) /* this should not happen */
736            PRINT(2)(" THERE IS A BACKLOOP TO THIS ELEMENT\n");
737        }
738    }
739  PRINT(0)("-----------------------------------------\n");
740}
Note: See TracBrowser for help on using the repository browser.