//#define DEBUG_listen2_H_low
//#define DEBUG_sprite_H

// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************    S P R I T E   V E R W A L T U N G       ****************
// ***************                                            ****************
// ***************    Programmed in C++ for DOS && LINUX      ****************
// ***************                                            ****************
// ***************    Created by Jens Thiele August 1995      ****************
// ***************    Version 1.0                             ****************
// ***************                                            ****************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************

// *************************** Instructions ***********************************
// Don't include sprite01.H directly !!!
// If you want to use sprite01.H with 
// 1. DOS you must define makefordos sprites are restricted to 64kb
//    The included vga support is only 320x200x256 include File: scrdosvga.H
// 2. vgalib you must include File: scrsvgalib.H
// 3. X you must include File: scrX11.H

// ***************** KNOWN BUGS : *********************************************
// Some Identifier Lengths are longer than 32 characters.
// This will cause problems if the Identifier Lenght is restricted.
// (Borland C++ for DOS)

// Will be changed:
// - rechteck  xanz=1 || yanz=1 !!!
// - rechteckclip does not exist !!
// - copysprite(int x,int y,sprite_pcxtype *dest);
// - sprite_pcxtype  braucht einen change 

#ifndef _sprite_H
#define _sprite_H


// Benoetigte Includes : ******************************************************
// Benoetigte Includes : ******************************************************
// Benoetigte Includes : ******************************************************
// Benoetigte Includes : ******************************************************


#include <math.h>
#include "datei.H"
#include "listen2.H"
#include "vektor.H"
#include "typecheck.H"
#include <list>
#include <algorithm>


// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************
// ****************************************** Die Paletten Klasse *************

/// The palette entry class
class palentrytype
{
public:
  uint16 red;
  uint16 green;
  uint16 blue;
  int operator==(const palentrytype &entry) const;

  // Achtung nur wirklich sinnvoll bei kleinen Farbuntersschieden ansonsten NB: >=maxdif*maxdif
  float operator-(const palentrytype &entry) const;
  float farbtondif(const palentrytype &entry) const;
  float hue() const;
  void change(iotype *ioptr,int8 mode);
  void darkdown()
  {
    float f=red;
    f*=0.8;
    red=ftoi(f);
    f=green;
    f*=0.8;
    green=ftoi(f);
    f=blue;
    f*=0.8;
    blue=ftoi(f);
  }
};
machezeigerelemtype(palentry);
machekettetype(palentry);

/// The palette class
class palettetype
{
public:    
  // Typeinfo -Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  virtual const char *getheaderstring(){return headerstring;}

  palettetype();
  palettetype(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  palettetype(const char *dateiname,int8 mode=CFG_TEXT_MODE);
  //  palettetype(uint8 *palptr);

  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  uint8 remap(const palentrytype &entry) const;
  int16 find(const palentrytype &entry) const;
  void calc_black();
  void calc_white();
  uint8 black() const
  {
    return cblack;
  }
  uint8 white() const
  {
    return cwhite;
  }

  void cycle();
  void calc_darkdown()
  {
    for (uint8 akt=0;akt<anzentries;akt++)
      {
	palentrytype aktentry=palette[akt];
	aktentry.darkdown();
	darkdowntable[akt]=remap(aktentry);
      }
  }

  palentrytype palette[256];
  char darkdowntable[256];
  uint16 maxval;
  uint8 anzentries;
private:
  uint8 cblack;
  uint8 cwhite;
};


// Das Rechteck !!!!!!! :-) **************************************************
// Das Rechteck !!!!!!! :-) **************************************************
// Das Rechteck !!!!!!! :-) **************************************************
// Das Rechteck !!!!!!! :-) **************************************************
// Das Rechteck !!!!!!! :-) **************************************************
/// The rectangle class
class rechtecktype
{
public:
  // Typeinfo -Achtung statisch wird nicht vererbt !!! =>benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  virtual const char *getheaderstring();

  // middle x
  int32 mx; 
  // middle y
  int32 my; 
  // x size (width)
  int32 sx; 
  // y size (height)
  int32 sy; 
  // load save
  virtual void change(iotype *ioptr,int8 mode); 
  
  // is point in rectangle ? 1=yes 0=no
  inline int punktinrechteck(int32 x,int32 y) const;

  // rotate and zoom rectangle
  rechtecktype *rotate_rechteck(const float winkel,const float zoom); 
  // merge to rectangles (the smallest rectangle which includes both)
  void addrechteck(const rechtecktype &other); 
  // subtract a rectangle (the biggest rectangle which doesn't contain the other)
  bool subrechteck(const rechtecktype &other); 


  rechtecktype(){};
  rechtecktype(int _mx,int _my,int _sx,int _sy) : mx(_mx),my(_my),sx(_sx),sy(_sy){}
protected:
  // 1=Coord in Sprite
  inline int xcoordinrechteck(int32 x) const;
  inline int ycoordinrechteck(int32 y) const;

private:
  void calcsize(const float winkel,const float zoom,int32 &_sx,int32 &_sy);
  void calcmitte(const float winkel,const float zoom,int32 &_mx,int32 &_my);
};

inline int rechtecktype::punktinrechteck(int32 x,int32 y) const
{
  return (xcoordinrechteck(x)&&ycoordinrechteck(y));
}

inline int rechtecktype::xcoordinrechteck(int32 x) const
{
    return ((x+mx>=0)&&(x+mx<sx));
}

inline int rechtecktype::ycoordinrechteck(int32 y) const
{
    return ((y+my>=0)&&(y+my<sy));
}

ostream& operator<<(ostream &ost,const rechtecktype &r);



// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********
// ****************************************** Das Allgemeine Sprite **********

// ******************************************* Sprite Aufbau: ****************
//   string: Art d. Sprites
//   int32:      X-Breite      
//   int32:      Y-Breite      
//   int32:      Mitte X       
//   int32:      Mitte Y       
//   int32:      Pointer auf Sprite
//   int32:      Pointer auf Routine copysprite      --> sprite_lineartype
//   int32:      Pointer auf Routine copysprite_clip --> sprite_lineartype
//   int32:      Pointer auf Routine save
// ****************************************************************************


class sprite_lineartype;                   //Forward
class sprite_linear_transparenttype;       //Forward
class sprite_kette_iqtype;                 //Forward 

/// The base spritetype (declares the routines all sprites (should) have
class spritetype : public zeigerelem_iqtype<spritetype>, public rechtecktype
{
public:
  char *sprite; // Pointer to sprite data (8-Bit => depends upon a palette)

  // Init/Deinit ***********************************************************
  spritetype();
  virtual ~spritetype();

  // Spezial routine um objekte mit abgeleiteten virtuellen routinen einheitlich zu erstellen !!
  // wird in listen2.H verwendet (kette_iqtype)
  // erstellt einen spritetype aus einem stream 
  // (und erkennt anhand eines headerstrings was fuer ein sprite es ist)
  static spritetype *create(iotype *ioptr,int8 mode); // create a sprite from iotype
  static spritetype *create(char *name); // create sprite from file

  // Pseudoroutinen die von den Erben ueberlagert werden ****************
  // bzw. deren Pointer bei dynamischen Objekten verbogen werden ********
  
  /// paint a sprite into another
  // copy sprite into a linear sprite and clip
  virtual void copysprite_clip(int x,int y,sprite_lineartype *dest,uint32 index=0); 
  // copy sprite into a rectangle (in a linear sprite) and clip
  virtual void copysprite_clip_to(int ,int ,sprite_lineartype *,const rechtecktype &,uint32=0)=0; 
  // copy sprite into a rectangle and zoom to maxpect
  void copysprite_maxpect_to(sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0)
    {
      float zoom1=float(rect.sx)/float(sx);
      float zoom2=float(rect.sy)/float(sy);
      float zoom;
      if (zoom1<zoom2)
	zoom=zoom1;
      else
	zoom=zoom2;
      copysprite_rotate_clip_to(-rect.mx+rect.sx/2,-rect.my+rect.sy/2,0,zoom,dest,rect,index);
    }
  
  // Get a pixel out of a sprite (returns 0 if point is in sprite otherwise -1)
  virtual int getpixel_clip(int x,int y,char *farbe,uint32 index=0)=0; 
  
  // Sprite rotate
  // todo besser machen aber erstmal so !
  // this just calls copysprite_rotate_clip_to
  virtual void copysprite_rotate_clip(int x,int y,float winkel,float zoom,sprite_lineartype *dest,uint32 index=0);
  virtual void copysprite_rotate_clip_to(int x,int y,float winkel,float zoom,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);

  // Attention this is not yet defined for all types => don't use it
  virtual spritetype *rotate(float winkel,float zoom, uint32=0, char=255)=0;

  // load and save (save works for all sprites?)
  virtual void change(iotype *ioptr,int8 mode)=0;
  // Show the sprite => only interesting if the sprite is on a physical screen
  virtual void map(){}   
  // Show rectangle of the sprite => only interesting if the sprite is on a physical screen
  virtual void map(const rechtecktype &){} 
protected:
  // error output 
  void fehler(char *string); 
private:
  /// Data important for copysprite_rotate_clip (this is a caching implementation)
  // old sprite direction
  float oldwinkel;
  // old zoom factor 
  float oldzoom; 
  // cached rotated sprite (NULL=>NONE)
  spritetype *oldsprite; 
};



// *******************************************************+ Spriteverwaltung
// *******************************************************+ Spriteverwaltung
// *******************************************************+ Spriteverwaltung
// *******************************************************+ Spriteverwaltung
// *******************************************************+ Spriteverwaltung
// *******************************************************+ Spriteverwaltung

/// List (see also listen2.H) which maps spritenames onto sprites (to load every sprite only once)
/// This is the userinterface
class sprite_kette_iqtype : public kette_iqtype<spritetype>
{
public:
  spritetype *make_elementadress(const char *name,int8 mode=CFG_TEXT_MODE);
  palettetype *paletteptr;
  sprite_kette_iqtype(){paletteptr=NULL;}
  sprite_kette_iqtype(const char *palname);
  ~sprite_kette_iqtype();
};

extern sprite_kette_iqtype *allsprites_ketteptr;
void init_allsprites_kette(const char *palname);
void deinit_allsprites_kette();


// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************
// ****************************************** Das Lineare Sprite *************


// ******************************************* Linear_Sprite-Datei Aufbau: ***
/*
   int32: X-Breite  --\
   int32: Y-Breite  ---\__ Header
   int32: Mitte X   ---/
   int32: Mitte Y   --/

   char : Bildpunkt --\
   char : Bildpunkt ---\
    :               ----\
    :               ------ Bild als RAW anz Bytes=X-Breite*Y-Breite
    :               ----/
    :               ---/
   char : Bildpunkt --/

 [ char : Transparente Farbe ] nur bei Transparenten Sprites
                               (s.h Konstruktor von
                                sprite_linear_transparenttype)
*/
// ***************************************************************************

/// The linear sprites base type 
/// All sprites with linear pixmap buffers
class sprite_lineartype : public spritetype 
{
public:
  /* todo
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();
  */

  // Routinen *******************************************************
  // Paint point 
  inline void putpixel(int x,int y,char farbe);
  // Paint point and clip
  void putpixel_clip(int x,int y,char farbe);
  void putpixel_clip_to(int x,int y,char farbe,const rechtecktype &rect);

  // Punkt malen und clippen !!! todo
  //  void putpixel_clip_to(int x,int y,char farbe,const rechtecktype &rect);

  // get Point
  inline char getpixel(int x,int y,uint32=0);
  // Punkt holen und clippen !!!
  int getpixel_clip(int x,int y,char *farbe,uint32 =0);
  // Verdunkelt einen Punkt (benutzt Palette der allsprites_kette !)
  inline void darkdownpixel(int x,int y);
  // Farbe in Sprite NB: true wenn farbe in sprite
  char farbeinsprite(char farbe);
  // Horizontale Linie malen
  void hline(int x1,int x2,int y,char farbe);
  // Horizontale Linie malen und clippen !!!
  void hline_clip(int x1,int x2,int y,char farbe);
  // Vertikale Linie malen 
  void vline(int x,int y1,int y2,char farbe);
  // Vertikale Linie malen und clippen 
  void vline_clip(int x,int y1,int y2,char farbe);
  // Kreis malen
  void kreis(int x,int y,int radius,char farbe);
  // Kreis malen und clippen !!!
  void kreis_clip(int x,int y,int radius,char farbe);
  // Kreisflaeche malen
  void kreis_flaeche(int x,int y,int radius,char farbe);
  // Kreisflaeche malen und clippen !!! 
  // NB: ==0 => kreis bedeckt das ganze sprite ==1 =>kreis ganz ausserhalb != =>sonst
  int kreis_flaeche_clip(int x,int y,int radius,char farbe);
  // Sprite mit einer Farbe clearen
  inline void clearsprite(char farbe);
  // Rechteck in Sprite malen
  void malerechteck(int x1,int y1,int xanz,int yanz,char farbe);
  // Rechteck in Sprite malen und clippen
  void malerechteck_clip(int x1,int y1,int xanz,int yanz,char farbe);
  // Rechteckflaeche in Sprite malen
  void malerechteck_flaeche(int x1,int y1,int xanz,int yanz,char farbe);
  // Rechteckflaeche in Sprite malen und clippen
  void malerechteck_flaeche_clip(int x1,int y1,int xanz,int yanz,char farbe);
  // true (!=0) => kein Punkt ist in beiden Rechtecken !!
  // Achtung:  x1<=x2 && y1<=y2
  char rechteckcheck(int x1,int y1,int x2, int y2);
  // Spritegroesse veraendern ! => realloc Inhalt nicht definiert
  void resize(int sxneu,int syneu);
  // Spritegroesse veraendern ! => realloc Erg.: Sprite in Farbe
  void resize(int sxneu,int syneu,char farbe);
  // Spritecheck ! Hat jemand uebers Ende geschrieben ?  !=0 => Fehler
  int spritecheck();
  // Fuellen
  void fuellen(int x,int y,char farbe);
  // raster  VB: groesse teilbar durch vier !!! 
  void raster(uint32 wert);

  // Sprite rotate
  virtual spritetype *rotate(float winkel,float zoom,uint32=0,char trans=255);


  // Show on Screen (only for sprite_linear_screentypes this has an effect)
  virtual void map(){}
  // Show Part of Screen
  virtual void map_box(int32 _x,int32 _y,int32 _sx,int32 _sy){}
  virtual void map(const rechtecktype &r){map_box(-r.mx,-r.my,r.sx,r.sy);}

protected:
  // Init ***********************************************************
  // Sprite initen
  sprite_lineartype(int _sx,int _sy,int _mx,int _my);
  // Einfarbiges Sprite initen
  sprite_lineartype(int _sx,int _sy,int _mx,int _my,char _farbe);
  // Standardkonstruktor
  sprite_lineartype();
    

  // Sprite laden/saven
  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  // Sprites Drehen !!!
  void ROTATE_rotatetoexisting(sprite_lineartype *dest,sprite_lineartype *source,
			       float winkel,float zoom,char trans);
  sprite_linear_transparenttype *ROTATE_generatenewsprite(sprite_lineartype *source,
							  float winkel,float zoom,char trans);
  // Sprite initen
  void initspritedat(int _sx,int _sy,int _mx,int _my);

private:

  struct headertype{
    int32 sx;
    int32 sy;
    int32 mx;
    int32 my;
  };
  
  // Liefert Adresse auf Punkt im Sprite
  inline char *calcadresse(int x,int y);
};

inline void sprite_lineartype::putpixel(int x,int y,char farbe)
{
	*(calcadresse(x,y))=farbe;
}

inline char sprite_lineartype::getpixel(int x,int y,uint32)
{
	return(*(calcadresse(x,y)));
}

inline void sprite_lineartype::darkdownpixel(int x,int y)
{
  char *akt=calcadresse(x,y);
  *akt=allsprites_ketteptr->paletteptr->darkdowntable[uint8(*akt)];
}


inline void sprite_lineartype::hline(int x1,int x2,int y,char farbe)
{
	char *dest=calcadresse(x1,y);
	int anz=x2-x1;
	anz++;
	memset(dest,farbe,anz);
}

inline void sprite_lineartype::vline(int x,int y1,int y2,char farbe)
{
  char *dest=calcadresse(x,y1);
  int anz=y2-y1;
  anz++;
  while (anz)
    {
      *dest=farbe;
      dest+=sx;
      anz--;
    }
}

inline void sprite_lineartype::clearsprite(char farbe)
{
  memset(sprite,farbe,(int32)sx*(int32)sy);
}

// ************************************************* Private

inline char *sprite_lineartype::calcadresse(int x,int y)
{
    return(sprite+mx+my*sx+x+y*sx);
}





// Nichttransparente Lineare Sprites ****************************************
// Nichttransparente Lineare Sprites ****************************************
// Nichttransparente Lineare Sprites ****************************************
// Nichttransparente Lineare Sprites ****************************************
// Nichttransparente Lineare Sprites ****************************************
// Nichttransparente Lineare Sprites ****************************************

class sprite_linear_nontransparenttype : public sprite_lineartype
{
// Public Funktionen ************************************************
// Public Funktionen ************************************************
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Init ***********************************************************
  // Sprite laden !!
  sprite_linear_nontransparenttype(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  // Sprite initen
  sprite_linear_nontransparenttype(int _sx,int _sy,int _mx,int _my);
  // Einfarbiges Sprite initen
  sprite_linear_nontransparenttype(int _sx,int _sy,int _mx,int _my,char _farbe);
protected:
  sprite_linear_nontransparenttype();


  // Deinit *********************************************************
  // Gibt Speicher frei !!
  //~sprite_linear_nontransparenttype(){};
  
public:
  // Routinen *******************************************************
  // Sprite kopieren
  void copysprite(int x,int y,sprite_lineartype *dest,uint32=0);
  void copysprite_clip(int x,int y,sprite_lineartype *dest,uint32=0);
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);
  
  
  // Sprite rotaten 
  spritetype *rotate(float winkel,float zoom,uint32,char trans=255);
  // Sprite laden/speichern (bis jetzt genau die von sprite_lineartype !)
  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  
  // Private Funktionen ***********************************************
  // Private Funktionen ***********************************************
private:
};



// Nichttransparente Lineare Sprites !!! PPM FORMAT !!! ******************************
// Nichttransparente Lineare Sprites !!! PPM FORMAT !!! ******************************
// Nichttransparente Lineare Sprites !!! PPM FORMAT !!! ******************************
// Nichttransparente Lineare Sprites !!! PPM FORMAT !!! ******************************

class sprite_ppmtype : public sprite_linear_nontransparenttype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !=> benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
};

// Lineare Transparente Sprites *********************************************
// Lineare Transparente Sprites *********************************************
// Lineare Transparente Sprites *********************************************
// Lineare Transparente Sprites *********************************************
// Lineare Transparente Sprites *********************************************
// Lineare Transparente Sprites *********************************************

class sprite_linear_transparenttype : public sprite_lineartype
{
  // Public Funktionen ************************************************
  // Public Funktionen ************************************************
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  char transcolor;

  // Init ***********************************************************
  // Sprite laden !!
  sprite_linear_transparenttype(iotype *ioptr,int8 mode=CFG_TEXT_MODE);

  // Sprite initen
  sprite_linear_transparenttype(int _sx,int _sy,int _mx,int _my,char _transcolor=255);
    
  // Einfarbiges Sprite initen
  sprite_linear_transparenttype(int _sx,int _sy,int _mx,int _my,char _farbe,char _transcolor);
    
  // Deinit *********************************************************
  // Bis jetzt keine Funktion !!
  // ~sprite_linear_transparenttype() {};
  
  
  // Routinen *******************************************************
  // Sprite kopieren
  void copysprite(int x,int y,sprite_lineartype *dest,uint32=0);
  void copysprite_clip(int x,int y,sprite_lineartype *dest,uint32=0);
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);
  
  //  rotate
  //  spritetype *rotate(float winkel,float zoom,uint32);    
  spritetype *rotate(float winkel,float zoom,uint32,char);
  
  // laden /speichern
  void change(iotype *ioptr,int8 mode=CFG_TEXT_MODE);
  
  // Minimiere transparentes sprite
  void minimize();

  // Generiere Zufallslandschaft spaeter ueberdenken !
  void putrandompixel(int x,int y,int basis,int scale);
  void randomrechteck(int x1,int y1,int x2,int y2,int steigung);
  void randomsprite();

// Private Funktionen ***********************************************
// Private Funktionen ***********************************************
private:
};









// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************
// *********************************** Das Koordinaten Sprite *****************


class sprite_coordedtype : public spritetype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  sprite_coordedtype();  
  sprite_coordedtype(iotype *ioptr,int8 mode);
  ~sprite_coordedtype();
  
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index);
  void copysprite_rotate_clip_to(int x,int y,float winkel,float zoom,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);
  
  int getpixel_clip(int x,int y,char *farbe,uint index32);
  // Sprite rotate todo !!!!!
  spritetype *rotate(float,float,uint32,char=255)
  {fehler("Routine rotate n. def. !");return NULL;};
  void change(iotype *ioptr,int8 mode);
protected:
  string spritename;
  int posx;
  int posy;
  spritetype *spriteptr;

};


// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************
// *********************************** Das Modifizierte Sprite *****************

class sprite_modifiedtype : public sprite_coordedtype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  sprite_modifiedtype();  
  ~sprite_modifiedtype();
  
  void change(iotype *ioptr,int8 mode);
private:
  float modwinkel,modzoom;

};

// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************
// **************************************** Das Index-Sprite ******************

class sprite_indextype : public spritetype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  sprite_indextype();
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index);
  int getpixel_clip(int x,int y,char *farbe,uint32 index);
  // Sprite rotate
  void copysprite_rotate_clip_to(int x,int y,float winkel,float zoom,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);
  
  spritetype *rotate(float winkel,float zoom,uint32 index,char trans=255);
  void change(iotype *ioptr,int8 mode);
  int32 anzsprites()
  {
    return sprite_kette_iq.anzzeigerelem;
  }
  protected:
  sprite_kette_iqtype sprite_kette_iq;
};

// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************
// **************************************** Das Movie-Sprite ******************

class displaytime_zeigerelemtype : public zeigerelem_changetype<displaytime_zeigerelemtype>
{
public:
  uint32 display_ms;
  void change(iotype *ioptr,int8 mode);
};
typedef kette_changetype<displaytime_zeigerelemtype> displaytime_kettetype;


class sprite_movietype : public sprite_indextype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  sprite_movietype();
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index);
  int getpixel_clip(int x,int y,char *farbe,uint32 index);
  // Sprite rotate
  void copysprite_rotate_clip_to(int x,int y,float winkel,float zoom,sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);

  spritetype *rotate(float winkel,float zoom,uint32 index,char trans=255);
  void change(iotype *ioptr,int8 mode);  
  uint32 getloop();
  int repeat;
private:
  uint32 mspassed;
  displaytime_kettetype displaytime_kette;
  displaytime_zeigerelemtype *akt_displaytimeptr;
  uint32 aktelemnr;
  uint32 loop;

  void init();
  uint32 calcindex(uint32 index);
};



// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************
// **************************************** Das Puzzle-Sprite *****************

// Beim copysprite !!!:
// spaeter erst einen Rechteckecheck ob uebrhaupt drin !
// aus dem puzzle Sprite muss ein Sprite werden => mx,my,sx,sy
// muessen sinnvolle werte bekommen !

// **** Puzzleteile ***********************************************************
// **** Puzzleteile ***********************************************************



class sprite_puzzletype : public spritetype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  sprite_puzzletype();
  sprite_puzzletype(iotype *ioptr,int8 mode);
  ~sprite_puzzletype();
  void copysprite_clip_to(int x,int y,sprite_lineartype *dest,const rechtecktype &rect,uint32 index);

  void copysprite_rotate_clip_to(int x,int y,float winkel,float zoom,
			      sprite_lineartype *dest,const rechtecktype &rect,uint32 index=0);

  int getpixel_clip(int x,int y,char *farbe,uint32 index);

  // Sprite rotate
  // Geht net weil jedes sprite ein zeigerelem_iqtype sein muss !!! todo !!!
  spritetype *rotate(float,float,uint32,char=255)
  {fehler("Routine rotate n. def. !");return NULL;};

  void change(iotype *ioptr,int8 mode);

private:
  // Kette enthaelt alle Spritepositionen ( s.h. lands/schlacht.lan)
  sprite_kette_iqtype sprite_kette_iq;
  spritetype *lastspriteptr;
};






// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************
// ****************************************** Das PCX-Sprite *****************


// ACHTUNG!!  Diese Klasse ist Obermuell !!!!!!!!!!!!!!!!
// => Benutze NIE PCX-Sprites :-)))))


class sprite_pcxtype : public spritetype
{
public:
  // Typeinfo - Achtung statisch wird nicht vererbt !!! => benutze getheaderstring() muss aber public sein!
  static const char *headerstring;
  const char *getheaderstring();

  // Init ***************************************************************
  // Reine PCX-Bildinfo laden !!! Nicht verwenden !!! 
  // Dazu gehoerige Routinen verwenden !
  sprite_pcxtype(iotype *ioptr,int32 kompsize,int _sx,int _sy,int _mx,int _my);
  
  // Routinen ***********************************************************
  // Male Sprite
  void copysprite(int x,int y,sprite_lineartype *dest,uint32=0);
  // todo
  void copysprite_clip_to(int,int,sprite_lineartype *,const rechtecktype &,uint)
  {fehler("sprite_pcxtype::function copysprite_clip_to n. def. !");};
  //todo
  int getpixel_clip(int,int,char *,uint32=0)
  {fehler("Routine getpixel_clip n. def. !");return 0;};
  // todo    
  void change(iotype *,int8)
  {fehler("Routine change n. def. !");}
  // todo
  spritetype *rotate(float,float,uint32,char=255)
  {fehler("Routine rotate n. def. !");return NULL;};

private:
};







// ***************************************************** Ladepcx- Bild ****

sprite_pcxtype *ladepcx_to_sprite_pcxtype(iotype *ioptr,int mx,int my);

sprite_linear_nontransparenttype *ladepcx_to_sprite_linear_nontransparenttype
(iotype *ioptr,int mx,int my);

sprite_linear_transparenttype *ladepcx_to_sprite_linear_transparenttype
(iotype *ioptr,int mx,int my,char transcolor=255);

// Erstellt einen palettetype !!!
palettetype *ladepcxpalette_to_palettetype(iotype *ioptr);

// Forward
class screentype;
class layertype;

class layer_spritetype
{
public:
  layer_spritetype(screentype *_scrptr,layertype *_layer,spritetype *_sprite,int _x=0,int _y=0,float _dir=0,float _zoom=1) 
    : screenptr(_scrptr),layer(_layer),sprite(_sprite),x(_x),y(_y),dir(_dir),zoom(_zoom)
  {
    alloced=false;
    calc_rectangle();
    paint();
  }
  layer_spritetype(screentype *_scrptr,layertype *_layer,const char *spritename,int _x=0,int _y=0,float _dir=0,float _zoom=1) 
    : screenptr(_scrptr),layer(_layer),x(_x),y(_y),dir(_dir),zoom(_zoom)
  {
    sprite=allsprites_ketteptr->make_elementadress(spritename);
    alloced=true;
    calc_rectangle();
    paint();
  }
  ~layer_spritetype();
  
  void paint();

  void paint_to(const rechtecktype &rect);

  void modify_sprite(int _x,int _y,float _dir=0,float _zoom=1);
  rechtecktype get_back(){return back;}
  layertype *get_layer(){return layer;}
private:
  void calc_rectangle();

  screentype *screenptr;
  layertype *layer;
  spritetype *sprite;
  int x,y;
  float dir,zoom;
  rechtecktype back;
  bool alloced;
};

/// layer object
/// before use the allsprites_kette must be initialised (init_allsprites_kette)
class layertype
{
public:
  layertype(screentype *_screenptr) : screenptr(_screenptr){}
  
  layer_spritetype *add_sprite(const char *spritename,int _x=0,int _y=0,float _dir=0,float _zoom=1);
  layer_spritetype *add_sprite(spritetype *sprite,int _x=0,int _y=0,float _dir=0,float _zoom=1);
  
  void del_sprite(layer_spritetype *sprite);
  void paint_layer(const rechtecktype &rect);
  void paint_layers_below(const rechtecktype &rect);
  void paint_layers_above(const rechtecktype &rect);
private:
  list<layer_spritetype *> sprites;
  screentype *screenptr;
};

/// screen object
/// this is to use layers based on one sprite as drawable
/// container for the layers
class screentype
{
public:
  screentype(sprite_lineartype *_spriteptr) : spriteptr(_spriteptr){}

  layertype *add_layer();
  /*
  void del_layer(){}
  void raise_layer(layertype *layer){}
  void lower_layer(layertype *layer){}*/

  void paint_layers_below(layertype *layer, const rechtecktype &rect);
  void paint_layers(const rechtecktype &rect);
  void paint_layers_above(layertype *layer, const rechtecktype &rect);
  sprite_lineartype *get_drawable();
  void map(){spriteptr->map();}
  void map(const rechtecktype &r){spriteptr->map(r);}
private:
  sprite_lineartype *spriteptr;
  list<layertype *> layers;
};

#endif





