Module: rtrack.cpp

class RTrack
.h

constructorRTrack()
destructor~RTrack()
GetTimeLineRTimeLine *GetTimeLine(int n)
GetGridPosRCarPos *GetGridPos(int n)
GetPitPosRCarPos *GetPitPos(int n)
GetSurfaceInfovoid GetSurfaceInfo(DVector3 *pos,DVector3 *dir,RSurfaceInfo *si)

Retrieves info on track surface
Note that normally only pos->x and pos->z are used. In case of
bridges like in Suzuka however, pos->y may be used to return either
the track above or below the bridge.

SetNamevoid SetName(cstring _trackName)

Load a track (of any type)
This is the base function; a derived class should override this
function, call us first (and check the return code), then load the
actual track from 'file'.


Flat functions
 

trackName.cstr()trackName.cstr(),(cstring)trackDir);

}


class RTrack
.h

LoadSpecialbool LoadSpecial()

Load positions and timelines etc

Loadbool Load()

Load a track (of any type)
This is the base function; a derived class should override this
function, call us first (and check the return code), then load the
actual track from 'file'.

SaveSpecialbool SaveSpecial()

Load positions and timelines etc

Savebool Save()
Paintvoid Paint()

Painter; override in the derived class

PaintHiddenvoid PaintHidden()

Paint hidden parts; override in subclasses



/*
 * RTrack - base class for Racer tracks
 * ??-11-00: Created!
 * (c) Dolphinity
 */

#include <racer/racer.h>
#include <qlib/debug.h>
#pragma hdrstop
DEBUG_ENABLE

// Default track information file
#define TRACK_INI  "track.ini"
// File with special things, like grid positions, pit positions and timelines
#define FILE_SPECIAL   "special.ini"

RTrack::RTrack()
{
  type="flat";
  cbLoad=0;
  timeLines=0;
  gridPosCount=pitPosCount=0;
}
RTrack::~RTrack()
{
  int i;
  
  for(i=0;i<timeLines;i++)
    if(timeLine[i])delete timeLine[i];
}

/**********
* Attribs *
**********/
RTimeLine *RTrack::GetTimeLine(int n)
{
  if(n<0||n>=timeLines)
  { qwarn("RTrack:GetTimeLine(%d) out of bounds",n);
    return 0;
  }
  return timeLine[n];
}

/****************
* Car positions *
****************/
RCarPos *RTrack::GetGridPos(int n)
{
  QASSERT_0(n>=0&&n<gridPosCount);
  return &gridPos[n];
}
RCarPos *RTrack::GetPitPos(int n)
{
  QASSERT_0(n>=0&&n<pitPosCount);
  return &pitPos[n];
}

/**********************
* SURFACE DESCRIPTION *
**********************/
void RTrack::GetSurfaceInfo(DVector3 *pos,DVector3 *dir,RSurfaceInfo *si)
// Retrieves info on track surface
// Note that normally only pos->x and pos->z are used. In case of
// bridges like in Suzuka however, pos->y may be used to return either
// the track above or below the bridge.
{
//qdbg("RTrack::GetSurfaceInfo()\n");

  // Default is flat boring track
  si->x=pos->x;
  si->y=0;
  si->z=pos->z;
  si->grade=0;
  si->bank=0;
  si->friction=1.0;
}

/*********
* Naming *
*********/
void RTrack::SetName(cstring _trackName)
// Load a track (of any type)
// This is the base function; a derived class should override this
// function, call us first (and check the return code), then load the
// actual track from 'file'.
{
  char    buf[256];
  cstring s;
  
  trackName=_trackName;
  
  // Deduce track directory
  sprintf(buf,"data/tracks/%s",trackName.cstr());
  strcpy(buf,RFindDir(buf));
#ifdef OBS
  s=RFindFile(".",buf);
  // Strip "."
  strcpy(buf,s);
  buf[strlen(buf)-2]=0;
#endif
  trackDir=buf;
qdbg("RTrack:SetName(%s) => trackDir='%s'\n",
trackName.cstr(),(cstring)trackDir);
}

/**********
* LOADING *
**********/
bool RTrack::LoadSpecial()
// Load positions and timelines etc
{
  QInfo *info;
  char buf[256];
  int i;
  RCarPos *p;
  
  sprintf(buf,"%s/%s",(cstring)trackDir,FILE_SPECIAL);
  info=new QInfo(buf);
  
  // Restore grid positions
  gridPosCount=info->GetInt("grid.count");
  if(gridPosCount>MAX_GRID_POS)gridPosCount=MAX_GRID_POS;
  for(i=0;i<gridPosCount;i++)
  {
    p=&gridPos[i];
    sprintf(buf,"grid.pos%d.from.x",i); p->from.x=info->GetFloat(buf);
    sprintf(buf,"grid.pos%d.from.y",i); p->from.y=info->GetFloat(buf);
    sprintf(buf,"grid.pos%d.from.z",i); p->from.z=info->GetFloat(buf);
    sprintf(buf,"grid.pos%d.to.x",i); p->to.x=info->GetFloat(buf);
    sprintf(buf,"grid.pos%d.to.y",i); p->to.y=info->GetFloat(buf);
    sprintf(buf,"grid.pos%d.to.z",i); p->to.z=info->GetFloat(buf);
  }
  
  // Restore pit positions
  pitPosCount=info->GetInt("pit.count");
  if(pitPosCount>MAX_PIT_POS)pitPosCount=MAX_PIT_POS;
  for(i=0;i<pitPosCount;i++)
  {
    p=&pitPos[i];
    sprintf(buf,"pit.pos%d.from.x",i); p->from.x=info->GetFloat(buf);
    sprintf(buf,"pit.pos%d.from.y",i); p->from.y=info->GetFloat(buf);
    sprintf(buf,"pit.pos%d.from.z",i); p->from.z=info->GetFloat(buf);
    sprintf(buf,"pit.pos%d.to.x",i); p->to.x=info->GetFloat(buf);
    sprintf(buf,"pit.pos%d.to.y",i); p->to.y=info->GetFloat(buf);
    sprintf(buf,"pit.pos%d.to.z",i); p->to.z=info->GetFloat(buf);
  }
  
  // Restore timelines
  timeLines=info->GetInt("timeline.count");
  if(timeLines>MAX_TIMELINE)timeLines=MAX_TIMELINE;
  for(i=0;i<timeLines;i++)
  {
    RTimeLine *t;
    DVector3 v1,v2;
    v1.SetToZero(); v2.SetToZero();
    timeLine[i]=new RTimeLine(&v1,&v2);
    t=timeLine[i];
    sprintf(buf,"timeline.line%d.from.x",i); v1.x=info->GetFloat(buf);
    sprintf(buf,"timeline.line%d.from.y",i); v1.y=info->GetFloat(buf);
    sprintf(buf,"timeline.line%d.from.z",i); v1.z=info->GetFloat(buf);
    sprintf(buf,"timeline.line%d.to.x",i); v2.x=info->GetFloat(buf);
    sprintf(buf,"timeline.line%d.to.y",i); v2.y=info->GetFloat(buf);
    sprintf(buf,"timeline.line%d.to.z",i); v2.z=info->GetFloat(buf);
    // Redefine to get variables right
    t->Define(&v1,&v2);
  }

//qdbg("RTrack:LoadSpecial(); timeLines=%d\n",timeLines);
  delete info;
  return TRUE;
}
bool RTrack::Load()
// Load a track (of any type)
// This is the base function; a derived class should override this
// function, call us first (and check the return code), then load the
// actual track from 'file'.
{
  QInfo  *infoTrk;
  char    buf[256];

  // Find generic info on track
  infoTrk=new QInfo(RFindFile(TRACK_INI,trackDir));
  // Found the track.ini?
  if(!infoTrk->FileExists())
  { qwarn("Can't find track.ini for track %s",trackName);
    return FALSE;
  }
  infoTrk->GetString("track.type",type);
  infoTrk->GetString("track.name",name);
  infoTrk->GetString("track.creator",creator);
  infoTrk->GetString("track.length",length);
  infoTrk->GetString("track.file",file);
  delete infoTrk;

  if(!LoadSpecial())return FALSE;
  
#ifdef OBS
  // Find actual track 3D file
  strcpy(buf,RFindFile(file,trackDir));
  file=buf;
  if(!QFileExists(file))
  { qwarn("Can't find track file (%s) for track %s",(cstring)file,trackName);
    return FALSE;
  }
#endif
  return TRUE;
}

/*********
* Saving *
*********/
bool RTrack::SaveSpecial()
// Load positions and timelines etc
{
  QInfo *info;
  int i;
  RCarPos *p;
  char buf[100];
  
  sprintf(buf,"%s/%s",(cstring)trackDir,FILE_SPECIAL);
  info=new QInfo(buf);
  
  // Store grid positions
  info->SetInt("grid.count",gridPosCount);
  for(i=0;i<gridPosCount;i++)
  {
    p=&gridPos[i];
    sprintf(buf,"grid.pos%d.from.x",i); info->SetFloat(buf,p->from.x);
    sprintf(buf,"grid.pos%d.from.y",i); info->SetFloat(buf,p->from.y);
    sprintf(buf,"grid.pos%d.from.z",i); info->SetFloat(buf,p->from.z);
    sprintf(buf,"grid.pos%d.to.x",i); info->SetFloat(buf,p->to.x);
    sprintf(buf,"grid.pos%d.to.y",i); info->SetFloat(buf,p->to.y);
    sprintf(buf,"grid.pos%d.to.z",i); info->SetFloat(buf,p->to.z);
  }
  
  // Store pit positions
  info->SetInt("pit.count",pitPosCount);
  for(i=0;i<pitPosCount;i++)
  {
    p=&pitPos[i];
    sprintf(buf,"pit.pos%d.from.x",i); info->SetFloat(buf,p->from.x);
    sprintf(buf,"pit.pos%d.from.y",i); info->SetFloat(buf,p->from.y);
    sprintf(buf,"pit.pos%d.from.z",i); info->SetFloat(buf,p->from.z);
    sprintf(buf,"pit.pos%d.to.x",i); info->SetFloat(buf,p->to.x);
    sprintf(buf,"pit.pos%d.to.y",i); info->SetFloat(buf,p->to.y);
    sprintf(buf,"pit.pos%d.to.z",i); info->SetFloat(buf,p->to.z);
  }
  
  // Store timelines
  info->SetInt("timeline.count",timeLines);
  for(i=0;i<timeLines;i++)
  {
    RTimeLine *t;
    t=timeLine[i];
    sprintf(buf,"timeline.line%d.from.x",i); info->SetFloat(buf,t->from.x);
    sprintf(buf,"timeline.line%d.from.y",i); info->SetFloat(buf,t->from.y);
    sprintf(buf,"timeline.line%d.from.z",i); info->SetFloat(buf,t->from.z);
    sprintf(buf,"timeline.line%d.to.x",i); info->SetFloat(buf,t->to.x);
    sprintf(buf,"timeline.line%d.to.y",i); info->SetFloat(buf,t->to.y);
    sprintf(buf,"timeline.line%d.to.z",i); info->SetFloat(buf,t->to.z);
  }
  delete info;
  return TRUE;
}
bool RTrack::Save()
{
  if(!SaveSpecial())return FALSE;
  
  return TRUE;
}

/********
* PAINT *
********/
void RTrack::Paint()
// Painter; override in the derived class
{
}
void RTrack::PaintHidden()
// Paint hidden parts; override in subclasses
{
}