Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/levelloader/src/track_manager.cc @ 3536

Last change on this file since 3536 was 3530, checked in by chris, 20 years ago

orxonox/branches/levelloader: Got the system to compile, the basic backbone now runs. What remains to be done is implementing all necessary functions to load all vital classes into a world

File size: 23.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: Christian Meyer
14*/
15
16
17#include "track_manager.h"
18
19#include "p_node.h"
20#include "substring.h"
21
22#include <stdarg.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}
50
51/**
52    \brief destroys all alocated memory)
53    \todo eventually when deleting a TrackElement you would not like to delete all its preceding TrackElements
54*/
55TrackElement::~TrackElement(void)
56{
57  if (this->name)
58    delete []name;
59  if (this->curve)
60    delete this->curve;
61  if ((!this->isJoined &&this->childCount > 0) || (this->isJoined && this->mainJoin))
62    {
63      for (int i=0; i < this->childCount; i++)
64        delete this->children[i];
65      delete this->children;
66    }
67}
68
69/**
70   \brief Searches through all the TrackElements for trackID.
71   \param trackID The ID to search for.
72   \returns The TrackElement if Found, NULL otherwise.
73   
74   \todo make this more modular, to search for different things
75*/
76TrackElement* TrackElement::findByID(unsigned int trackID)
77{
78  // return if Found.
79  if (this->ID == trackID)
80    return this;
81  // search on.
82  if (this->childCount > 0)
83    for (int i=0; i < this->childCount; i++)
84      {
85        TrackElement* tmpElem;
86        if ((tmpElem = this->children[i]->findByID(trackID)))
87          return tmpElem;
88      }
89  else return NULL;
90}
91
92/**
93   \brief Sets the name of this TrackElement
94   \param trackName The new name for this element
95*/
96void TrackElement::setName(const char* trackName)
97{
98        if( this->name != NULL) delete this->name;
99       
100        this->name = new char[strlen(trackName) + 1];
101        strcpy( this->name, trackName);
102}
103
104/**
105   \brief Searches through all the TrackElements for trackName.
106   \param trackName The name to search for.
107   \returns The TrackElement if Found, NULL otherwise.
108   
109   \todo make this more modular, to search for different things
110*/
111TrackElement* TrackElement::findByName(const char* trackName)
112{
113  // return if Found.
114  if ( this->name != NULL && !strcmp( this->name, trackName))
115    return this;
116  // search on.
117  if (this->childCount > 0)
118    for (int i=0; i < this->childCount; i++)
119      {
120        TrackElement* tmpElem;
121        if ((tmpElem = this->children[i]->findByName(trackName)))
122          return tmpElem;
123      }
124  else return NULL;
125}
126
127
128
129
130/////////////////////////////////////
131///// TRACKMANAGER //////////////////
132/////////////////////////////////////
133/**
134   \brief standard constructor
135
136*/
137TrackManager::TrackManager(void)
138{
139  this->setClassName ("TrackManager");
140
141  PRINTF(3)("Initializing the TrackManager\n");
142  this->firstTrackElem = new TrackElement();
143  this->firstTrackElem->ID = 1;
144  this->currentTrackElem = firstTrackElem;
145  this->localTime = 0;
146  this->maxTime = 0;
147  this->trackElemCount = 1;
148  this->bindSlave = NULL;
149}
150
151
152/**
153   \brief standard destructor
154
155*/
156TrackManager::~TrackManager(void)
157{
158  PRINTF(3)("Destruct TrackManager\n");
159
160  PRINTF(3)("Deleting all the TrackElements\n");
161  delete this->firstTrackElem;
162  // delete this->name;
163
164  // we do not have a TrackManager anymore
165  singletonRef = NULL;
166}
167
168TrackManager* TrackManager::singletonRef = NULL;
169
170/**
171   \returns The reference on the TrackManager.
172
173   If the TrackManager does not exist, it will be created.
174*/
175TrackManager* TrackManager::getInstance(void) 
176{
177  if (singletonRef)
178    return singletonRef;
179  else
180    return singletonRef = new TrackManager();
181}
182
183/**
184   \brief reserves Space for childCount children
185   \param childCount The Count of children to make space for.
186*/
187void TrackManager::initChildren(unsigned int childCount, SubString* names)
188{
189  this->currentTrackElem->childCount = childCount;
190  this->currentTrackElem->mainJoin = true;
191  this->currentTrackElem->children = new TrackElement*[childCount];
192  for (int i=0; i<childCount; i++)
193    {
194        if( names != NULL)
195        {
196                if( this->findTrackElementByName( names->getString(i)))
197                {
198                        PRINTF(1)("Track name '%s' already taken", names->getString(i));
199                }
200            }
201               
202      this->currentTrackElem->children[i] = new TrackElement();
203      this->currentTrackElem->children[i]->ID = ++trackElemCount;
204      this->currentTrackElem->children[i]->startingTime = this->currentTrackElem->endTime + this->currentTrackElem->jumpTime;
205      this->addPoint(this->currentTrackElem->curve->getNode(this->currentTrackElem->curve->getNodeCount()), this->currentTrackElem->children[i]);
206    }
207}
208
209/**
210   \brief Searches for a given trackID.
211   \param trackID the trackID to search for.
212   \returns The TrackElement #trackID if found, NULL otherwise.
213*/
214TrackElement* TrackManager::findTrackElementByID(unsigned int trackID) const
215{
216  return firstTrackElem->findByID(trackID);
217}
218
219/**
220   \brief Searches for a given trackname.
221   \param trackName the trackName to search for.
222   \returns The TrackElement if found, NULL otherwise.
223*/
224TrackElement* TrackManager::findTrackElementByName(const char* trackName) const
225{
226  return firstTrackElem->findByName(trackName);
227}
228// INITIALIZE //
229
230/**
231   \brief Sets the trackID we are working on.
232   \param trackID the trackID we are working on
233*/
234void TrackManager::workOn(unsigned int trackID)
235{
236  TrackElement* tmpElem = findTrackElementByID(trackID);
237  if (tmpElem)
238    this->currentTrackElem = tmpElem;
239  else
240    printf("TrackElement not Found, leaving unchanged\n");
241  printf("now Working on %d\n", this->currentTrackElem->ID);
242
243}
244
245/**
246   \brief Sets the Type of the Curve
247   \brief curveType The Type to set
248*/
249void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
250{
251  if (!trackElem->isFresh)
252    {
253      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
254      return;
255    }
256  trackElem->curveType = curveType;
257  switch (curveType)
258    {
259    case BEZIERCURVE:
260      trackElem->curve = new BezierCurve();
261      break;
262    case UPOINTCURVE:
263      trackElem->curve = new UPointCurve();
264      break;
265    }
266}
267
268/**
269   \brief Sets the duration of the current path in seconds.
270   \param time The duration in seconds.
271*/
272
273void TrackManager::setDuration(float time)
274{
275  this->currentTrackElem->duration = time;
276  this->currentTrackElem->endTime = this->currentTrackElem->startingTime + time;
277}
278
279/**
280   \brief adds a point to the current TrackElement
281   \param newPoint The point to add.
282*/
283bool TrackManager::addPoint(Vector newPoint)
284{
285  return this->addPoint(newPoint, this->currentTrackElem);
286}
287
288/**
289   \brief adds a point to trackElem
290   \param newPoint The point to add.
291   \param trackElem The TrackElement to add the Point to
292*/
293bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
294{
295  if (trackElem->isFresh)
296    {
297      this->setCurveType(BEZIERCURVE, trackElem);
298      trackElem->isFresh = false;
299    }
300  trackElem->curve->addNode(newPoint);
301  trackElem->nodeCount++;
302}
303
304/**
305   \brief adds save/splitpoint.
306   \param newPoint The point to add.
307   \returns A Pointer to a newly appended Curve
308*/
309int TrackManager::addHotPoint(Vector newPoint)
310{
311  printf("setting up a HotPoint\n");
312  if (this->currentTrackElem->isFresh)
313    {
314      this->setCurveType(BEZIERCURVE);
315      this->currentTrackElem->isFresh = false;
316    }
317
318  // \todo HotPoint Handling.
319  this->currentTrackElem->curve->addNode(newPoint);
320  this->currentTrackElem->nodeCount++;
321  this->initChildren(1);
322  this->currentTrackElem = this->currentTrackElem->children[0];
323}
324
325/**
326   \brief Sets the last HotPoint into a savePoint.
327   \returns A Pointer to a newly appended Curve
328   
329   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
330   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
331*/
332int TrackManager::setSavePoint(void)
333{
334  printf("setting up a SavePoint.\n");
335  if (this->currentTrackElem->isFork || this->currentTrackElem->isSavePoint)
336    return this->currentTrackElem->children[1]->ID;
337  this->currentTrackElem->isSavePoint = true;
338  this->currentTrackElem->isHotPoint = true;
339
340  this->initChildren(1);
341  this->currentTrackElem = this->currentTrackElem->children[0];
342}
343
344/**
345   \brief adds some interessting non-linear movments through the level.
346   \param count The Count of childrens the current HotPoint will have.
347
348   If no HotPoint was defined the last added Point will be rendered into a fork. \n
349   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
350*/
351void TrackManager::fork(unsigned int count, ...)
352{
353  int* trackIDs = new int[count];
354  this->forkV(count, trackIDs);
355  va_list ID;
356  va_start (ID, count);
357  for(int i = 0; i < count; i++)
358    {
359      *va_arg (ID, int*) = trackIDs[i];
360    }
361  va_end(ID); 
362  delete []trackIDs;
363}
364
365/**
366   \brief adds some interessting non-linear movments through the level.
367   \param count The Count of childrens the current HotPoint will have.
368   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
369   \param names A SubString containing the trackNames for the new tracks, if NULL, no names will be assigned
370
371   \see void TrackManager::fork(int count, ...)
372
373   \todo initialisation is wrong!! also in setSavePoint.
374*/
375void TrackManager::forkV(unsigned int count, int* trackIDs, SubString* names)
376{
377  printf("Forking with %d children\n", count);
378  if (this->currentTrackElem->isSavePoint)
379    return;
380  this->currentTrackElem->isFork = true;
381  this->currentTrackElem->isHotPoint = true;
382  for(int i = 0; i < count; i++)
383    trackIDs[i]=this->trackElemCount+1+i;
384  this->initChildren(count, names);
385}
386
387/**
388   \brief decides under what condition a certain Path will be chosen.
389   \param groupID the ID on which to choose the preceding move
390   \param cond \todo think about this
391*/
392void TrackManager::condition(unsigned int groupID, PathCondition cond)
393{
394 
395}
396
397/**
398   \brief joins some tracks together again.
399   \param count The count of Paths to join.
400
401   Join will set the localTime to the longest time a Path has to get to this Point. \n
402   Join will join all curves to the first curve, meaning that all the tangents will be matched.
403*/
404void TrackManager::join(unsigned int count, ...)
405{
406  int* trackIDs = new int [count];
407  va_list ID;
408  va_start (ID, count);
409  for(int i = 0; i < count; i++)
410    {
411      trackIDs[i] = va_arg (ID, int);
412    }
413  va_end(ID);
414  this->joinV(count, trackIDs);
415  delete []trackIDs;
416}
417
418/**
419   \brief joins some tracks together again.
420   \param count The count of Paths to join.
421   \param trackIDs an Array with the trackID's to join
422
423   \see void TrackManager::join(int count, ...)
424*/
425void TrackManager::joinV(unsigned int count, int* trackIDs)
426{
427  printf("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
428
429  // chanching work-on to temporary value. going back at the end.
430  int tmpCurrentWorkingID = this->currentTrackElem->ID;
431  this->workOn(trackIDs[0]);
432  TrackElement* firstJoint = this->currentTrackElem;
433  float tmpLatestTime = firstJoint->endTime;
434
435  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
436  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
437  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
438  firstJoint->isJoined = true;
439  //  firstJoint->mainJoin = true;
440  if(!firstJoint->isHotPoint)
441    this->setSavePoint();
442  // Timing:
443  for (int i = 0; i < count; i++)
444    {
445      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
446      if (tmpJoinElem->childCount == 0
447          && tmpJoinElem->endTime > tmpLatestTime)
448        tmpLatestTime = tmpJoinElem->endTime;
449    }
450  // time the main Join.
451  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
452 
453  // Joining:
454  for (int i = 1; i < count; i++)
455    {
456      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
457      if (tmpJoinElem->childCount > 0)
458        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
459      else
460        {
461          this->addPoint(tmpc2Point, tmpJoinElem);
462          this->addPoint(tmpTangentPoint, tmpJoinElem);
463          this->addPoint(tmpEndPoint, tmpJoinElem);
464          // time all other Joins
465          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
466         
467          //Copying Joint-Info
468          tmpJoinElem->children = firstJoint->children;
469          tmpJoinElem->childCount = firstJoint->childCount;
470          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
471          tmpJoinElem->isFork = firstJoint->isFork;
472
473          tmpJoinElem->isJoined = true;
474        }
475    }
476  if(firstJoint->childCount > 0)
477    for(int i = 0; i < firstJoint->childCount; i++)
478      {
479        printf("Setting startingTime of %d to %f.\n", firstJoint->children[i]->ID, tmpLatestTime);
480        firstJoint->children[i]->startingTime = tmpLatestTime;
481        firstJoint->children[i]->endTime = tmpLatestTime+firstJoint->children[i]->duration;
482      } 
483
484  // returning to the TrackElement we were working on.
485  this->workOn(tmpCurrentWorkingID);
486}
487
488/**
489   \brief finalizes the TrackSystem. after this it will not be editable anymore
490
491   \todo check for any inconsistencies, output errors
492*/
493void TrackManager::finalize(void)
494{
495  for (int i = 1; i<= trackElemCount ;i++)
496    {
497      TrackElement* tmpElem = findTrackElementByID(i);
498      if (tmpElem->childCount>0 && tmpElem->mainJoin)
499        {
500          for (int j = 0; j < tmpElem->childCount; j++)
501            {
502             
503              // c1-continuity
504              tmpElem->children[j]->curve->addNode(tmpElem->children[j]->curve->getNode(0) +
505                                                   ((tmpElem->children[j]->curve->getNode(0) - 
506                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
507                                                    ),2);
508              tmpElem->children[j]->nodeCount++;
509              // c2-continuity
510              tmpElem->children[j]->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
511                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
512                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
513              tmpElem->children[j]->nodeCount++;                                                   
514              printf("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
515                     tmpElem->ID, tmpElem->nodeCount,
516                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
517                     tmpElem->children[j]->ID, tmpElem->children[j]->nodeCount,
518                     tmpElem->children[j]->curve->calcAcc(0).x, tmpElem->children[j]->curve->calcAcc(0).y, tmpElem->children[j]->curve->calcAcc(0).z);
519            }
520        }
521    }
522}
523
524
525// RUNTIME //
526
527/**
528   \brief calculates the Position for the localTime of the Track.
529   \returns the calculated Position
530*/
531Vector TrackManager::calcPos() const
532{
533  //  PRINTF(0)("TrackElement:%d, localTime: %f\n",this->currentTrackElem->ID, this->localTime);
534  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
535}
536
537/**
538   \brief calculates the Rotation for the localTime of the Track.
539   \returns the calculated Rotation
540*/
541Vector TrackManager::calcDir() const
542{
543  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
544}
545
546/**
547   \brief Advances the local-time of the Track around dt
548   \param dt The time about which to advance.
549
550   This function also checks, if the TrackElement has to be changed.
551*/
552void TrackManager::tick(float dt)
553{
554  dt /= 1000;
555  printf("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
556  if (this->localTime <= this->firstTrackElem->duration)
557    this->jumpTo(this->localTime);
558  this->localTime += dt;
559  if (this->localTime > this->currentTrackElem->endTime
560      && this->currentTrackElem->children)
561    {
562      if (this->currentTrackElem->jumpTime > 0) 
563        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
564      this->currentTrackElem = this->currentTrackElem->children[0];
565    }
566  if (this->bindSlave)
567    {
568      Vector tmp = this->calcPos();
569      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)); 
570      this->bindSlave->setAbsCoor(&tmp);
571      this->bindSlave->setAbsDir(&quat);
572    }
573}
574
575/**
576   \brief Jumps to a certain point on the Track.
577   \param time The time on the Track to jump to.
578
579   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.)
580   Max is trackLengthMax.
581*/
582void TrackManager::jumpTo(float time)
583{
584  if (time == 0)
585    this->currentTrackElem = this->firstTrackElem;
586  this->localTime = time;
587}
588
589/**
590   \brief a Function that decides which Path we should follow.
591   \param graphID The Path to choose.
592   
593*/
594void TrackManager::choosePath(int graphID)
595{
596
597}
598
599/**
600   \brief Sets the PNode, that should be moved along the Tack
601   \param bindSlave the PNode to set
602*/
603void TrackManager::setBindSlave(PNode* bindSlave)
604{
605  if (!this->bindSlave)
606    this->bindSlave = bindSlave;
607}
608
609
610// DEBUG //
611
612/**
613   \brief Imports a model of the Graph into the OpenGL-environment.
614   \param dt The Iterator used in seconds for Painting the Graph.
615
616   This is for testing facility only. Do this if you want to see the Path inside the Level.
617   eventually this will all be packed into a gl-list.
618*/
619void TrackManager::drawGraph(float dt) const
620{
621
622  for (int i = 1; i <= trackElemCount; i++)
623    {
624      glBegin(GL_LINE_STRIP);
625      TrackElement* tmpElem = this->findTrackElementByID(i);
626      if (tmpElem->curve)
627        for(float f = 0.0; f < 1.0; f+=dt)
628          {
629            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
630            Vector tmpVector = tmpElem->curve->calcPos(f);
631            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
632          }
633  glEnd();
634    }
635}
636
637/**
638   \brief outputs debug information about the trackManager
639   \param level how much debug
640*/
641void TrackManager::debug(unsigned int level) const
642{
643  printf("::CLASS TRACKMANAGER::debug information::\n");
644  //  printf("Status is: %
645  printf(" Consists of %d elements\n", this->trackElemCount);
646  printf(" localTime is: %f\n", this->localTime);
647  if (level >= 2)
648    {
649      for (int i = 1; i <= trackElemCount; i++)
650        {
651          TrackElement* tmpElem = this->findTrackElementByID(i);
652          printf("  ::TrackElement:%i::", tmpElem->ID);
653          if(tmpElem->name)
654            printf("name:%s::", tmpElem->name);
655          if(tmpElem->isFresh)
656            printf("   has not jet eddited in any way\n");
657          printf("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
658          printf("   consists of %d Points\n", tmpElem->nodeCount);
659          if (tmpElem->childCount == 0)
660            printf("   has no child\n");           
661          else if (tmpElem->childCount == 1)
662            printf("   has 1 child: ==%d==\n", tmpElem->children[0]->ID);
663          else if (tmpElem->childCount > 1)
664            {
665              printf("   has %d children: ", tmpElem->childCount);
666              for(int i = 0; i < tmpElem->childCount; i++)
667                printf("=%d= ", tmpElem->children[i]->ID);
668              printf("\n");
669            }
670
671          if(tmpElem->isHotPoint)
672            printf("   is a special Point:\n");
673          if(tmpElem->isSavePoint)
674            printf("    is a SavePoint\n");
675          if(tmpElem->isFork)
676            {
677              printf("    is A Fork with with %d children.\n", tmpElem->childCount);
678            }
679          if(tmpElem->isJoined)
680            printf("   is Joined at the End\n");
681        }
682    }
683}
684
685/**
686   \brief loads track data from a XML Element
687   \param root the element containing all track data
688*/
689void TrackManager::loadTrack( TiXmlElement* root)
690{
691        assert( root != NULL);
692       
693        TiXmlElement* element;
694        TiXmlNode* container;
695        double x, y, z, d;
696       
697        element = root->FirstChildElement();
698       
699        while( element != NULL)
700        {
701                if( !strcmp( element->Value(), "Point"))
702                {
703                        container = element->FirstChild();
704                        if( container->ToText())
705                        {
706                                assert( container->Value() != NULL);
707                                if( sscanf( container->Value(), "%f,%f,%f", &x, &y, &z) == 3)
708                                        addPoint( Vector( x, y, z));
709                                else
710                                {
711                                        PRINTF(1)("Invalid Point in Track (skipped)\n");
712                                }                       
713                        }
714                }
715                else if( !strcmp( element->Value(), "Duration"))
716                {
717                        container = element->FirstChild();
718                        if( container->ToText())
719                        {
720                                assert( container->Value() != NULL);
721                                if( sscanf( container->Value(), "%f", &d) == 1)
722                                        setDuration( d);
723                                else
724                                {
725                                        PRINTF(1)("Invalid Duration in Track (skipped)\n");
726                                }                       
727                        }
728                }
729                else if( !strcmp( element->Value(), "SavePoint"))
730                {
731                        setSavePoint();
732                }
733                else if( !strcmp( element->Value(), "Fork"))
734                {
735                        container = element->FirstChild();
736                        if( container->ToText())
737                        {
738                                assert( container->Value() != NULL);
739                                forkS( container->Value());
740                        }
741                }
742                else if( !strcmp( element->Value(), "Join"))
743                {
744                        container = element->FirstChild();
745                        if( container->ToText())
746                        {
747                                assert( container->Value() != NULL);
748                                joinS( container->Value());
749                        }
750                }
751                else if( !strcmp( element->Value(), "WorkOn"))
752                {
753                        container = element->FirstChild();
754                        if( container->ToText())
755                        {
756                                assert( container->Value() != NULL);
757                                workOnS( container->Value());
758                        }
759                }
760               
761                element = element->NextSiblingElement();
762        }
763}
764
765/**
766   \brief forks the current track and names the resulting tracks
767   \param string the names of the new tracks, separated by commas
768   
769   The names used have to be unique within a particular track system.
770*/
771void TrackManager::forkS( const char* string)
772{
773        // get the names for the tracks and therefore the amount of new tracks
774        SubString* parts = new SubString( string);
775        int *IDs;
776        int n = parts->getN();
777       
778        assert( n != 0);
779       
780        IDs = new int[n];
781       
782        forkV( n, IDs, parts);
783       
784        // IDs are irrelevant when assigning string names to tracks
785        delete IDs;
786        delete parts;
787}
788
789/**
790   \brief joins the named strings
791   \param string the names of the track to be joined, separated by commas
792*/
793void TrackManager::joinS( const char* string)
794{
795        SubString* parts = new SubString( string);
796        int *IDs;
797        int n = parts->getN();
798       
799        assert( n != 0);
800       
801        IDs = new int[n];
802       
803        int d, t;
804        d = 0;
805        t = n;
806       
807        PRINTF(4)("Joining tracks:");
808       
809        for( int i = 0; i < n; i++)
810        {
811                TrackElement* element = this->findTrackElementByName(parts->getString( i));
812                if( element == NULL)
813                {
814                        PRINTF(1)("Track name '%s' unknown, could not join\n", parts->getString( i));
815                        t--;
816                }
817                else
818                {
819                        PRINTF(4)(" '%s'(%d)", parts->getString( i), element->ID);
820                        IDs[d] = element->ID;
821                        d++;
822                }
823        }
824       
825        PRINTF(4)("\n");
826
827        joinV( t, IDs);
828               
829        delete IDs;
830        delete parts;
831}
832
833/**
834   \brief set the piece of track to work on
835   \param string the name of the track to work on (must have been previosly set by forkS)
836*/
837void TrackManager::workOnS( const char* string)
838{
839  TrackElement* tmpElem = findTrackElementByName( string);
840  if (tmpElem)
841    this->currentTrackElem = tmpElem;
842  else
843    PRINTF(1)("TrackElement not Found, leaving unchanged\n");
844  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
845}
Note: See TracBrowser for help on using the repository browser.