Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3881 was 3880, checked in by bensch, 20 years ago

orxonox/trunk: trackManager should not end up in a seg-fault anymore when findByID returns NULL

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