Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/track_manager.cc @ 4172

Last change on this file since 4172 was 4166, checked in by bensch, 20 years ago

orxonox/trunk: resourceManager has some new functions

File size: 30.6 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#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_TRACK_MANAGER
17
18#include "track_manager.h"
19
20#include "base_object.h"
21#include "p_node.h"
22#include "track_node.h"
23#include "stdincl.h"
24#include "list.h"
25#include "text_engine.h"
26#include "t_animation.h"
27
28#include <stdarg.h>
29
30using namespace std;
31
32/**
33   \brief initializes a TrackElement (sets the default values)
34*/
35TrackElement::TrackElement(void)
36{
37  this->isFresh = true;
38  this->isHotPoint = false;
39  this->isSavePoint = false;
40  this->isFork = false;
41  this->isJoined = false;
42  this->mainJoin = false;
43  this->ID = -1;
44  this->startingTime = 0;
45  this->duration = TMAN_DEFAULT_DURATION;
46  this->endTime = 1;
47  this->jumpTime = 0;
48  this->width = TMAN_DEFAULT_WIDTH;
49  this->nodeCount = 0;
50  this->curve = NULL;
51  this->childCount = 0;
52  this->children = NULL;
53  this->name = NULL;
54
55  this->history = NULL;
56
57  this->subject = NULL;
58  this->condFunc = &TrackElement::random;
59}
60
61/**
62    \brief destroys all alocated memory)
63    \todo eventually when deleting a TrackElement you would not like to delete all its preceding TrackElements
64*/
65TrackElement::~TrackElement(void)
66{
67  // deleting the Name
68  delete []name;
69  // deleting the Curve
70  delete this->curve;
71
72  // deleting all the Children of this TrackNode.
73  if ((!this->isJoined &&this->childCount > 0) 
74      || (this->isJoined && this->mainJoin)) // only if this is the MainJoin.
75    {
76      tIterator<TrackElement>* iterator = this->children->getIterator();
77      TrackElement* enumElem = iterator->nextElement();
78      while (enumElem)
79        {
80          delete enumElem;
81          enumElem = iterator->nextElement();
82        }
83      delete iterator;
84      delete this->children;
85    }
86}
87
88/**
89   \brief Searches through all the TrackElements for trackID.
90   \param trackID The ID to search for.
91   \returns The TrackElement if Found, NULL otherwise.
92*/
93TrackElement* TrackElement::findByID(unsigned int trackID)
94{
95  // return if Found.
96  if (this->ID == trackID)
97    return this;
98  // search all children
99  if (this->childCount > 0)
100    {
101      tIterator<TrackElement>* iterator = this->children->getIterator();
102      TrackElement* enumElem = iterator->nextElement();
103      TrackElement* tmpElem;
104      while (enumElem)
105        {
106          if ((tmpElem = enumElem->findByID(trackID)))
107            return tmpElem;
108          enumElem = iterator->nextElement();
109        }
110      delete iterator;
111    }
112  // if not found
113  return NULL;
114}
115
116
117/**
118   \brief Searches through all the TrackElements for a trackName
119   \param trackName The name to search for.
120   \returns The TrackElement if Found, NULL otherwise.
121*/
122TrackElement* TrackElement::findByName(const char* trackName)
123{
124  // return if Found.
125  if (this->name && !strcmp(this->name, trackName))
126    return this;
127  // search all children
128  if (this->childCount > 0)
129    {
130      tIterator<TrackElement>* iterator = this->children->getIterator();
131      TrackElement* enumElem = iterator->nextElement();
132      TrackElement* tmpElem;
133      while (enumElem)
134        {
135          if ((tmpElem = enumElem->findByName(trackName)))
136            return tmpElem;
137          enumElem = iterator->nextElement();
138        }
139      delete iterator;
140    }
141  // if not found
142  return NULL;
143}
144
145/**
146   \brief checks if there are any BackLoops in the Track (Backloops only
147   \param trackElem the trackElement to check about
148   \returns true if NO loop was found, false Otherwise
149   You actually have to act on false!!
150   it simply does this by looking if the current trackElem is found again somewhere else in the Track
151*/
152bool TrackElement::backLoopCheck(const TrackElement* trackElem, unsigned int depth) const
153{
154  if(depth == 0 || this != trackElem)
155    {
156      if (this->children)
157        {
158          tIterator<TrackElement>* iterator = this->children->getIterator();
159          TrackElement* enumElem = iterator->nextElement();
160          while (enumElem)
161            {
162              if(!enumElem->backLoopCheck(trackElem, depth + 1))
163                return false;
164              enumElem = iterator->nextElement();
165            }
166          delete iterator;
167        }
168    }
169  else
170    return false;
171
172  // only returns if everything worked out
173  return true;
174}
175
176/**
177   \param childNumber which child to return
178   \returns the n-the children (starting at 0).
179   Be aware, that when the trackElement has no Children, NULL will be returned
180*/
181TrackElement* TrackElement::getChild(int childCount) const
182{
183  // if the the trackElement has no children return NULL.
184  if (this->childCount == 0)
185    return NULL;
186  // we cannot return the childCount+m's Child, so we return the last.
187  if (childCount > this->childCount)
188    childCount = this->childCount;
189 
190  tIterator<TrackElement>* iterator = this->children->getIterator();
191  TrackElement* enumElem = iterator->nextElement();
192  for (int i = 0; i < childCount; i++)
193    enumElem = iterator->nextElement();
194  delete iterator;
195  return enumElem;
196}
197
198/**
199   \param name the Name to set.
200*/
201void TrackElement::setName(const char* name)
202{
203  //  delete the old name
204  if (this->name)
205    delete []this->name;
206  // if a name was given.
207  if (name)
208    {
209      this->name = new char[strlen(name)+1];
210      strcpy(this->name, name);
211    }
212  else 
213    this->name = NULL;
214}
215
216/**
217   \returns The name of this TrackElement
218*/
219const char* TrackElement::getName(void) const
220{
221  return this->name;
222}
223
224/**
225   \brief prints out debug information about this TrackElement
226*/
227void TrackElement::debug(void) const
228{
229  PRINT(0)("--== TrackElement:%i ==--", this->ID);
230  if(this->getName())
231    PRINT(0)("--++Name: %s++--", this->getName());
232  if(this->isFresh)
233    PRINT(0)("  -- has not jet eddited in any way --\n");
234  PRINT(0)("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", this->startingTime, this->endTime, this->duration, this->jumpTime);
235  PRINT(0)("   consists of %d Points\n", this->nodeCount);
236  if (this->childCount == 0)
237    PRINT(0)("   has no child\n");
238  else if (this->childCount == 1)
239    PRINT(0)("   has 1 child: =%d=\n", this->getChild(0)->ID);
240  else if (this->childCount > 1)
241    {
242      PRINT(0)("   has %d children: ", this->childCount);
243      //TrackElement* enumElem = this->children->enumerate();
244      tIterator<TrackElement>* iterator = this->children->getIterator();
245      TrackElement* enumElem = iterator->nextElement();
246      while (enumElem)
247        {
248          PRINT(0)("=%d= ", enumElem->ID);
249          enumElem = iterator->nextElement();
250        }
251      delete iterator;
252      PRINT(0)("\n");
253    }
254 
255  if(this->isHotPoint)
256    PRINT(0)("   is a special Point:\n");
257  if(this->isSavePoint)
258    PRINT(0)("    is a SavePoint\n");
259  if(this->isFork)
260    {
261      PRINT(0)("    is A Fork with with %d children.\n", this->childCount);
262    }
263  if(this->isJoined)
264    PRINT(0)("   is Joined at the End\n");
265 
266  if(!this->backLoopCheck(this)) /* this should not happen */
267    PRINT(2)(" THERE IS A BACKLOOP TO THIS ELEMENT\n");
268}
269
270/**
271   \brief CONDITION that chooses the first child for the decision (static)
272   \param nothing Nothing in this function
273   \returns the chosen child
274*/
275int TrackElement::lowest(const void* nothing) const
276{
277  return 0;
278}
279
280/**
281   \brief CONDITION that chooses the last child for the decision (static)
282   \param nothing Nothing in this function
283   \returns the chosen child
284*/
285int TrackElement::highest(const void* nothing) const
286{ 
287  return this->childCount-1;
288}
289
290/**
291   \brief CONDITION that chooses a random child for the decision (static)
292   \param nothing Nothing in this function
293   \returns the chosen child
294*/
295int TrackElement::random(const void* nothing) const
296{
297  int i = (int)floor ((float)rand()/(float)RAND_MAX * (float)this->childCount);
298  if (i >= this->childCount)
299    return this->childCount-1;
300  else 
301    return i;
302}
303
304/**
305   \brief CONDITION that chooses child 0, if the node(probably Player)
306   is left of its parent (z<0)) and 1/right otherwise.
307   \param node The node to act upon.
308   \returns the chosen child
309*/
310int TrackElement::leftRight(const void* node) const
311{
312  PNode* tmpNode = (PNode*)node;
313
314  if (tmpNode->getRelCoor().z < 0)
315    return 0;
316  else 
317    return 1;
318}
319
320
321/**
322   \brief CONDITION that chooses the child, that has the nearest distance to the node (probably player).
323   \param node The node to act upon.
324   \returns the chosen child
325
326   This is rather dangerous, because one must carefully set the points on the curve.
327   The best Way is to set the nodes as wide away of each other as possible,
328   but take into consideration, that if the nodes are to far from a center node, the center will be chosen.
329   (play with this!!).
330*/
331int TrackElement::nearest(const void* node) const
332{
333  PNode* tmpNode = (PNode*)node;
334
335  Vector nodeRelCoord = tmpNode->getRelCoor();
336  float minDist = 100000000;
337  int childNumber = 0;
338  int i = 0;
339
340  //TrackElement* enumElem = this->children->enumerate();
341  tIterator<TrackElement>* iterator = this->children->getIterator();
342  TrackElement* enumElem = iterator->nextElement();
343  while (enumElem)
344    {
345      float dist = (nodeRelCoord - enumElem->curve->getNode(4)).len();
346      if (dist < minDist)
347        {
348          minDist = dist;
349          childNumber = i;
350        }
351      i++;
352      enumElem = iterator->nextElement();
353    }
354  delete iterator;
355
356  PRINTF(4)("PathDecision with nearest algorithm: %d\n", childNumber);
357  return childNumber;
358}
359
360
361////////////////////////
362///// TRACKMANAGER /////
363////////////////////////
364/**
365   \brief standard constructor
366
367*/
368TrackManager::TrackManager(void)
369{
370  this->setClassName("TrackManager");
371 
372  TrackManager::singletonRef = this; // do this because otherwise the TrackNode cannot get The instance of the TrackManager
373
374  PRINTF(3)("Initializing the TrackManager\n");
375  // setting up the First TrackElement
376  this->firstTrackElem = new TrackElement();
377  this->firstTrackElem->ID = 1;
378  this->firstTrackElem->setName("root");
379
380  this->currentTrackElem = firstTrackElem;
381
382  this->curveType = CURVE_BEZIER;
383  this->localTime = 0;
384  this->maxTime = 0;
385  this->trackElemCount = 1;
386
387  this->trackNode = new TrackNode();
388  this->setBindSlave(this->trackNode);
389  // initializing the Text
390  this->trackText = TextEngine::getInstance()->createText("fonts/earth.ttf", 30, TEXT_DYNAMIC, 0, 255, 0);
391  this->trackText->setAlignment(TEXT_ALIGN_SCREEN_CENTER);
392  // initializing the Animation for the Text.
393  this->textAnimation = new tAnimation<Text>(this->trackText, &Text::setBlending);
394  this->textAnimation->addKeyFrame(1.0, 3.0, ANIM_NEG_EXP);
395  this->textAnimation->addKeyFrame(0.0, .001);
396  this->textAnimation->setInfinity(ANIM_INF_CONSTANT);
397}
398
399
400/**
401   \brief loads a trackElement from a TiXmlElement
402   \param root the TiXmlElement to load the Data from
403
404*/
405bool TrackManager::load( TiXmlElement* root)
406{
407
408}
409
410
411
412/**
413   \brief standard destructor
414*/
415TrackManager::~TrackManager(void)
416{
417  PRINTF(3)("Destruct TrackManager\n");
418
419  PRINTF(4)("Deleting all the TrackElements\n");
420  delete this->firstTrackElem;
421
422  // the tracknode should be deleted here, but is deleted by pNode: -> null_parent
423
424  // we do not have a TrackManager anymore
425  TrackManager::singletonRef = NULL;
426}
427
428//! Singleton Reference to TrackManager
429TrackManager* TrackManager::singletonRef = NULL;
430
431/**
432   \returns The reference on the TrackManager.
433
434   If the TrackManager does not exist, it will be created.
435*/
436TrackManager* TrackManager::getInstance(void) 
437{
438  if (!TrackManager::singletonRef)
439    TrackManager::singletonRef = new TrackManager();
440  return TrackManager::singletonRef;
441}
442
443
444// INITIALIZE //
445/**
446   \brief reserves Space for childCount children
447   \param childCount The Count of children to make space for.
448   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
449*/
450void TrackManager::initChildren(unsigned int childCount, TrackElement* trackElem)
451{
452  if (!trackElem)
453    trackElem = this->currentTrackElem;
454
455  trackElem->childCount = childCount;
456  trackElem->mainJoin = true;  // this tells join, that this one is the Main Join, if it tries to join multiple Tracks
457  trackElem->children =  new tList<TrackElement>();
458  for (int i = 0; i < childCount; i++)
459    {
460      // create a new Element
461      TrackElement* newElem = new TrackElement();
462      // setting up the new ID
463      newElem->ID = ++trackElemCount;
464      // setting up the Time
465      newElem->startingTime = trackElem->endTime + trackElem->jumpTime;
466      // adds the conection Point
467      this->addPoint(trackElem->curve->getNode(trackElem->curve->getNodeCount()),
468                     newElem);
469      // add the new child to the childList.
470      trackElem->children->add(newElem);
471    }
472
473  // setting the Name of the new TrackElement to the name of the last one + _childI
474
475  if (trackElem->getName())
476    {
477      for (int i = 0; i < trackElem->childCount; i++)
478      {
479        char* childName = new char[strlen(trackElem->getName())+10];
480        sprintf(childName, "%s_child%d", trackElem->getName(), i);
481        trackElem->getChild(i)->setName(childName);
482      }
483    }
484  // select the first Child to work on.
485  this->currentTrackElem = trackElem->getChild(0);
486}
487
488
489/**
490   \brief Sets the trackID we are working on.
491   \param trackID the trackID we are working on
492*/
493void TrackManager::workOn(unsigned int trackID)
494{
495  TrackElement* tmpElem = this->firstTrackElem->findByID(trackID);
496  if (tmpElem)
497    this->currentTrackElem = tmpElem;
498  else
499    PRINTF(2)("TrackElement %d not Found, leaving unchanged\n", trackID);
500  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
501}
502
503/**
504   \brief Sets the TrackElement to work on
505   \param trackName the Name of the Track to work on
506*/
507void TrackManager::workOn(const char* trackName)
508{
509  TrackElement* tmpElem = this->firstTrackElem->findByName(trackName);
510  if (tmpElem)
511    this->currentTrackElem = tmpElem;
512  else
513    PRINTF(2)("TrackElement %s not Found, leaving unchanged\n", trackName);
514  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
515}
516
517/**
518   \brief Sets the Type of the Curve
519   \param curveType The Type to set
520   \param trackElem the TrackElement that should get a new Curve.
521
522   \brief this will possibly get obsolete during the process.
523*/
524void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
525{
526  if (!trackElem->isFresh)
527    {
528      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
529      return;
530    }
531  this->curveType = curveType;
532  switch (curveType)
533    {
534    case CURVE_BEZIER:
535      trackElem->curve = new BezierCurve();
536      break;
537    }
538}
539
540/**
541   \brief Sets the duration of the current path in seconds.
542   \param duration The duration in seconds.
543   \param trackElem The TrackElement to apply this to.
544*/
545void TrackManager::setDuration(float duration, TrackElement* trackElem)
546{
547  if (!trackElem)
548    trackElem = this->currentTrackElem;
549
550  trackElem->duration = duration;
551  trackElem->endTime = trackElem->startingTime + duration;
552}
553
554/**
555   \brief adds a point to trackElem
556   \param newPoint The point to add.
557   \param trackElem The TrackElement to add the Point to
558*/
559bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
560{
561  if (!trackElem)
562    trackElem = this->currentTrackElem;
563
564  if (trackElem->isFresh)
565    {
566      this->setCurveType(TMAN_DEFAULT_CURVETYPE, trackElem);
567      trackElem->isFresh = false;
568    }
569  trackElem->curve->addNode(newPoint);
570  trackElem->nodeCount++;
571}
572
573/**
574   \brief adds save/splitpoint.
575   \param newPoint The point to add.
576   \returns A Pointer to a newly appended Curve
577*/
578int TrackManager::addHotPoint(Vector newPoint, TrackElement* trackElem)
579{
580  if (!trackElem)
581    trackElem = this->currentTrackElem;
582
583  PRINTF(4)("setting up a HotPoint\n");
584  if (trackElem->isFresh)
585    {
586      trackElem->isFresh = false;
587    }
588
589  // \todo HotPoint Handling.
590  trackElem->curve->addNode(newPoint);
591  trackElem->nodeCount++;
592  this->initChildren(1, trackElem);
593}
594
595/**
596   \brief Sets the last HotPoint into a savePoint.
597   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
598   \returns A Pointer to a newly appended Curve
599
600   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
601   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
602*/
603int TrackManager::setSavePoint(TrackElement* trackElem)
604{
605  if (!trackElem)
606    trackElem = this->currentTrackElem;
607
608  PRINTF(4)("setting up a SavePoint.\n");
609  if (trackElem->isFork || trackElem->isSavePoint)
610    {
611      PRINTF(2)("%d is already finished \n", trackElem->ID);
612      return trackElem->getChild(0)->ID;
613    }
614  trackElem->isSavePoint = true;
615  trackElem->isHotPoint = true;
616
617  this->initChildren(1, trackElem);
618}
619
620/**
621   \brief adds some interessting non-linear movments through the level.
622   \param count The Count of childrens the current HotPoint will have.
623
624   If no HotPoint was defined the last added Point will be rendered into a fork. \n
625   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
626*/
627void TrackManager::fork(unsigned int count, ...)
628{
629  int* trackIDs = new int[count];
630  this->forkV(count, trackIDs);
631  va_list ID;
632  va_start (ID, count);
633  for(int i = 0; i < count; i++)
634    {
635      *va_arg (ID, int*) = trackIDs[i];
636    }
637  va_end(ID); 
638  delete []trackIDs;
639}
640
641/**
642   \brief adds some interessting non-linear movments through the level.
643   \param count The Count of childrens the current HotPoint will have.
644   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
645   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
646   \see TrackManager::fork(unsigned int count, ...)
647*/
648void TrackManager::forkV(unsigned int count, int* trackIDs, TrackElement* trackElem)
649{
650  if (!trackElem)
651    trackElem = this->currentTrackElem;
652
653  PRINTF(4)("Forking with %d children\n", count);
654  if (trackElem->isSavePoint)
655    return;
656  trackElem->isFork = true;
657  trackElem->isHotPoint = true;
658  for(int i = 0; i < count; i++)
659    trackIDs[i]=this->trackElemCount+1+i;
660  this->initChildren(count, trackElem);
661}
662
663/**
664   \brief decides under what condition a certain Path will be chosen.
665   \param trackID the trackID to apply this to.
666   \param cond the CONDITION of the decision
667   \param subject the Subject that will be decided upon with CONDITION cond.
668*/
669void TrackManager::condition(unsigned int trackID, CONDITION cond, void* subject)
670{
671  this->condition(cond, subject, this->firstTrackElem->findByID(trackID));
672}
673
674/**
675   \brief decides under what condition a certain Path will be chosen.
676   \param cond the CONDITION of the decision
677   \param subject the Subject that will be decided upon with CONDITION cond.
678   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
679*/
680void TrackManager::condition(CONDITION cond, void* subject, TrackElement* trackElem)
681{
682  if (!trackElem)
683    trackElem = this->currentTrackElem;
684
685  if (!trackElem->isFork)
686    {
687      PRINTF(2)("%d is not a Fork, and no condition can be set in this case\n", trackElem->ID);
688      return;
689    }
690  else
691    {
692      switch (cond)
693        {
694        case LOWEST:
695          trackElem->condFunc = &TrackElement::lowest;
696          break;
697        case HIGHEST:
698          trackElem->condFunc = &TrackElement::highest;
699          break;
700        case RANDOM: 
701          trackElem->condFunc = &TrackElement::random;
702          break;
703        case LEFTRIGHT:
704          trackElem->condFunc = &TrackElement::leftRight;
705          break;
706        case NEAREST:
707          trackElem->condFunc = &TrackElement::nearest;
708          break;
709        case ENEMYKILLED:
710          break;
711        }
712      trackElem->subject=subject;
713    }
714}
715
716/**
717   \brief joins some tracks together again.
718   \param count The count of Paths to join.
719
720   Join will set the localTime to the longest time a Path has to get to this Point. \n
721   Join will join all curves to the first curve, meaning that all the tangents will be matched.
722*/
723void TrackManager::join(unsigned int count, ...)
724{
725  int* trackIDs = new int [count];
726  va_list ID;
727  va_start (ID, count);
728  for(int i = 0; i < count; i++)
729    {
730      trackIDs[i] = va_arg (ID, int);
731    }
732  va_end(ID);
733  this->joinV(count, trackIDs);
734  delete []trackIDs;
735}
736
737/**
738   \brief Joins some Tracks together again.
739   \param count The count of trackElements to join
740
741   \see void TrackManager::join(unsigned int count, ...)
742   The difference to void TrackManager::join(unsigned int count, ...) is, that this function takes
743   the Names of the TrackElements as inputs and not their ID
744*/
745void TrackManager::joinc(unsigned int count, ...)
746{
747  int* trackIDs = new int [count];
748  va_list NAME;
749  va_start (NAME, count);
750  for(int i = 0; i < count; i++)
751    {
752      char* name = va_arg (NAME, char*);
753      TrackElement* tmpElem = this->firstTrackElem->findByName(name);
754      if (tmpElem)
755        trackIDs[i] = tmpElem->ID;
756      else
757        PRINTF(1)("Trying to join a Track, of which the name does not exist: %s\n", name);
758    }
759  va_end(NAME);
760  this->joinV(count, trackIDs);
761  delete []trackIDs;
762}
763
764
765/**
766   \brief joins some tracks together again.
767   \param count The count of Paths to join.
768   \param trackIDs an Array with the trackID's to join
769
770   \see void TrackManager::join(unsigned int count, ...)
771*/
772void TrackManager::joinV(unsigned int count, int* trackIDs)
773{
774  TrackElement* tmpTrackElem;
775  TrackElement* tmpJoinElem;
776  for (int i = 0; i < count; i++)
777    if (!this->firstTrackElem->findByID(trackIDs[i]))
778      {
779        PRINTF(1)("Error trying to Connect Paths that do not exist yet: %d\n Not Joining Anything", trackIDs[i]);
780        return;
781      }
782                 
783
784  PRINTF(3)("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
785
786  // checking if there is a back-loop-connection and ERROR if it is.
787  tmpTrackElem = this->firstTrackElem->findByID(trackIDs[0]);
788  if (!tmpTrackElem->backLoopCheck(tmpTrackElem))
789    {
790      PRINTF(2)("Backloop connection detected at joining trackElements\n -> TRACK WILL NOT BE JOINED\n");
791      return;
792    }
793
794  TrackElement* firstJoint =   this->firstTrackElem->findByID(trackIDs[0]);
795  float tmpLatestTime = firstJoint->endTime;
796
797  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
798  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
799  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
800  firstJoint->isJoined = true;
801  //  firstJoint->mainJoin = true;
802  if(!firstJoint->isHotPoint)
803    this->setSavePoint(firstJoint);
804  // Timing:
805  for (int i = 0; i < count; i++)
806    {
807      if(tmpJoinElem = this->firstTrackElem->findByID(trackIDs[i]))
808        {
809          if (tmpJoinElem->childCount == 0
810              && tmpJoinElem->endTime > tmpLatestTime)
811            tmpLatestTime = tmpJoinElem->endTime;
812        }
813    }
814  // time the main Join.
815  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
816 
817  // Joining:
818  for (int i = 1; i < count; i++)
819    {
820      if( tmpJoinElem = this->firstTrackElem->findByID(trackIDs[i]))
821        {
822          if (tmpJoinElem->childCount > 0)
823            printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
824          else
825            {
826              this->addPoint(tmpc2Point, tmpJoinElem);
827              this->addPoint(tmpTangentPoint, tmpJoinElem);
828              this->addPoint(tmpEndPoint, tmpJoinElem);
829              // time all other Joins
830              tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
831             
832              //Copying Joint-Info
833              tmpJoinElem->children = firstJoint->children;
834              tmpJoinElem->childCount = firstJoint->childCount;
835              tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
836              tmpJoinElem->isFork = firstJoint->isFork;
837             
838              tmpJoinElem->isJoined = true;
839            }
840        }
841    }
842  if(firstJoint->children)
843    {
844      //TrackElement* enumElem = firstJoint->children->enumerate();
845      tIterator<TrackElement>* iterator = firstJoint->children->getIterator();
846      TrackElement* enumElem = iterator->nextElement();
847      while (enumElem)
848        {
849          PRINTF(5)("Setting startingTime of %d to %f.\n", enumElem->ID, tmpLatestTime);
850          enumElem->startingTime = tmpLatestTime;
851          enumElem->endTime = tmpLatestTime + enumElem->duration;
852         
853          enumElem = iterator->nextElement();
854        }
855      delete iterator;
856    }
857}
858
859/**
860   \brief finalizes the TrackSystem. after this it will not be editable anymore
861
862   \todo check for any inconsistencies, output errors
863*/
864void TrackManager::finalize(void)
865{
866  for (int i = 1; i<= trackElemCount ;i++)
867    {
868      TrackElement* tmpElem = this->firstTrackElem->findByID(i);
869      if( tmpElem->childCount > 0 && tmpElem->mainJoin)
870        {
871          tIterator<TrackElement>* iterator = tmpElem->children->getIterator();
872          TrackElement* enumElem = iterator->nextElement();
873          //TrackElement* enumElem = tmpElem->children->enumerate();
874          while (enumElem)
875            {
876             
877              // c1-continuity
878              enumElem->curve->addNode(enumElem->curve->getNode(0) +
879                                                   ((enumElem->curve->getNode(0) - 
880                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
881                                                    ),2);
882              enumElem->nodeCount++;
883              // c2-continuity
884              enumElem->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
885                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
886                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
887              enumElem->nodeCount++;                                               
888              PRINTF(5)("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
889                     tmpElem->ID, tmpElem->nodeCount,
890                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
891                     enumElem->ID, enumElem->nodeCount,
892                     enumElem->curve->calcAcc(0).x, enumElem->curve->calcAcc(0).y, enumElem->curve->calcAcc(0).z);
893             
894              enumElem = iterator->nextElement();
895            }
896          delete iterator;
897        }
898    }
899  for (int i = 1; i <= trackElemCount;i++)
900    if (this->firstTrackElem->findByID(i)->endTime > this->maxTime)
901      this->maxTime = this->firstTrackElem->findByID(i)->endTime; // very bad implemented :/
902}
903
904
905// RUNTIME //
906
907/**
908   \brief calculates the Position for the localTime of the Track.
909   \returns the calculated Position
910*/
911Vector TrackManager::calcPos() const
912{
913  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
914}
915
916/**
917   \brief calculates the Rotation for the localTime of the Track.
918   \returns the calculated Rotation
919*/
920Vector TrackManager::calcDir() const
921{
922  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
923}
924
925/**
926   \returns the current Width of the track
927*/
928float TrackManager::getWidth(void) const
929{
930  return this->currentTrackElem->width;
931}
932
933/**
934   \brief Advances the local-time of the Track around dt
935   \param dt The time about which to advance.
936
937   This function also checks, if the TrackElement has to be changed.
938*/
939void TrackManager::tick(float dt)
940{
941  dt /= 1000;
942  PRINTF(4)("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
943  if (this->localTime <= this->firstTrackElem->duration)
944    this->jumpTo(this->localTime);
945  if (this->localTime <= this->maxTime)
946    this->localTime += dt;
947  if (this->localTime > this->currentTrackElem->endTime
948      && this->currentTrackElem->children)
949    {
950      if (this->currentTrackElem->jumpTime != 0.0)
951        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
952      // jump to the next TrackElement and also set the history of the new Element to the old one.
953      TrackElement* tmpHistoryElem = this->currentTrackElem;
954      this->currentTrackElem = this->currentTrackElem->getChild(this->choosePath(this->currentTrackElem));
955      this->currentTrackElem->history = tmpHistoryElem;
956      if (this->currentTrackElem->getName())
957        {
958          this->trackText->setText(this->currentTrackElem->getName());
959          this->textAnimation->replay();
960        }
961    }
962  if (this->bindSlave)
963    {
964      Vector tmp = this->calcPos();
965      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)); 
966
967      Vector v(0.0, 1.0, 0.0);
968      Quaternion q(-PI/2, v);
969      quat = quat * q;
970
971      this->bindSlave->setAbsCoor(tmp);
972      this->bindSlave->setAbsDir(quat);
973    }
974}
975
976/**
977   \brief Jumps to a certain point on the Track.
978   \param time The time on the Track to jump to.
979
980   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.)
981   Max is trackLengthMax.
982*/
983void TrackManager::jumpTo(float time)
984{
985  if (time == 0)
986    {
987      this->currentTrackElem = this->firstTrackElem;
988      if (this->currentTrackElem->getName())
989        {
990          this->trackText->setText(this->currentTrackElem->getName());
991          this->textAnimation->play();
992        }
993    }
994  this->localTime = time;
995}
996
997/**
998   \brief a Function that decides which Path we should follow.
999   \param trackElem The Path to choose.
1000   
1001*/
1002int TrackManager::choosePath(TrackElement* trackElem)
1003{
1004  return (trackElem->*(trackElem->condFunc))(trackElem->subject);
1005}
1006
1007/**
1008   \brief Sets the PNode, that should be moved along the Tack
1009   \param bindSlave the PNode to set
1010*/
1011void TrackManager::setBindSlave(PNode* bindSlave)
1012{
1013  this->bindSlave = bindSlave;
1014}
1015
1016/**
1017   \returns the main TrackNode
1018*/
1019PNode* TrackManager::getTrackNode(void)
1020{
1021  return this->trackNode;
1022}
1023
1024// DEBUG //
1025
1026/**
1027   \brief Imports a model of the Graph into the OpenGL-environment.
1028   \param dt The Iterator used in seconds for Painting the Graph.
1029
1030   This is for testing facility only. Do this if you want to see the Path inside the Level.
1031   eventually this will all be packed into a gl-list.
1032*/
1033void TrackManager::drawGraph(float dt) const
1034{
1035  for (int i = 1; i <= trackElemCount; i++)
1036    {
1037      glBegin(GL_LINE_STRIP);
1038      TrackElement* tmpElem = this->firstTrackElem->findByID(i);
1039      if (tmpElem->curve)
1040        for(float f = 0.0; f < 1.0; f+=dt)
1041          {
1042            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
1043            Vector tmpVector = tmpElem->curve->calcPos(f);
1044            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
1045          }
1046      glEnd();
1047    }
1048}
1049
1050/**
1051   \brief outputs debug information about the trackManager
1052   \param level how much debug
1053*/
1054void TrackManager::debug(unsigned int level) const
1055{
1056  PRINT(0)("=========================================\n");
1057  PRINT(0)("= CLASS TRACKMANAGER::debug information =\n");
1058  PRINT(0)("=========================================\n");
1059  //  PRINT(0)("Status is: %
1060  PRINT(0)(" Consists of %d elements\n", this->trackElemCount);
1061  PRINT(0)(" localTime is: %f\n", this->localTime);
1062  if (level >= 2)
1063    {
1064      for (int i = 1; i <= trackElemCount; i++)
1065        {
1066          TrackElement* tmpElem = this->firstTrackElem->findByID(i);
1067          tmpElem->debug();
1068        }
1069    }
1070  PRINT(0)("-----------------------------------------\n");
1071}
Note: See TracBrowser for help on using the repository browser.