/***************************************************************************
                          spl_prg.cpp  -  description
                             -------------------
    begin                : Fri Jan 21 2005
    copyright            : (C) 2005 by Harald Krippel
    email                : neuro.harald@surfeu.at
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

 #include "spl_prg.h"
 #include <qfile.h>
 #include <main.h>
 
#include "globdefines.h"
#include "glcontrol.h"
#include "astar.h"

class splaEntity ;


#define SPLA_MAX_MODELS 500



static int       splaNextModel   =   0   ;
static bool      splaInitialised = false ;
static splaEntity *splaModels [ SPLA_MAX_MODELS ] ;

class splaEntity
{
protected:

  int           handle ;
  int           mid;        // modell id == id from tree
  int           updateme;
  sgCoord       pos ;
  sgCoord       vel ;
  int           play;
  int           attrupdate;

public:

  splaEntity ( const int id )
  {
    splaModels [ splaNextModel ] = this ;

    handle = splaNextModel++ ;

    if ( splaNextModel >= SPLA_MAX_MODELS )
    {
      fprintf ( stderr, "qcake: ERROR - More than %d models loaded!\n", SPLA_MAX_MODELS ) ;
      exit ( 1 ) ;
    }

    sgZeroCoord ( & pos ) ;
    sgZeroCoord ( & vel ) ;
    play=0;
    updateme=0;
  }

  virtual ~splaEntity(void)
  {

  }

  int getHandle () const { return handle ; }

  float getPositionX () const { return pos.xyz[0] ; }
  float getPositionY () const { return pos.xyz[1] ; }
  float getPositionZ () const { return pos.xyz[2] ; }
  float getPositionH () const { return pos.hpr[0] ; }
  float getPositionP () const { return pos.hpr[1] ; }
  float getPositionR () const { return pos.hpr[2] ; }

  
  
  void addRelTorque ( float velx, float vely, float velz )
  {
      if(g_ListItem[mid]->text(1) == "BODY")
      {
          g_ListItem[mid]->body->lvel[0] = velx;
          g_ListItem[mid]->body->lvel[1] = vely;
          g_ListItem[mid]->body->lvel[2] = velz;
          g_ListItem[mid]->body->AddRelTorque ();
      }
  }
  void setSequence ( int sequenz , int mode )
  {
      if(g_ListItem[mid]->text(1) == "OBJECT")
      {
          if(g_ListItem[mid]->objtrans-> getKid(0)-> isAKindOf ( ssgTypeSelector() ) )
          {
              ssgSelector *selector = (ssgSelector *)g_ListItem[mid]->objtrans-> getKid(0);
              selector->selectStep ( sequenz );
              if(selector -> getKid(sequenz)-> isAKindOf ( ssgTypeTimedSelector() ) )
              {
                  ssgTimedSelector *ts = (ssgTimedSelector *)selector -> getKid(sequenz);
                  if(mode == 0)
                    ts -> setMode(SSG_ANIM_SWING);
                  if(mode == 1)
                    ts -> setMode(SSG_ANIM_ONESHOT);
                  if(mode == 2)
                    ts -> setMode(SSG_ANIM_SHUTTLE);
                  ts -> control(SSG_ANIM_START);
                  ts -> setDuration ( 0.1 , -1 , SSG_ANIM_CLOCK ) ;
              }
              else
              {
                fprintf ( stderr, "qcake: ERROR - OBJECT has no TimedSelector %i !\n",sequenz ) ;
              }
          }
          else
          {
              fprintf ( stderr, "qcake: ERROR - OBJECT has no Selector!\n" ) ;
          }
      }
  }

  
  void setAngularVel ( float velx, float vely, float velz )
  {
      if(g_ListItem[mid]->text(1) == "BODY")
      {
          g_ListItem[mid]->body->lvel[0] = velx;
          g_ListItem[mid]->body->lvel[1] = vely;
          g_ListItem[mid]->body->lvel[2] = velz;
          g_ListItem[mid]->body->SetAngularVel ();
      }
  }
  void addRelForce ( float velx, float vely, float velz )
  {
      if(g_ListItem[mid]->text(1) == "BODY")
      {
          g_ListItem[mid]->body->lvel[0] = velx;
          g_ListItem[mid]->body->lvel[1] = vely;
          g_ListItem[mid]->body->lvel[2] = velz;
          g_ListItem[mid]->body->AddRelForce ();
      }
  }
  void setLinVel ( float velx, float vely, float velz )
  {
      if(g_ListItem[mid]->text(1) == "BODY")
      {
          g_ListItem[mid]->body->lvel[0] = velx;
          g_ListItem[mid]->body->lvel[1] = vely;
          g_ListItem[mid]->body->lvel[2] = velz;
          g_ListItem[mid]->body->SetLinearVel ();
      }
  }

  void setPosition ( float x, float y, float z, float h, float p, float r )
  {
    sgSetCoord ( &pos, x, y, z, h, p, r ) ;
    updateme=1;
  }

  void setRotation ( float h, float p, float r )
  {
          g_ListItem[mid]->body->pos.hpr[0] = h;
          g_ListItem[mid]->body->pos.hpr[1] = p;
          g_ListItem[mid]->body->pos.hpr[2] = r;
          g_ListItem[mid]->body->SetRotation ();
  }

  void Rotation ( float h, float p, float r )
  {
    sgMat4 m ;
    sgMat4 mh ;
    
      if(g_ListItem[mid]->text(1) == "OBJECT")
      {
        sgMakeCoordMat4 ( mh, 0, 0, 0, h, p, r ) ;
        g_ListItem[mid]->objtrans->getTransform ( m ) ;
        sgPreMultMat4  ( m, mh ) ;
        g_ListItem[mid]->objtrans->setTransform ( m ) ;    
      }
      if(g_ListItem[mid]->text(1) == "BODY")
      {
          g_ListItem[mid]->body->Rotation(h,p,r);
      }
      if(g_ListItem[mid]->text(1) == "BARRIER")
      {
          g_ListItem[mid]->barrier->Rotation(h,p,r);
      }
  }

  void playSound ()
  {
    play=1;
  }

  void stopSound ()
  {
    play=2;
  }
  
  int switchScene()
  {
    if(g_ListItem[mid] != NULL)
    {
      if(g_ListItem[mid]->text(1) == "SCENE")
      {
        if(g_gl != NULL)
        {
            g_switchScene= g_ListItem[mid];
            g_switch=1;
        }
      }
    }
    return(0);
  }

  ssgEntity * getEntity()
  {
      if(g_ListItem[mid]->text(1) == "OBJECT")
      {
          if(g_ListItem[mid]->objtrans-> getKid(0)-> isAKindOf ( ssgTypeEntity() ) )
          {
              return((ssgEntity *)g_ListItem[mid]->objtrans-> getKid(0));
          }
      }
      return(NULL);
  }

  int switchCamera()
  {
    if(g_ListItem[mid] != NULL)
    {
      if(g_ListItem[mid]->text(1) == "CAMERA")
      {
        if(g_gl != NULL)
        {
          g_gl->switchCamera(g_ListItem[mid]);
        }
      }
    }
    return(0);
  }

  float getAttribute(char *attr)
  {
    float value=0;
    int ok=0;
    if(g_ListItem[mid] != NULL)
    {
      // this code is possible to move to the listviews.cpp
         if(strstr(attr,"collision") != NULL)
         {
             value = g_ListItem[mid]->collision;
             ok=1;
         }
         if(strstr(attr,"groundcollision") != NULL)
         {
             value = g_ListItem[mid]->groundcollision;
             ok=1;
         }
         if(ok != 1)
         {
            value =  g_ListItem[mid]->GetValue(attr).toFloat();
         }
    }
    return(value);
  }

  void setAttribute(char *attr, char *value)
  {
    if(g_ListItem[mid] != NULL)
    {

      if(g_gl != NULL)  // update
      {
         g_gl->changeAttribute(g_ListItem[mid],attr,value);
      }
    }
  }


  
//  virtual void update ( double dt ) = NULL ;
  virtual void update ( double dt ) = 0 ;
} ;


class splaModel : public splaEntity
{
  sgMat4 m ;
  long a;

public:

  splaModel ( const int id ) : splaEntity ( id )
  {
    mid=0;
    for(a=0;a<MAX_LIST_ITEMS;a++)
    {
      if(g_ListItem[a] != NULL)
      {
        if(g_ListItem[a]->GetValue("tmpid").toInt() == id)
        {
          mid=a;
        }
      }
    }
    if(mid == 0)
    {
          fprintf ( stderr, "SPL: There is no such 3D Object as '%d'\n", id ) ;
    }
    else
    {
      update ( 0 );

    }
 //   fprintf ( stderr, "3D Object as '%d'\n", mid ) ;  //debug
  }

  virtual ~splaModel(void)
  {

  }

  
  virtual void update ( double dt )
  {
    sgMat4 m ;
    
    if(g_ListItem[mid] != NULL )
    {
      // this code is possible to move to the listviews.cpp

      if(g_ListItem[mid]->text(1) == "OBJECT")
      {
        if(g_ListItem[mid]->objtrans != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->objtrans->setTransform ( & pos,g_ListItem[mid]->GetValue("scax").toFloat(),g_ListItem[mid]->GetValue("scay").toFloat(),g_ListItem[mid]->GetValue("scaz").toFloat() ) ;
          }
          g_ListItem[mid]->objtrans->getTransform ( m ) ;
          sgSetCoord  ( &pos, m ) ;
        }

      }
      if(g_ListItem[mid]->text(1) == "FIRE")
      {
        if(g_ListItem[mid]->objtrans != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->objtrans->setTransform ( & pos ) ;
          }
          g_ListItem[mid]->objtrans->getTransform ( m ) ;
          sgSetCoord  ( &pos, m ) ;
        }
      }
      if(g_ListItem[mid]->text(1) == "CAMERA")
      {
        if(g_ListItem[mid]->objtrans != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->objtrans->setTransform ( & pos ) ;
          }
          g_ListItem[mid]->objtrans->getTransform ( m ) ;
          sgSetCoord  ( &pos, m ) ;
        }
      }
      if(g_ListItem[mid]->text(1) == "BARRIER")
      {
        if(g_ListItem[mid]->barrier != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->barrier->pos.xyz[0] = pos.xyz[0];
            g_ListItem[mid]->barrier->pos.xyz[1] = pos.xyz[1];
            g_ListItem[mid]->barrier->pos.xyz[2] = pos.xyz[2];

            g_ListItem[mid]->barrier->pos.hpr[0] = pos.hpr[0];
            g_ListItem[mid]->barrier->pos.hpr[1] = pos.hpr[1];
            g_ListItem[mid]->barrier->pos.hpr[2] = pos.hpr[2];
            g_ListItem[mid]->barrier->SetPosition ();
          }
          g_ListItem[mid]->barrier->GetPosition (&pos);
        }
      }
      if(g_ListItem[mid]->text(1) == "PLAYER")
      {
        if( g_ListItem[mid]->player != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->player->pos.xyz[0] = pos.xyz[0];
            g_ListItem[mid]->player->pos.xyz[1] = pos.xyz[1];
            g_ListItem[mid]->player->pos.xyz[2] = pos.xyz[2];

            g_ListItem[mid]->player->pos.hpr[0] = pos.hpr[0];
            g_ListItem[mid]->player->pos.hpr[1] = pos.hpr[1];
            g_ListItem[mid]->player->pos.hpr[2] = pos.hpr[2];
            g_ListItem[mid]->player->SetPosition ();
          }
          g_ListItem[mid]->player->GetPosition (&pos);
        }
      }
      if(g_ListItem[mid]->text(1) == "BODY")
      {
        if(g_ListItem[mid]->body != NULL)
        {
          if(updateme==1)
          {
            g_ListItem[mid]->body->pos.xyz[0] = pos.xyz[0];
            g_ListItem[mid]->body->pos.xyz[1] = pos.xyz[1];
            g_ListItem[mid]->body->pos.xyz[2] = pos.xyz[2];

            g_ListItem[mid]->body->pos.hpr[0] = pos.hpr[0];
            g_ListItem[mid]->body->pos.hpr[1] = pos.hpr[1];
            g_ListItem[mid]->body->pos.hpr[2] = pos.hpr[2];
            g_ListItem[mid]->body->SetPosition ();
          }
          g_ListItem[mid]->body->GetPosition (&pos);        
        }
      }
      if(g_ListItem[mid]->text(1) == "LAMP")
      {

      }
      if(g_ListItem[mid]->text(1) == "CURSOR")
      {
        if(g_ListItem[mid]->cursor != NULL)
        {
          g_ListItem[mid]->cursor->GetPosition(&pos);
        }
      }
      if(g_ListItem[mid]->text(1) == "SOUND")
      {
        if(g_ListItem[mid]->sound != NULL)
        {
          if(updateme==1)
          {
             g_ListItem[mid]->sound->pos.xyz[0] = pos.xyz[0];
             g_ListItem[mid]->sound->pos.xyz[1] = pos.xyz[1];
             g_ListItem[mid]->sound->pos.xyz[2] = pos.xyz[2];
             g_ListItem[mid]->sound->SetPosition();
          }
          if(play==1)
          {
#ifdef KCOPENAL
           g_ListItem[mid]->sound->Play();
#endif
           play=0;
          }
          if(play==2)
          {
#ifdef KCOPENAL
           g_ListItem[mid]->sound->Stop();
#endif
           play=0;
          }

        }
      }
      updateme=0;
    }
  }

};
    
static splaEntity *getModel ( int i )
{
  if ( i < 0 || i >= SPLA_MAX_MODELS ||
       splaModels [ i ] == NULL )
  {
    fprintf ( stderr, "SPL: There is no such model as '%d'\n", i ) ;
    exit ( 1 ) ;
  }

  return splaModels [ i ] ;
}

void splaRedraw ()
{
//  double dt = siFrameTimer -> getDeltaTime () ;
  double dt = 0 ;
  for ( int i = 0 ; i < splaNextModel ; i++ )
    splaModels [ i ] -> update ( dt ) ;

}

void splaInit ()
{
  if ( splaInitialised )
  {
    fprintf ( stderr, "spla: splInit() was called more than once!\n" ) ;
//    exit ( 1 ) ;
  }

  splaInitialised = true ;


  for ( int i = 0 ; i < SPLA_MAX_MODELS ; i++ )
    splaModels [ i ] = NULL ;

  splaNextModel = 0 ;

}

//******spla functions()*******************************************

int splaSwitchScene ( int hh)
{
  int value=0;

  value = getModel ( hh ) -> switchScene ( ) ;
  return(value);
}

int splaSwitchCamera ( int hh)
{
  int value=0;

  value = getModel ( hh ) -> switchCamera ( ) ;
  return(value);
}

float splaGetPositionX(int hh) { return getModel ( hh ) -> getPositionX () ; }
float splaGetPositionY(int hh) { return getModel ( hh ) -> getPositionY () ; }
float splaGetPositionZ(int hh) { return getModel ( hh ) -> getPositionZ () ; }
float splaGetPositionH(int hh) { return getModel ( hh ) -> getPositionH () ; }
float splaGetPositionP(int hh) { return getModel ( hh ) -> getPositionP () ; }
float splaGetPositionR(int hh) { return getModel ( hh ) -> getPositionR () ; }

void splaAddRelTorque ( int hh, float velx, float vely, float velz )
{
  getModel ( hh ) -> addRelTorque ( velx, vely, velz ) ;
}

void splaSetSequenz ( int hh, int sequenz, int mode )
{
  getModel ( hh ) -> setSequence ( sequenz , mode ) ;
}

void splaSetAngularVel ( int hh, float velx, float vely, float velz )
{
  getModel ( hh ) -> setAngularVel ( velx, vely, velz ) ;
}

void splaAddRelForce ( int hh, float velx, float vely, float velz )
{
  getModel ( hh ) -> addRelForce ( velx, vely, velz ) ;
}

void splaSetLinVel ( int hh, float velx, float vely, float velz )
{
  getModel ( hh ) -> setLinVel ( velx, vely, velz ) ;
}

void splaSetRotation ( int hh, float h, float p, float r )
{
  getModel ( hh ) -> setRotation ( h, p, r ) ;
}

void splaRotation ( int hh, float h, float p, float r )
{
  getModel ( hh ) -> Rotation ( h, p, r ) ;
}

void splaSetPosition ( int hh, float x, float y, float z,
                          float h, float p, float r )
{
  getModel ( hh ) -> setPosition ( x, y, z, h, p, r ) ;
}

void splaPlaySound ( int hh)
{
  getModel ( hh ) -> playSound ( ) ;
}

void splaStopSound ( int hh)
{
  getModel ( hh ) -> stopSound ( ) ;
}

int splaGetRef ( int id )
{
  if ( ! splaInitialised )
    splaInit () ;

  splaModel *m = new splaModel ( id ) ;

 // fprintf ( stderr,"splaGetRef %d %d\n",id,m -> getHandle ());  // debug

  return m -> getHandle () ;
}

float splaGetJoystick ( int js,int a )
{
  float value = 0;

  if ( a >= 0 && a < 8  && js >= 0 && js < 2)
  {
      value = g_ax[js][a];
  }
  return(value);
}

int splaGetJoyButton (int js)
{
  int value = 0;

  value = g_buttons[js];
  return(value);
}

/* get the mouse position */

int splaGetMouse ( int a )
{
  int value = 0;

  if ( a == 0 )
  {
      value = g_mouse_x;
  }
  if ( a == 1 )
  {
      value = g_mouse_y;
  }
  return(value);
}

int splaGetMouseButton (void)
{
  int value = 0;

  value = g_mouse_button;
  return(value);
}

/* get the global POI */

float splaGet3DMouse ( int a )
{
  float value = 0.0f;

  if ( a == 0 )  // POI->x
  {
      value = g_poi[0];
  }
  if ( a == 1 ) // POI->y
  {
      value = g_poi[1];
  }
  if ( a == 2 ) // POI->z
  {
      value = g_poi[2];
  }
  return(value);
}

float splaGetAttribute ( int hh, char * attr)
{
  float value=0;

  // fprintf ( stderr,"splaGetAttribute %d %s\n",hh,attr);  // debug

  value = getModel ( hh ) -> getAttribute ( attr ) ;
  return(value);
}

int splaSetAttribute ( int hh, char * attr, char * value)
{
  getModel ( hh ) -> setAttribute ( attr , value) ;
  return (0);
}

int splaGetKey ()
{
  int tmp;

   tmp=g_key;
   g_key=0;
   return(tmp);
}

int splaSrand (unsigned int seed)
{
   srand(seed);
   return(0);
}

float splaRand ()
{
   return((float)((float)rand()/ (float)RAND_MAX));
 //  return(0.33f);
}

int splaAstarFindPath (int pl,int sx,int sy,int tx,int ty)
{

  return(gastar->FindPath(pl,sx,sy,tx,ty));
}

int splaAstarReadPathX (int pl,int sx)
{

  return(gastar->ReadPathX(pl,sx));
}

int splaAstarReadPathY (int pl,int sy)
{

  return(gastar->ReadPathY(pl,sy));
}

int splaAstarReadMap (char *file)
{
  QString pfad =  g_prjpath + file;
  return(gastar->ReadMap(pfad.ascii()));
}

int splaAstarReadMapValue (int x, int y)
{
  return(gastar->ReadMapValue(x,y));
}

int splaAstarInit (int mapWidth, int mapHeight , int tileSize, int numberPeople)
{
  if(gastar != NULL)
  {
    delete gastar;
  }
  gastar = new aStar(mapWidth, mapHeight , tileSize, numberPeople);

  return(0);
}

int splaTmpobjInit (int hh, float x , float y, float z, float h , float p, float r)
{
  ssgTransform *objtrans = NULL ;
  sgCoord       pos ;

  objtrans = new ssgTransform ;
  if(objtrans != NULL)
  {
    sgSetCoord ( &pos,
                  x,
                  y,
                  z,
                  h,
                  p,
                  r ) ;

    objtrans->setTransform ( & pos,getModel ( hh ) -> getAttribute ( "scax" ),
                                   getModel ( hh ) -> getAttribute ( "scay" ),
                                   getModel ( hh ) -> getAttribute ( "scaz" )) ;

    objtrans -> addKid ( getModel ( hh ) -> getEntity()) ;
    g_gl->scene->addKid ( objtrans ) ;
  }
  return(0);
}

//******spla_node****************************************************

static struct spl_node *my_getPositionX ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionX: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionX(hh));
  }
}
static struct spl_node *my_getPositionY ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionY: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionY(hh));
  }
}
static struct spl_node *my_getPositionZ ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionZ: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionZ(hh));
  }
}
static struct spl_node *my_getPositionH ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionH: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionH(hh));
  }
}
static struct spl_node *my_getPositionP ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionP: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionP(hh));
  }
}
static struct spl_node *my_getPositionR ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getPositionR: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  {
   int hh= spl_clib_get_int(task);
   return SPL_NEW_FLOAT(splaGetPositionR(hh));
  }
}

static struct spl_node *my_addRelTorque ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "addRelTorque: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,velx,vely,velz
   int hh= spl_clib_get_int(task);
   float velx= spl_clib_get_float(task);
   float vely= spl_clib_get_float(task);
   float velz= spl_clib_get_float(task);

   splaAddRelTorque ( hh,velx,vely,velz ) ;
   return 0 ;
  }
}

static struct spl_node *my_setAngularVel ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "setAngularVel: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,velx,vely,velz
   int hh= spl_clib_get_int(task);
   float velx= spl_clib_get_float(task);
   float vely= spl_clib_get_float(task);
   float velz= spl_clib_get_float(task);

   splaSetAngularVel ( hh,velx,vely,velz ) ;
   return 0 ;
  }
}


static struct spl_node *my_addRelForce ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "addRelForce: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,velx,vely,velz
   int hh= spl_clib_get_int(task);
   float velx= spl_clib_get_float(task);
   float vely= spl_clib_get_float(task);
   float velz= spl_clib_get_float(task);

   splaAddRelForce ( hh,velx,vely,velz ) ;
   return 0 ;
  }
}

static struct spl_node *my_setSequence ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 3 )
  {
    fprintf ( stderr, "setLinVel: ERROR - Parameter must be a int, int, int!\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,sequenz
   int hh= spl_clib_get_int(task);
   int sequenz= spl_clib_get_int(task);
   int mode= spl_clib_get_int(task);

   splaSetSequenz ( hh,sequenz,mode ) ;
   return 0 ;
  }
}


static struct spl_node *my_setLinVel ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "setLinVel: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,velx,vely,velz
   int hh= spl_clib_get_int(task);
   float velx= spl_clib_get_float(task);
   float vely= spl_clib_get_float(task);
   float velz= spl_clib_get_float(task);

   splaSetLinVel ( hh,velx,vely,velz ) ;
   return 0 ;
  }
}

static struct spl_node *my_setRotation ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "setRotation: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,h,p,r
   int hh= spl_clib_get_int(task);
   float h= spl_clib_get_float(task);
   float p= spl_clib_get_float(task);
   float r= spl_clib_get_float(task);

//   fprintf ( stderr,"my_setRotation %d %f\n",hh,x);  // debug

   splaSetRotation ( hh,h,p,r ) ;
   return 0 ;
  }
}

static struct spl_node *my_Rotation ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "setRotation: ERROR - Parameter must be a int, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
   // hh,h,p,r
   int hh= spl_clib_get_int(task);
   float h= spl_clib_get_float(task);
   float p= spl_clib_get_float(task);
   float r= spl_clib_get_float(task);

//   fprintf ( stderr,"my_setRotation %d %f\n",hh,x);  // debug

   splaRotation ( hh,h,p,r ) ;
   return 0 ;
  }
}


static struct spl_node *my_setPosition ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 7 )
  {
    fprintf ( stderr, "setPosition: ERROR - Parameter must be a int, float, float, float, float, float, float !\n" ) ;
    return 0 ;
  }
  else
  {
  // hh,x,y,z,h,p,r
   int hh= spl_clib_get_int(task);
   float x= spl_clib_get_float(task);
   float y= spl_clib_get_float(task);
   float z= spl_clib_get_float(task);
   float h= spl_clib_get_float(task);
   float p= spl_clib_get_float(task);
   float r= spl_clib_get_float(task);

//   fprintf ( stderr,"my_setPosition %d %f\n",hh,x);  // debug
      
   splaSetPosition ( hh,x,y,z,h,p,r ) ;
   return 0 ;
  }
}

static struct spl_node *my_getRef ( struct spl_task *task, void *data )
{
  return SPL_NEW_INT(splaGetRef ( spl_clib_get_int(task) ));
}

static struct spl_node *my_getJoystick ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 2 )
  {
    fprintf ( stderr, "getJoystick: ERROR - Parameter must be a int and a int !\n" ) ;
    return 0 ;
  }
  else
  {
    int js=spl_clib_get_int(task);
    int ax=spl_clib_get_int(task);
    return SPL_NEW_FLOAT( splaGetJoystick ( js,ax ) ) ;
  }
}

static struct spl_node *my_getJoyButton ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getJoyButton: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
  return SPL_NEW_INT( splaGetJoyButton (spl_clib_get_int(task)) ) ;
}

static struct spl_node *my_getMouse ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "getMouse: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
   return SPL_NEW_INT( splaGetMouse ( spl_clib_get_int(task) ) ) ;
}

static struct spl_node *my_getMouseButton ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 0 )
  {
    fprintf ( stderr, "getMouseButton: ERROR - no Parameter needs !\n" ) ;
    return 0 ;
  }
  else
  return SPL_NEW_INT( splaGetMouseButton () ) ;
}

static struct spl_node *my_get3DMouse ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "get3DMouse: ERROR - Parameter must be a int !\n" ) ;
    return 0 ;
  }
  else
   return SPL_NEW_FLOAT( splaGet3DMouse ( spl_clib_get_int(task) ) ) ;
}


static struct spl_node *my_getAttribute ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 2 )
  {
    fprintf ( stderr, "getAttribute: ERROR - Parameter must be a int and a string !\n" ) ;
    return 0 ;
  }
  else
  {
    int     hh=spl_clib_get_int(task);
    char *attr=spl_clib_get_string(task);
    return SPL_NEW_FLOAT( splaGetAttribute ( hh, attr ) ) ;
  }
}

static struct spl_node *my_setAttribute ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 3 )
  {
    fprintf ( stderr, "setAttribute: ERROR - Parameter must be a int and a string and a string!\n" ) ;
    return 0 ;
  }
  else
  {
    int   hh    =  spl_clib_get_int(task);
    char* attr  =  spl_clib_get_string(task);
    char* value =  spl_clib_get_string(task);
  
    return SPL_NEW_INT( splaSetAttribute ( hh , attr, value) ) ;
  }
}

static struct spl_node *my_getKey ( struct spl_task *task, void *data )
{
  return SPL_NEW_INT( splaGetKey ( ) ) ;
}

static struct spl_node *my_switchScene ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "switchScene: ERROR - Parameter must be a single int!\n" ) ;
    return 0 ;
  }
  else
  return SPL_NEW_INT( splaSwitchScene (spl_clib_get_int(task) ) ) ;
}

static struct spl_node *my_playSound ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
    fprintf ( stderr, "playSound: ERROR - Parameter must be a single int!\n" ) ;
  else
   splaPlaySound ( spl_clib_get_int(task) ) ;
  return 0 ;
}

static struct spl_node *my_stopSound ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
    fprintf ( stderr, "stopSound: ERROR - Parameter must be a single int!\n" ) ;
  else
   splaStopSound ( spl_clib_get_int(task) ) ;
  return 0 ;
}

static struct spl_node *my_switchCamera ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "switchCamera: ERROR - Parameter must be a single int!\n" ) ;
    return 0 ;
  }
  else
  return SPL_NEW_INT( splaSwitchCamera (spl_clib_get_int(task) ) ) ;
}

static struct spl_node *my_srand ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "srand: ERROR - Parameter must be a single int!\n" ) ;
    return 0 ;
  }
  else
  return SPL_NEW_INT( splaSrand (spl_clib_get_int(task) ) ) ;
}

static struct spl_node *my_rand ( struct spl_task *task, void *data )
{
  return SPL_NEW_FLOAT( splaRand ( ) ) ;
}

static struct spl_node *my_astarFindPath ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 5 )
  {
    fprintf ( stderr, "astarFindPath: ERROR - Parameter must be a int, int, int, int, int !\n" ) ;
    return 0 ;
  }
  else
  {
    int   pl    =  spl_clib_get_int(task);
    int   sx    =  spl_clib_get_int(task);
    int   sy    =  spl_clib_get_int(task);
    int   tx    =  spl_clib_get_int(task);
    int   ty    =  spl_clib_get_int(task);

    return SPL_NEW_INT( splaAstarFindPath ( pl,sx,sy,tx,ty) ) ;
  }
}

static struct spl_node *my_astarReadPathX ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 2 )
  {
    fprintf ( stderr, "astarReadPathX: ERROR - Parameter must be a int, int !\n" ) ;
    return 0 ;
  }
  else
  {
    int   pl    =  spl_clib_get_int(task);
    int   sx    =  spl_clib_get_int(task);

    return SPL_NEW_INT( splaAstarReadPathX (pl,sx) ) ;
  }
}

static struct spl_node *my_astarReadPathY ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 2 )
  {
    fprintf ( stderr, "astarReadPathY: ERROR - Parameter must be a int, int !\n" ) ;
    return 0 ;
  }
  else
  {
    int   pl    =  spl_clib_get_int(task);
    int   sy    =  spl_clib_get_int(task);

    return SPL_NEW_INT( splaAstarReadPathY (pl,sy) ) ;
  }
}

static struct spl_node *my_astarReadMap ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 1 )
  {
    fprintf ( stderr, "astarReadPathY: ERROR - Parameter must be a string !\n" ) ;
    return 0 ;
  }
  else
  {
    char    *file    =  spl_clib_get_string(task);

    return SPL_NEW_INT( splaAstarReadMap (file) ) ;
  }
}

static struct spl_node *my_astarReadMapValue ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 2 )
  {
    fprintf ( stderr, "astarReadPathY: ERROR - Parameter must be a int int !\n" ) ;
    return 0 ;
  }
  else
  {
    int    x    =  spl_clib_get_int(task);
    int    y    =  spl_clib_get_int(task);

    return SPL_NEW_INT( splaAstarReadMapValue (x,y) ) ;
  }
}

static struct spl_node *my_astarInit ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 4 )
  {
    fprintf ( stderr, "astarReadPathY: ERROR - Parameter must be a int int int int !\n" ) ;
    return 0 ;
  }
  else
  {
    int width     =  spl_clib_get_int(task);
    int height    =  spl_clib_get_int(task);
    int size      =  spl_clib_get_int(task);
    int people    =  spl_clib_get_int(task);

    return SPL_NEW_INT( splaAstarInit (width, height, size, people) ) ;
  }
}

static struct spl_node *my_tmpobjInit ( struct spl_task *task, void *data )
{
  if ( spl_clib_get_argc(task) != 7 )
  {
    fprintf ( stderr, "astarReadPathY: ERROR - Parameter must be a int float float float float float float !\n" ) ;
    return 0 ;
  }
  else
  {
    int ref    =  spl_clib_get_int(task);
    float x    =  spl_clib_get_float(task);
    float y    =  spl_clib_get_float(task);
    float z    =  spl_clib_get_float(task);
    float h    =  spl_clib_get_float(task);
    float p    =  spl_clib_get_float(task);
    float r    =  spl_clib_get_float(task);

    return SPL_NEW_INT( splaTmpobjInit (ref,x,y,z,h,p,r) ) ;
  }
}

//****************************************************************
 
 splPrg::splPrg(const char *prg)
 {
     on=1;
     strcpy(prgname,prg);
     strcpy(prgsrc,prg);

     vm = spl_vm_create();
     spl_builtin_register_all(vm);
     asprintf(&vm->path, ".:./spl_modules:%s", spl_system_modules_dir());
	   task = spl_task_create(vm, 0);

     // register the language qcake routines
     spl_clib_reg(vm, (char *)"getPositionX" , my_getPositionX,  0);
     spl_clib_reg(vm, (char *)"getPositionY" , my_getPositionY,  0);
     spl_clib_reg(vm, (char *)"getPositionZ" , my_getPositionZ,  0);
     spl_clib_reg(vm, (char *)"getPositionH" , my_getPositionH,  0);
     spl_clib_reg(vm, (char *)"getPositionP" , my_getPositionP,  0);
     spl_clib_reg(vm, (char *)"getPositionR" , my_getPositionR,  0); 
     spl_clib_reg(vm, (char *)"getJoyButton" , my_getJoyButton,  0);
     spl_clib_reg(vm, (char *)"getJoystick"  , my_getJoystick ,  0);
     spl_clib_reg(vm, (char *)"addRelTorque" , my_addRelTorque,  0);
     spl_clib_reg(vm, (char *)"addRelForce"  , my_addRelForce ,  0);
     spl_clib_reg(vm, (char *)"setSequence"  , my_setSequence ,  0);
     spl_clib_reg(vm, (char *)"setAngVel"    , my_setAngularVel ,0);
     spl_clib_reg(vm, (char *)"setLinVel"    , my_setLinVel   ,  0);
     spl_clib_reg(vm, (char *)"setRotation"  , my_setRotation ,  0);
     spl_clib_reg(vm, (char *)"Rotate"       , my_Rotation    ,  0);
     spl_clib_reg(vm, (char *)"setPosition"  , my_setPosition ,  0);
     spl_clib_reg(vm, (char *)"getRef"       , my_getRef      ,  0);
     spl_clib_reg(vm, (char *)"getMouse"     , my_getMouse    ,  0);
     spl_clib_reg(vm, (char *)"get3DMouse"   , my_get3DMouse  ,  0);
     spl_clib_reg(vm, (char *)"getMouseButton"     , my_getMouseButton    ,  0);
     spl_clib_reg(vm, (char *)"getAttribute" , my_getAttribute,  0);
     spl_clib_reg(vm, (char *)"setAttribute" , my_setAttribute,  0);
     spl_clib_reg(vm, (char *)"getKey"       , my_getKey      ,  0);
     spl_clib_reg(vm, (char *)"switchScene"  , my_switchScene ,  0);
     spl_clib_reg(vm, (char *)"playSound"    , my_playSound   ,  0);
     spl_clib_reg(vm, (char *)"stopSound"    , my_stopSound   ,  0);
     spl_clib_reg(vm, (char *)"switchCamera" , my_switchCamera,  0);
     spl_clib_reg(vm, (char *)"srand"        , my_srand       ,  0);
     spl_clib_reg(vm, (char *)"rand"         , my_rand        ,  0);
     spl_clib_reg(vm, (char *)"astarFindPath" , my_astarFindPath    ,  0);
     spl_clib_reg(vm, (char *)"astarReadPathX" , my_astarReadPathX  ,  0);
     spl_clib_reg(vm, (char *)"astarReadPathY" , my_astarReadPathY  ,  0);
     spl_clib_reg(vm, (char *)"astarReadMap" , my_astarReadMap      ,  0);
     spl_clib_reg(vm, (char *)"astarReadMapValue" , my_astarReadMapValue  ,  0);
     spl_clib_reg(vm, (char *)"astarInit" , my_astarInit      ,  0);
     spl_clib_reg(vm, (char *)"tmpobjInit" , my_tmpobjInit    ,  0);
    
     // load the standard spl qcake library
     char *spl_stdlib_code = (char *)spl_malloc_file("spl_stdlib.spl", 0);
     assert(spl_stdlib_code != NULL);
     spl_eval(vm, 0, strdup("stdlib"), spl_stdlib_code);
     free(spl_stdlib_code);
 }

 void splPrg::compile(void)
 {
  spl_source = (char *)spl_malloc_file(prgsrc,0);
  as = spl_asm_create();
  if(spl_compiler(as,spl_source,prgsrc,spl_malloc_file,1))
  {
    spl_asm_add(as,SPL_OP_HALT,0);
//     return 1;
  }
  else
  {
    spl_asm_add(as,SPL_OP_HALT,0);
    free(spl_source);
    spl_optimizer(as);
	  spl_task_setcode(task, spl_asm_dump(as));
    spl_asm_destroy(as);
    spl_eval(vm, 0, 0,"function freeze() { asm 'pushc 200' 'rlret'; }");
   }
 }
 
 void splPrg::update(void)
 {
  while ( task && task->code && on==1)
  {
   spl_gc_maybe(vm);
   task = spl_schedule(task); 
   if(spl_exec(task)) break;
  }
 }

 void splPrg::TurnOn(void)
 {
   on = 1;
 }
 
 void splPrg::TurnOff(void)
 {
   on = 0;
 }

 splPrg::~splPrg()
 {
    spl_vm_destroy(vm);
 }
