Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3523 was 3523, checked in by chris, 19 years ago

orxonox/branches/levelloader: Implemented support for loading tracks in the WorldDataFiles

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