source code

EXPORT GameApi::PT GameApi::PointApi::point(float x, float y, float z)

{

  return add_point(e, x,y,z);

}

EXPORT GameApi::PT GameApi::PointApi::point(float x, float y, float z)

{

  return add_point(e, x,y,z);

}

EXPORT GameApi::PT GameApi::PointApi::point(float x, float y, float z)

{

  return add_point(e, x,y,z);

}

EXPORT GameApi::PT GameApi::PointApi::point(float x, float y, float z)

{

  return add_point(e, x,y,z);

}

class GradientBitmap2 : public Bitmap<Color>

{

public:

  GradientBitmap2(Point2d pos_1, Point2d pos_2, unsigned int color_1, unsigned int color_2, int sx, int sy) : pos_1(pos_1), pos_2(pos_2), color_1(color_1), color_2(color_2), sx(sx), sy(sy) { 

    u_x = Point(pos_2.x, pos_2.y, 0.0)-Point(pos_1.x, pos_1.y, 0.0);

    v = u_x.Dist();

    v = v*v;

  }

  void Prepare() { }

  virtual int SizeX() const { return sx; }

  virtual int SizeY() const { return sy; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << "gradient" << std::endl;

    Vector u = Point(x, y, 0.0)-Point(pos_1.x, pos_1.y, 0.0);

    float val = Vector::DotProduct(u, u_x);

    val /= v;

    //val /= v; 

    // now [0.0 .. 1.0]

    if (val<0.0) return 0;

    if (val>1.0) return 0;

    return Color(Color::CubicInterpolate(color_1, color_2, val));

  }



private:

  Point2d pos_1;

  Point2d pos_2;

  unsigned int color_1;

  unsigned int color_2;

  int sx,sy;

  Vector u_x;

  float v;

};

EXPORT GameApi::BM GameApi::BitmapApi::gradient(PT pos_1, PT pos_2, unsigned int color_1, unsigned int color_2, int sx, int sy)

{

  Point *pos_1a = find_point(e, pos_1);

  Point *pos_2a = find_point(e, pos_2);

  Point2d pos_1b = { pos_1a->x, pos_1a->y };

  Point2d pos_2b = { pos_2a->x, pos_2a->y };

  return add_color_bitmap2(e, new GradientBitmap2(pos_1b, pos_2b, color_1, color_2, sx,sy));

}

class GradientBitmap2 : public Bitmap<Color>

{

public:

  GradientBitmap2(Point2d pos_1, Point2d pos_2, unsigned int color_1, unsigned int color_2, int sx, int sy) : pos_1(pos_1), pos_2(pos_2), color_1(color_1), color_2(color_2), sx(sx), sy(sy) { 

    u_x = Point(pos_2.x, pos_2.y, 0.0)-Point(pos_1.x, pos_1.y, 0.0);

    v = u_x.Dist();

    v = v*v;

  }

  void Prepare() { }

  virtual int SizeX() const { return sx; }

  virtual int SizeY() const { return sy; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << "gradient" << std::endl;

    Vector u = Point(x, y, 0.0)-Point(pos_1.x, pos_1.y, 0.0);

    float val = Vector::DotProduct(u, u_x);

    val /= v;

    //val /= v; 

    // now [0.0 .. 1.0]

    if (val<0.0) return 0;

    if (val>1.0) return 0;

    return Color(Color::CubicInterpolate(color_1, color_2, val));

  }



private:

  Point2d pos_1;

  Point2d pos_2;

  unsigned int color_1;

  unsigned int color_2;

  int sx,sy;

  Vector u_x;

  float v;

};

EXPORT GameApi::BM GameApi::BitmapApi::gradient(PT pos_1, PT pos_2, unsigned int color_1, unsigned int color_2, int sx, int sy)

{

  Point *pos_1a = find_point(e, pos_1);

  Point *pos_2a = find_point(e, pos_2);

  Point2d pos_1b = { pos_1a->x, pos_1a->y };

  Point2d pos_2b = { pos_2a->x, pos_2a->y };

  return add_color_bitmap2(e, new GradientBitmap2(pos_1b, pos_2b, color_1, color_2, sx,sy));

}

EXPORT GameApi::BM GameApi::BitmapApi::scale_bitmap_fullscreen(EveryApi &ev, BM orig)

{

  int sx = ev.mainloop_api.get_screen_sx();

  int sy = ev.mainloop_api.get_screen_sy();

  CBM cbm = ev.cont_bitmap_api.from_bitmap(orig, 1.0, 1.0);

  BM ret = ev.cont_bitmap_api.to_bitmap(cbm, sx,sy);

  return ret;

}

EXPORT GameApi::BM GameApi::BitmapApi::scale_bitmap_fullscreen(EveryApi &ev, BM orig)

{

  int sx = ev.mainloop_api.get_screen_sx();

  int sy = ev.mainloop_api.get_screen_sy();

  CBM cbm = ev.cont_bitmap_api.from_bitmap(orig, 1.0, 1.0);

  BM ret = ev.cont_bitmap_api.to_bitmap(cbm, sx,sy);

  return ret;

}

EXPORT GameApi::ML GameApi::SpriteApi::vertex_array_render(EveryApi &ev, BM bm)

{

  //GameApi::VA va = create_vertex_array(bm);

  GameApi::ML ml = render_sprite_vertex_array_ml(ev, bm);

  return ml;

}

EXPORT GameApi::ML GameApi::SpriteApi::vertex_array_render(EveryApi &ev, BM bm)

{

  //GameApi::VA va = create_vertex_array(bm);

  GameApi::ML ml = render_sprite_vertex_array_ml(ev, bm);

  return ml;

}

class TurnTo2d : public MainLoopItem

{

public:

  TurnTo2d(GameApi::EveryApi &ev, MainLoopItem *next, Point2d tl, Point2d br) : ev(ev), next(next), tl(tl), br(br) {

  }

  void handle_event(MainLoopEvent &e)

  {

    next->handle_event(e);

  }

  void Prepare() { next->Prepare(); }

  void execute(MainLoopEnv &e)

  {

    static int inside_it = false;

    if (inside_it) { 

    g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

      next->execute(e); 

    g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

      return; 

    }



    inside_it = true;

    tl.x = e.screen_x;

    tl.y = e.screen_y;

    br.x = e.screen_width;

    br.y = e.screen_height;

    screen_x = ev.mainloop_api.get_screen_sx();

    screen_y = ev.mainloop_api.get_screen_sy();

    corner_x = ev.mainloop_api.get_corner_x();

    corner_y = ev.mainloop_api.get_corner_y();

    rect_sx = ev.mainloop_api.get_screen_rect_sx();

    rect_sy = ev.mainloop_api.get_screen_rect_sy();





  	float scale_x = 1.0;

	float scale_y = 1.0;

	if (g_event_screen_y!=-1) {

	  scale_x = float(g_event_screen_x)/float(screen_x);

	  scale_y = float(g_event_screen_y)/float(screen_y);

	}





    GameApi::SH sh = { e.sh_texture_2d };

    ev.shader_api.use(sh);

    ev.mainloop_api.switch_to_3d(false, sh, screen_x, screen_y);

    g_low->ogl->glViewport((corner_x+tl.x)*scale_x,(screen_y-corner_y-(br.y-tl.y))*scale_y, (br.x-tl.x)*scale_x, (br.y-tl.y)*scale_y);



    g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

    //int old_sh = e.sh_texture;

    MainLoopEnv ee = e;

    ee.sh_texture = e.sh_texture_2d;

    ee.in_MV = Matrix::Identity();

    //ee.env = e.env * Matrix::Translate(0.0,0.0,400.0);

    ee.is_2d = true;

    next->execute(ee);

    //e.sh_texture = old_sh;

    g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

    ev.mainloop_api.switch_to_3d(true, sh, screen_x, screen_y);

    g_low->ogl->glViewport(corner_x*scale_x,(screen_y-corner_y-rect_sy)*scale_y,rect_sx*scale_x, rect_sy*scale_y);

    inside_it = false;

  }



private:

  GameApi::EveryApi &ev;

  MainLoopItem *next;

  Point2d tl,br;

  int screen_x, screen_y;

  int corner_x, corner_y;

  int rect_sx, rect_sy;

};

EXPORT GameApi::ML GameApi::SpriteApi::turn_to_2d(EveryApi &ev, ML ml, float tl_x, float tl_y, float br_x, float br_y)

{

  MainLoopItem *next = find_main_loop(e, ml);

  Point2d tl = { tl_x, tl_y };

  Point2d br = { br_x, br_y };

  return add_main_loop(e, new TurnTo2d(ev,next,tl,br));

}

class TurnTo2d : public MainLoopItem

{

public:

  TurnTo2d(GameApi::EveryApi &ev, MainLoopItem *next, Point2d tl, Point2d br) : ev(ev), next(next), tl(tl), br(br) {

  }

  void handle_event(MainLoopEvent &e)

  {

    next->handle_event(e);

  }

  void Prepare() { next->Prepare(); }

  void execute(MainLoopEnv &e)

  {

    static int inside_it = false;

    if (inside_it) { 

    g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

      next->execute(e); 

    g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

      return; 

    }



    inside_it = true;

    tl.x = e.screen_x;

    tl.y = e.screen_y;

    br.x = e.screen_width;

    br.y = e.screen_height;

    screen_x = ev.mainloop_api.get_screen_sx();

    screen_y = ev.mainloop_api.get_screen_sy();

    corner_x = ev.mainloop_api.get_corner_x();

    corner_y = ev.mainloop_api.get_corner_y();

    rect_sx = ev.mainloop_api.get_screen_rect_sx();

    rect_sy = ev.mainloop_api.get_screen_rect_sy();





  	float scale_x = 1.0;

	float scale_y = 1.0;

	if (g_event_screen_y!=-1) {

	  scale_x = float(g_event_screen_x)/float(screen_x);

	  scale_y = float(g_event_screen_y)/float(screen_y);

	}





    GameApi::SH sh = { e.sh_texture_2d };

    ev.shader_api.use(sh);

    ev.mainloop_api.switch_to_3d(false, sh, screen_x, screen_y);

    g_low->ogl->glViewport((corner_x+tl.x)*scale_x,(screen_y-corner_y-(br.y-tl.y))*scale_y, (br.x-tl.x)*scale_x, (br.y-tl.y)*scale_y);



    g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

    //int old_sh = e.sh_texture;

    MainLoopEnv ee = e;

    ee.sh_texture = e.sh_texture_2d;

    ee.in_MV = Matrix::Identity();

    //ee.env = e.env * Matrix::Translate(0.0,0.0,400.0);

    ee.is_2d = true;

    next->execute(ee);

    //e.sh_texture = old_sh;

    g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

    ev.mainloop_api.switch_to_3d(true, sh, screen_x, screen_y);

    g_low->ogl->glViewport(corner_x*scale_x,(screen_y-corner_y-rect_sy)*scale_y,rect_sx*scale_x, rect_sy*scale_y);

    inside_it = false;

  }



private:

  GameApi::EveryApi &ev;

  MainLoopItem *next;

  Point2d tl,br;

  int screen_x, screen_y;

  int corner_x, corner_y;

  int rect_sx, rect_sy;

};

EXPORT GameApi::ML GameApi::SpriteApi::turn_to_2d(EveryApi &ev, ML ml, float tl_x, float tl_y, float br_x, float br_y)

{

  MainLoopItem *next = find_main_loop(e, ml);

  Point2d tl = { tl_x, tl_y };

  Point2d br = { br_x, br_y };

  return add_main_loop(e, new TurnTo2d(ev,next,tl,br));

}

class NoiseVectors : public Bitmap<Color>

{

public:

  NoiseVectors(int sx, int sy) : sx(sx), sy(sy) {}

  int SizeX() const { return sx; }

  int SizeY() const { return sy; }

  

  Color Map(int mx, int my) const

  {

    Random r;

    float xp = double(r.next())/r.maximum();

    float yp = double(r.next())/r.maximum();

    xp*=3.14159;

    yp*=3.14159*2.0;

    float x = 127*sin(xp)*cos(yp);

    float y = 127*sin(xp)*sin(yp);

    float z = 127*cos(xp);

    Color c2(128+int(x),128+int(y),128+int(z),255);

    return c2;    

  }

  void Prepare() { }

private:

  int sx,sy;

};

GameApi::BM GameApi::BitmapApi::noise_vectors(int sx, int sy)

{

  Bitmap<Color> *b = new NoiseVectors(sx,sy);

  BitmapColorHandle *handle2 = new BitmapColorHandle;

  handle2->bm = b;

  BM bm = add_bitmap(e, handle2);

  return bm;



}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class MulFB : public Bitmap<float>

{

public:

  MulFB(Bitmap<float> *f, float mul) : f(f),mul(mul) {}

  void Prepare() { f->Prepare(); }

  int SizeX() const { return f->SizeX(); }

  int SizeY() const { return f->SizeY(); }

  float Map(int x, int y) const { return mul*f->Map(x,y); }

private:

  Bitmap<float> *f;

  float mul;

};

GameApi::FB GameApi::BitmapApi::mul_fb(FB f, float mul)

{

  Bitmap<float> *fb1 = find_float_bitmap(e, f)->bitmap;

  return add_float_bitmap(e, new MulFB(fb1, mul));

};

template<class C>

class ConstantBitmap : public Bitmap<C>

{

public:

  ConstantBitmap(C c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  C Map(int , int ) const

  {

    return c;

  }

private:

  C c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap<Color>(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class ConstantBitmap_Color : public Bitmap<Color>

{

public:

  ConstantBitmap_Color(Color c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  Color Map(int , int ) const

  {

    return c;

  }

private:

  Color c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap_Color(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

template<class C>

class ConstantBitmap : public Bitmap<C>

{

public:

  ConstantBitmap(C c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  C Map(int , int ) const

  {

    return c;

  }

private:

  C c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap<Color>(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class ConstantBitmap_Color : public Bitmap<Color>

{

public:

  ConstantBitmap_Color(Color c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  Color Map(int , int ) const

  {

    return c;

  }

private:

  Color c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap_Color(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

template<class C>

class ConstantBitmap : public Bitmap<C>

{

public:

  ConstantBitmap(C c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  C Map(int , int ) const

  {

    return c;

  }

private:

  C c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap<Color>(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class ConstantBitmap_Color : public Bitmap<Color>

{

public:

  ConstantBitmap_Color(Color c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  Color Map(int , int ) const

  {

    return c;

  }

private:

  Color c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap_Color(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

template<class C>

class ConstantBitmap : public Bitmap<C>

{

public:

  ConstantBitmap(C c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  C Map(int , int ) const

  {

    return c;

  }

private:

  C c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap<Color>(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class ConstantBitmap_Color : public Bitmap<Color>

{

public:

  ConstantBitmap_Color(Color c, int x, int y) : c(c), x(x), y(y) { }

  void Prepare() { }



  int SizeX() const { return x; }

  int SizeY() const { return y; }

  Color Map(int , int ) const

  {

    return c;

  }

private:

  Color c;

  int x,y;

};

EXPORT GameApi::BM GameApi::BitmapApi::newbitmap(int sx, int sy, unsigned int color)

{

  ::Bitmap<Color> *b = new ConstantBitmap_Color(Color(color), sx,sy);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = b;

  BM bm = add_bitmap(e, handle);

  return bm;

  

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromGreen : public Bitmap<float>

{

public:

  BitmapFromGreen(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.g;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_green(BM bm)

{

  BitmapHandle *handle = find_bitmap(e, bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromGreen(*bmc);

  return add_float_bitmap(e, bm2);

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class Mandelbrot : public Bitmap<int>

{

public: // good values are x=[-2..1], y=[-1,1]

  Mandelbrot(bool julia, float start_x, float end_x, float start_y, float end_y, int sx, int sy, int count, float xx, float yy) : julia(julia), start_x(start_x), end_x(end_x), start_y(start_y), end_y(end_y),sx(sx), sy(sy), count(count), xx(xx), yy(yy) { }



  void Prepare() { }

  int SizeX() const { return sx; }

  int SizeY() const { return sy; }

  int Map(int x, int y) const

  {

    if (julia)

      {

	Point2d z;

	z.x = start_x + x*(end_x-start_x)/sx;

	z.y = start_y + y*(end_y-start_y)/sy;

	Point2d C;

	C.x = xx;

	C.y = yy;

	return RecRec(count, z,C);

      }

    else

      {

	Point2d z;

	z.x = xx;

	z.y = yy;

	Point2d C;

	C.x = start_x + x*(end_x-start_x)/sx;

	C.y = start_y + y*(end_y-start_y)/sy;

	return RecRec(count, z,C);

      }

  }

private:

  Point2d Rec(Point2d z, Point2d C) const

  {

    return Add(Mul(z,z), C);

  }

  int RecRec(int count, Point2d z, Point2d C) const

  {

    int i=0;

    for(;i<count;i++)

      {

	z = Rec(z,C);

	if (Dist2(z)>2.0*2.0)

	  return i;

      }

    return i;

  }

  float Dist2(Point2d p1) const

  {

    return p1.x*p1.x+p1.y*p1.y;

  }

  Point2d Add(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x+p2.x;

    r.y = p1.y+p2.y;

    return r;

  }

  Point2d Mul(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x*p2.x-p1.y*p2.y;

    r.y = p1.x*p2.y+p1.y*p2.x;

    return r;

  }



private:

  bool julia;

  float start_x, end_x;

  float start_y, end_y;

  int sx,sy;

  int count;

  float xx,yy;

};

class MapBitmapToColor : public Bitmap<Color>

{

public:

  MapBitmapToColor(int value1, int value2,

		   Color c1, Color c2,

		   Bitmap<int> &bm)

    : value1(value1), value2(value2),

      c1(c1), c2(c2), bm(bm)

  {

  }

  void Prepare() { bm.Prepare(); }



  int SizeX() const { return bm.SizeX(); }

  int SizeY() const { return bm.SizeY(); }

  Color Map(int x, int y) const

  {

    float val = (float)bm.Map(x,y);

    val -= float(value1);

    val /= float(value2-value1);

    //float f = float(val-value1)/(value2-value1);

    return Color::Interpolate(c1,c2, 1.0-val);

  }



private:

  int value1, value2;

  Color c1,c2;

  Bitmap<int> &bm;

};

class MemoizeBitmap : public Bitmap<Color>

{

public:

  MemoizeBitmap(Bitmap<Color> &bm) : bm(bm) 

  {

    

  }

  void Prepare() { 

    bm.Prepare();

    

    int width = bm.SizeX();

    int height = bm.SizeY();

    buf = BufferRef::NewBuffer(width, height);

    for(int j=0;j<height;j++)

      for(int i=0;i<width;i++)

	{

	  buf.buffer[i+j*buf.ydelta] = 0xfefefefe;

	}



  }



  ~MemoizeBitmap() { BufferRef::FreeBuffer(buf); }

  void MemoizeAll()

  {

    int sx=SizeX();

    int sy=SizeY();

    for(int x=0;x<sx;x++)

      for(int y=0;y<sy;y++)

	{

	  Map(x,y);

	}

  }

  virtual int SizeX() const { return buf.width; }

  virtual int SizeY() const { return buf.height; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << x << " " << y << std::endl;

    if (x<0 || x >= int(buf.width) || y <0 || y>=int(buf.height))

	return Color(0x00000000);

    if (buf.buffer[x+y*buf.ydelta] == 0xfefefefe)

      {

	Color c = bm.Map(x,y);

	unsigned int cc = c.Pixel();

	buf.buffer[x+y*buf.ydelta] = cc;

      }

    return Color(buf.buffer[x+y*buf.ydelta]);

  }



private:

  Bitmap<Color> &bm;

  BufferRef buf;

};

EXPORT GameApi::BM GameApi::BitmapApi::mandelbrot(bool julia,

{

  ::Bitmap<int> *b = new Mandelbrot(julia, start_x, end_x,

				      start_y, end_y,

				      sx,sy,

				      count,

				      xx,yy);

  ::Bitmap<Color> *b2 = new MapBitmapToColor(0, count, Color(255,255,255), Color(0,128,255), *b);

  ::EnvImpl *env = ::EnvImpl::Environment(&e);



  env->deletes.push_back(std::shared_ptr<void>(b));

  env->deletes.push_back(std::shared_ptr<void>(b2));

  ::Bitmap<Color> *m = new MemoizeBitmap(*b2);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m; 

  BM bm = add_bitmap(e, handle);

  return bm;  

}

class Mandelbrot : public Bitmap<int>

{

public: // good values are x=[-2..1], y=[-1,1]

  Mandelbrot(bool julia, float start_x, float end_x, float start_y, float end_y, int sx, int sy, int count, float xx, float yy) : julia(julia), start_x(start_x), end_x(end_x), start_y(start_y), end_y(end_y),sx(sx), sy(sy), count(count), xx(xx), yy(yy) { }



  void Prepare() { }

  int SizeX() const { return sx; }

  int SizeY() const { return sy; }

  int Map(int x, int y) const

  {

    if (julia)

      {

	Point2d z;

	z.x = start_x + x*(end_x-start_x)/sx;

	z.y = start_y + y*(end_y-start_y)/sy;

	Point2d C;

	C.x = xx;

	C.y = yy;

	return RecRec(count, z,C);

      }

    else

      {

	Point2d z;

	z.x = xx;

	z.y = yy;

	Point2d C;

	C.x = start_x + x*(end_x-start_x)/sx;

	C.y = start_y + y*(end_y-start_y)/sy;

	return RecRec(count, z,C);

      }

  }

private:

  Point2d Rec(Point2d z, Point2d C) const

  {

    return Add(Mul(z,z), C);

  }

  int RecRec(int count, Point2d z, Point2d C) const

  {

    int i=0;

    for(;i<count;i++)

      {

	z = Rec(z,C);

	if (Dist2(z)>2.0*2.0)

	  return i;

      }

    return i;

  }

  float Dist2(Point2d p1) const

  {

    return p1.x*p1.x+p1.y*p1.y;

  }

  Point2d Add(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x+p2.x;

    r.y = p1.y+p2.y;

    return r;

  }

  Point2d Mul(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x*p2.x-p1.y*p2.y;

    r.y = p1.x*p2.y+p1.y*p2.x;

    return r;

  }



private:

  bool julia;

  float start_x, end_x;

  float start_y, end_y;

  int sx,sy;

  int count;

  float xx,yy;

};

class MapBitmapToColor : public Bitmap<Color>

{

public:

  MapBitmapToColor(int value1, int value2,

		   Color c1, Color c2,

		   Bitmap<int> &bm)

    : value1(value1), value2(value2),

      c1(c1), c2(c2), bm(bm)

  {

  }

  void Prepare() { bm.Prepare(); }



  int SizeX() const { return bm.SizeX(); }

  int SizeY() const { return bm.SizeY(); }

  Color Map(int x, int y) const

  {

    float val = (float)bm.Map(x,y);

    val -= float(value1);

    val /= float(value2-value1);

    //float f = float(val-value1)/(value2-value1);

    return Color::Interpolate(c1,c2, 1.0-val);

  }



private:

  int value1, value2;

  Color c1,c2;

  Bitmap<int> &bm;

};

class MemoizeBitmap : public Bitmap<Color>

{

public:

  MemoizeBitmap(Bitmap<Color> &bm) : bm(bm) 

  {

    

  }

  void Prepare() { 

    bm.Prepare();

    

    int width = bm.SizeX();

    int height = bm.SizeY();

    buf = BufferRef::NewBuffer(width, height);

    for(int j=0;j<height;j++)

      for(int i=0;i<width;i++)

	{

	  buf.buffer[i+j*buf.ydelta] = 0xfefefefe;

	}



  }



  ~MemoizeBitmap() { BufferRef::FreeBuffer(buf); }

  void MemoizeAll()

  {

    int sx=SizeX();

    int sy=SizeY();

    for(int x=0;x<sx;x++)

      for(int y=0;y<sy;y++)

	{

	  Map(x,y);

	}

  }

  virtual int SizeX() const { return buf.width; }

  virtual int SizeY() const { return buf.height; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << x << " " << y << std::endl;

    if (x<0 || x >= int(buf.width) || y <0 || y>=int(buf.height))

	return Color(0x00000000);

    if (buf.buffer[x+y*buf.ydelta] == 0xfefefefe)

      {

	Color c = bm.Map(x,y);

	unsigned int cc = c.Pixel();

	buf.buffer[x+y*buf.ydelta] = cc;

      }

    return Color(buf.buffer[x+y*buf.ydelta]);

  }



private:

  Bitmap<Color> &bm;

  BufferRef buf;

};

EXPORT GameApi::BM GameApi::BitmapApi::mandelbrot(bool julia,

{

  ::Bitmap<int> *b = new Mandelbrot(julia, start_x, end_x,

				      start_y, end_y,

				      sx,sy,

				      count,

				      xx,yy);

  ::Bitmap<Color> *b2 = new MapBitmapToColor(0, count, Color(255,255,255), Color(0,128,255), *b);

  ::EnvImpl *env = ::EnvImpl::Environment(&e);



  env->deletes.push_back(std::shared_ptr<void>(b));

  env->deletes.push_back(std::shared_ptr<void>(b2));

  ::Bitmap<Color> *m = new MemoizeBitmap(*b2);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m; 

  BM bm = add_bitmap(e, handle);

  return bm;  

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class Mandelbrot : public Bitmap<int>

{

public: // good values are x=[-2..1], y=[-1,1]

  Mandelbrot(bool julia, float start_x, float end_x, float start_y, float end_y, int sx, int sy, int count, float xx, float yy) : julia(julia), start_x(start_x), end_x(end_x), start_y(start_y), end_y(end_y),sx(sx), sy(sy), count(count), xx(xx), yy(yy) { }



  void Prepare() { }

  int SizeX() const { return sx; }

  int SizeY() const { return sy; }

  int Map(int x, int y) const

  {

    if (julia)

      {

	Point2d z;

	z.x = start_x + x*(end_x-start_x)/sx;

	z.y = start_y + y*(end_y-start_y)/sy;

	Point2d C;

	C.x = xx;

	C.y = yy;

	return RecRec(count, z,C);

      }

    else

      {

	Point2d z;

	z.x = xx;

	z.y = yy;

	Point2d C;

	C.x = start_x + x*(end_x-start_x)/sx;

	C.y = start_y + y*(end_y-start_y)/sy;

	return RecRec(count, z,C);

      }

  }

private:

  Point2d Rec(Point2d z, Point2d C) const

  {

    return Add(Mul(z,z), C);

  }

  int RecRec(int count, Point2d z, Point2d C) const

  {

    int i=0;

    for(;i<count;i++)

      {

	z = Rec(z,C);

	if (Dist2(z)>2.0*2.0)

	  return i;

      }

    return i;

  }

  float Dist2(Point2d p1) const

  {

    return p1.x*p1.x+p1.y*p1.y;

  }

  Point2d Add(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x+p2.x;

    r.y = p1.y+p2.y;

    return r;

  }

  Point2d Mul(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x*p2.x-p1.y*p2.y;

    r.y = p1.x*p2.y+p1.y*p2.x;

    return r;

  }



private:

  bool julia;

  float start_x, end_x;

  float start_y, end_y;

  int sx,sy;

  int count;

  float xx,yy;

};

class MapBitmapToColor : public Bitmap<Color>

{

public:

  MapBitmapToColor(int value1, int value2,

		   Color c1, Color c2,

		   Bitmap<int> &bm)

    : value1(value1), value2(value2),

      c1(c1), c2(c2), bm(bm)

  {

  }

  void Prepare() { bm.Prepare(); }



  int SizeX() const { return bm.SizeX(); }

  int SizeY() const { return bm.SizeY(); }

  Color Map(int x, int y) const

  {

    float val = (float)bm.Map(x,y);

    val -= float(value1);

    val /= float(value2-value1);

    //float f = float(val-value1)/(value2-value1);

    return Color::Interpolate(c1,c2, 1.0-val);

  }



private:

  int value1, value2;

  Color c1,c2;

  Bitmap<int> &bm;

};

class MemoizeBitmap : public Bitmap<Color>

{

public:

  MemoizeBitmap(Bitmap<Color> &bm) : bm(bm) 

  {

    

  }

  void Prepare() { 

    bm.Prepare();

    

    int width = bm.SizeX();

    int height = bm.SizeY();

    buf = BufferRef::NewBuffer(width, height);

    for(int j=0;j<height;j++)

      for(int i=0;i<width;i++)

	{

	  buf.buffer[i+j*buf.ydelta] = 0xfefefefe;

	}



  }



  ~MemoizeBitmap() { BufferRef::FreeBuffer(buf); }

  void MemoizeAll()

  {

    int sx=SizeX();

    int sy=SizeY();

    for(int x=0;x<sx;x++)

      for(int y=0;y<sy;y++)

	{

	  Map(x,y);

	}

  }

  virtual int SizeX() const { return buf.width; }

  virtual int SizeY() const { return buf.height; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << x << " " << y << std::endl;

    if (x<0 || x >= int(buf.width) || y <0 || y>=int(buf.height))

	return Color(0x00000000);

    if (buf.buffer[x+y*buf.ydelta] == 0xfefefefe)

      {

	Color c = bm.Map(x,y);

	unsigned int cc = c.Pixel();

	buf.buffer[x+y*buf.ydelta] = cc;

      }

    return Color(buf.buffer[x+y*buf.ydelta]);

  }



private:

  Bitmap<Color> &bm;

  BufferRef buf;

};

EXPORT GameApi::BM GameApi::BitmapApi::mandelbrot(bool julia,

{

  ::Bitmap<int> *b = new Mandelbrot(julia, start_x, end_x,

				      start_y, end_y,

				      sx,sy,

				      count,

				      xx,yy);

  ::Bitmap<Color> *b2 = new MapBitmapToColor(0, count, Color(255,255,255), Color(0,128,255), *b);

  ::EnvImpl *env = ::EnvImpl::Environment(&e);



  env->deletes.push_back(std::shared_ptr<void>(b));

  env->deletes.push_back(std::shared_ptr<void>(b2));

  ::Bitmap<Color> *m = new MemoizeBitmap(*b2);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m; 

  BM bm = add_bitmap(e, handle);

  return bm;  

}

class Mandelbrot : public Bitmap<int>

{

public: // good values are x=[-2..1], y=[-1,1]

  Mandelbrot(bool julia, float start_x, float end_x, float start_y, float end_y, int sx, int sy, int count, float xx, float yy) : julia(julia), start_x(start_x), end_x(end_x), start_y(start_y), end_y(end_y),sx(sx), sy(sy), count(count), xx(xx), yy(yy) { }



  void Prepare() { }

  int SizeX() const { return sx; }

  int SizeY() const { return sy; }

  int Map(int x, int y) const

  {

    if (julia)

      {

	Point2d z;

	z.x = start_x + x*(end_x-start_x)/sx;

	z.y = start_y + y*(end_y-start_y)/sy;

	Point2d C;

	C.x = xx;

	C.y = yy;

	return RecRec(count, z,C);

      }

    else

      {

	Point2d z;

	z.x = xx;

	z.y = yy;

	Point2d C;

	C.x = start_x + x*(end_x-start_x)/sx;

	C.y = start_y + y*(end_y-start_y)/sy;

	return RecRec(count, z,C);

      }

  }

private:

  Point2d Rec(Point2d z, Point2d C) const

  {

    return Add(Mul(z,z), C);

  }

  int RecRec(int count, Point2d z, Point2d C) const

  {

    int i=0;

    for(;i<count;i++)

      {

	z = Rec(z,C);

	if (Dist2(z)>2.0*2.0)

	  return i;

      }

    return i;

  }

  float Dist2(Point2d p1) const

  {

    return p1.x*p1.x+p1.y*p1.y;

  }

  Point2d Add(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x+p2.x;

    r.y = p1.y+p2.y;

    return r;

  }

  Point2d Mul(Point2d p1, Point2d p2) const

  {

    Point2d r;

    r.x = p1.x*p2.x-p1.y*p2.y;

    r.y = p1.x*p2.y+p1.y*p2.x;

    return r;

  }



private:

  bool julia;

  float start_x, end_x;

  float start_y, end_y;

  int sx,sy;

  int count;

  float xx,yy;

};

class MapBitmapToColor : public Bitmap<Color>

{

public:

  MapBitmapToColor(int value1, int value2,

		   Color c1, Color c2,

		   Bitmap<int> &bm)

    : value1(value1), value2(value2),

      c1(c1), c2(c2), bm(bm)

  {

  }

  void Prepare() { bm.Prepare(); }



  int SizeX() const { return bm.SizeX(); }

  int SizeY() const { return bm.SizeY(); }

  Color Map(int x, int y) const

  {

    float val = (float)bm.Map(x,y);

    val -= float(value1);

    val /= float(value2-value1);

    //float f = float(val-value1)/(value2-value1);

    return Color::Interpolate(c1,c2, 1.0-val);

  }



private:

  int value1, value2;

  Color c1,c2;

  Bitmap<int> &bm;

};

class MemoizeBitmap : public Bitmap<Color>

{

public:

  MemoizeBitmap(Bitmap<Color> &bm) : bm(bm) 

  {

    

  }

  void Prepare() { 

    bm.Prepare();

    

    int width = bm.SizeX();

    int height = bm.SizeY();

    buf = BufferRef::NewBuffer(width, height);

    for(int j=0;j<height;j++)

      for(int i=0;i<width;i++)

	{

	  buf.buffer[i+j*buf.ydelta] = 0xfefefefe;

	}



  }



  ~MemoizeBitmap() { BufferRef::FreeBuffer(buf); }

  void MemoizeAll()

  {

    int sx=SizeX();

    int sy=SizeY();

    for(int x=0;x<sx;x++)

      for(int y=0;y<sy;y++)

	{

	  Map(x,y);

	}

  }

  virtual int SizeX() const { return buf.width; }

  virtual int SizeY() const { return buf.height; }

  virtual Color Map(int x, int y) const

  {

    //std::cout << x << " " << y << std::endl;

    if (x<0 || x >= int(buf.width) || y <0 || y>=int(buf.height))

	return Color(0x00000000);

    if (buf.buffer[x+y*buf.ydelta] == 0xfefefefe)

      {

	Color c = bm.Map(x,y);

	unsigned int cc = c.Pixel();

	buf.buffer[x+y*buf.ydelta] = cc;

      }

    return Color(buf.buffer[x+y*buf.ydelta]);

  }



private:

  Bitmap<Color> &bm;

  BufferRef buf;

};

EXPORT GameApi::BM GameApi::BitmapApi::mandelbrot(bool julia,

{

  ::Bitmap<int> *b = new Mandelbrot(julia, start_x, end_x,

				      start_y, end_y,

				      sx,sy,

				      count,

				      xx,yy);

  ::Bitmap<Color> *b2 = new MapBitmapToColor(0, count, Color(255,255,255), Color(0,128,255), *b);

  ::EnvImpl *env = ::EnvImpl::Environment(&e);



  env->deletes.push_back(std::shared_ptr<void>(b));

  env->deletes.push_back(std::shared_ptr<void>(b2));

  ::Bitmap<Color> *m = new MemoizeBitmap(*b2);

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m; 

  BM bm = add_bitmap(e, handle);

  return bm;  

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class BitmapFromRed : public Bitmap<float>

{

public:

  BitmapFromRed(Bitmap<Color> &bm) : bm(bm) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual float Map(int x, int y) const

  {

    Color c = bm.Map(x,y);

    int val = c.r;

    return float(val)/255.0;

  }



private:

  Bitmap<Color> &bm;

};

EXPORT GameApi::FB GameApi::FloatBitmapApi::from_red(BM bm)

{

  BitmapHandle *handle = find_bitmap(e,bm);

  Bitmap<Color> *bmc = find_color_bitmap(handle);

  Bitmap<float> *bm2 = new BitmapFromRed(*bmc);

  return add_float_bitmap(e, bm2);

}

class GrayScaleBitmapFromFloatBitmap : public Bitmap<Color>

{

public:

  GrayScaleBitmapFromFloatBitmap(Bitmap<float> &bm, Color c1, Color c2) : bm(bm), c1(c1), c2(c2) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual Color Map(int x, int y) const

  {

    float val = bm.Map(x,y);

    return Color::Interpolate(c2,c1,val);

  }



private:

  Bitmap<float> &bm;

  Color c1, c2;

};

EXPORT GameApi::BM GameApi::FloatBitmapApi::to_grayscale_color(FB fb, int r, int g, int b, int a,

{

  Bitmap<float> *bm = find_float_bitmap(e,fb)->bitmap;

  return add_color_bitmap2(e, new GrayScaleBitmapFromFloatBitmap(*bm, Color(r,g,b,a), Color(r2,g2,b2,a2)));

}

class GrayScaleBitmapFromFloatBitmap : public Bitmap<Color>

{

public:

  GrayScaleBitmapFromFloatBitmap(Bitmap<float> &bm, Color c1, Color c2) : bm(bm), c1(c1), c2(c2) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual Color Map(int x, int y) const

  {

    float val = bm.Map(x,y);

    return Color::Interpolate(c2,c1,val);

  }



private:

  Bitmap<float> &bm;

  Color c1, c2;

};

EXPORT GameApi::BM GameApi::FloatBitmapApi::to_grayscale_color(FB fb, int r, int g, int b, int a,

{

  Bitmap<float> *bm = find_float_bitmap(e,fb)->bitmap;

  return add_color_bitmap2(e, new GrayScaleBitmapFromFloatBitmap(*bm, Color(r,g,b,a), Color(r2,g2,b2,a2)));

}

class GrayScaleBitmapFromFloatBitmap : public Bitmap<Color>

{

public:

  GrayScaleBitmapFromFloatBitmap(Bitmap<float> &bm, Color c1, Color c2) : bm(bm), c1(c1), c2(c2) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual Color Map(int x, int y) const

  {

    float val = bm.Map(x,y);

    return Color::Interpolate(c2,c1,val);

  }



private:

  Bitmap<float> &bm;

  Color c1, c2;

};

EXPORT GameApi::BM GameApi::FloatBitmapApi::to_grayscale_color(FB fb, int r, int g, int b, int a,

{

  Bitmap<float> *bm = find_float_bitmap(e,fb)->bitmap;

  return add_color_bitmap2(e, new GrayScaleBitmapFromFloatBitmap(*bm, Color(r,g,b,a), Color(r2,g2,b2,a2)));

}

class GrayScaleBitmapFromFloatBitmap : public Bitmap<Color>

{

public:

  GrayScaleBitmapFromFloatBitmap(Bitmap<float> &bm, Color c1, Color c2) : bm(bm), c1(c1), c2(c2) { }

  void Prepare() { bm.Prepare(); }



  virtual int SizeX() const { return bm.SizeX(); }

  virtual int SizeY() const { return bm.SizeY(); }

  virtual Color Map(int x, int y) const

  {

    float val = bm.Map(x,y);

    return Color::Interpolate(c2,c1,val);

  }



private:

  Bitmap<float> &bm;

  Color c1, c2;

};

EXPORT GameApi::BM GameApi::FloatBitmapApi::to_grayscale_color(FB fb, int r, int g, int b, int a,

{

  Bitmap<float> *bm = find_float_bitmap(e,fb)->bitmap;

  return add_color_bitmap2(e, new GrayScaleBitmapFromFloatBitmap(*bm, Color(r,g,b,a), Color(r2,g2,b2,a2)));

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ChessBoardBitmap2 : public Bitmap<Color>

{

public:

  ChessBoardBitmap2(int tile_sx, int tile_sy, int count_x, int count_y, Color c1, Color c2) : tile_sx(tile_sx), tile_sy(tile_sy), count_x(count_x), count_y(count_y), c1(c1), c2(c2) { }

  void Prepare() { }



  int SizeX() const { return tile_sx*count_x; }

  int SizeY() const { return tile_sy*count_y; }

  Color Map(int x, int y) const

  {

    bool bb = false;

    int xx = x / count_x;

    int yy = y / count_y;

    if (xx & 1) { bb = !bb; }

    if (yy & 1) { bb = !bb; }

    if (bb) { return c1; }

    return c2;

  }

private:

  int tile_sx, tile_sy;

  int count_x, count_y;

  Color c1,c2;

};

EXPORT GameApi::BM GameApi::BitmapApi::chessboard(int tile_sx, int tile_sy, int count_x, int count_y, unsigned int c1, unsigned int c2)

{

  Bitmap<Color> *m = new ChessBoardBitmap2(tile_sx, tile_sy, count_x, count_y, Color(c1), Color(c2));

  BitmapColorHandle *handle = new BitmapColorHandle;

  handle->bm = m;

  BM bm = add_bitmap(e, handle);

  return bm;

}

class ArrayMainLoop : public MainLoopItem

{

public:

  ArrayMainLoop(GameApi::Env &env, GameApi::EveryApi &ev, std::vector<MainLoopItem*> vec) : env(env), ev(ev), vec(vec) { }

  void Prepare() {

    int s = vec.size();

    for(int i=0;i<s;i++) vec[i]->Prepare();

  }

  void execute(MainLoopEnv &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	MainLoopEnv ee = e;



	// here's a block needed to distribute in_MV to different cases.

	int id = vec[i]->shader_id();

	if (id!=-1) {

	  GameApi::SH sh;

	  sh.id = id;

	  GameApi::M m = add_matrix2( env, e.in_MV);

	  ev.shader_api.use(sh);

	  ev.shader_api.set_var(sh, "in_MV", m);

	}

	vec[i]->execute(ee);

      }

  }

  void handle_event(MainLoopEvent &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	vec[i]->handle_event(e);

      }

  }

#if 0

  int shader_id() { 

    int s = vec.size();

    for(int i=s-1;i>=0;i--)

      {

	if (vec[i]->shader_id()!=-1) return vec[i]->shader_id();

      }

    return -1; 

  }

#endif

private:

  GameApi::Env &env;

  GameApi::EveryApi &ev;

  std::vector<MainLoopItem*> vec;

};

EXPORT GameApi::ML GameApi::MainLoopApi::array_ml(std::vector<ML> vec)

{

  std::vector<MainLoopItem*> vec2;

  int s = vec.size();

  for(int i=0;i<s;i++)

    {

      //std::cout << "array_ml id: " << vec[i].id << std::endl;

      vec2.push_back(find_main_loop(e,vec[i]));

    }

  return add_main_loop(e, new ArrayMainLoop(vec2));

}

class ArrayMainLoop : public MainLoopItem

{

public:

  ArrayMainLoop(GameApi::Env &env, GameApi::EveryApi &ev, std::vector<MainLoopItem*> vec) : env(env), ev(ev), vec(vec) { }

  void Prepare() {

    int s = vec.size();

    for(int i=0;i<s;i++) vec[i]->Prepare();

  }

  void execute(MainLoopEnv &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	MainLoopEnv ee = e;



	// here's a block needed to distribute in_MV to different cases.

	int id = vec[i]->shader_id();

	if (id!=-1) {

	  GameApi::SH sh;

	  sh.id = id;

	  GameApi::M m = add_matrix2( env, e.in_MV);

	  ev.shader_api.use(sh);

	  ev.shader_api.set_var(sh, "in_MV", m);

	}

	vec[i]->execute(ee);

      }

  }

  void handle_event(MainLoopEvent &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	vec[i]->handle_event(e);

      }

  }

#if 0

  int shader_id() { 

    int s = vec.size();

    for(int i=s-1;i>=0;i--)

      {

	if (vec[i]->shader_id()!=-1) return vec[i]->shader_id();

      }

    return -1; 

  }

#endif

private:

  GameApi::Env &env;

  GameApi::EveryApi &ev;

  std::vector<MainLoopItem*> vec;

};

EXPORT GameApi::ML GameApi::MainLoopApi::array_ml(GameApi::EveryApi &ev, std::vector<ML> vec)

{

  std::vector<MainLoopItem*> vec2;

  int s = vec.size();

  for(int i=0;i<s;i++)

    {

      //std::cout << "array_ml id: " << vec[i].id << std::endl;

      vec2.push_back(find_main_loop(e,vec[i]));

    }

  return add_main_loop(e, new ArrayMainLoop(e,ev,vec2));

}

class ArrayMainLoop : public MainLoopItem

{

public:

  ArrayMainLoop(GameApi::Env &env, GameApi::EveryApi &ev, std::vector<MainLoopItem*> vec) : env(env), ev(ev), vec(vec) { }

  void Prepare() {

    int s = vec.size();

    for(int i=0;i<s;i++) vec[i]->Prepare();

  }

  void execute(MainLoopEnv &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	MainLoopEnv ee = e;



	// here's a block needed to distribute in_MV to different cases.

	int id = vec[i]->shader_id();

	if (id!=-1) {

	  GameApi::SH sh;

	  sh.id = id;

	  GameApi::M m = add_matrix2( env, e.in_MV);

	  ev.shader_api.use(sh);

	  ev.shader_api.set_var(sh, "in_MV", m);

	}

	vec[i]->execute(ee);

      }

  }

  void handle_event(MainLoopEvent &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	vec[i]->handle_event(e);

      }

  }

#if 0

  int shader_id() { 

    int s = vec.size();

    for(int i=s-1;i>=0;i--)

      {

	if (vec[i]->shader_id()!=-1) return vec[i]->shader_id();

      }

    return -1; 

  }

#endif

private:

  GameApi::Env &env;

  GameApi::EveryApi &ev;

  std::vector<MainLoopItem*> vec;

};

EXPORT GameApi::ML GameApi::MainLoopApi::array_ml(std::vector<ML> vec)

{

  std::vector<MainLoopItem*> vec2;

  int s = vec.size();

  for(int i=0;i<s;i++)

    {

      //std::cout << "array_ml id: " << vec[i].id << std::endl;

      vec2.push_back(find_main_loop(e,vec[i]));

    }

  return add_main_loop(e, new ArrayMainLoop(vec2));

}

class ArrayMainLoop : public MainLoopItem

{

public:

  ArrayMainLoop(GameApi::Env &env, GameApi::EveryApi &ev, std::vector<MainLoopItem*> vec) : env(env), ev(ev), vec(vec) { }

  void Prepare() {

    int s = vec.size();

    for(int i=0;i<s;i++) vec[i]->Prepare();

  }

  void execute(MainLoopEnv &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	MainLoopEnv ee = e;



	// here's a block needed to distribute in_MV to different cases.

	int id = vec[i]->shader_id();

	if (id!=-1) {

	  GameApi::SH sh;

	  sh.id = id;

	  GameApi::M m = add_matrix2( env, e.in_MV);

	  ev.shader_api.use(sh);

	  ev.shader_api.set_var(sh, "in_MV", m);

	}

	vec[i]->execute(ee);

      }

  }

  void handle_event(MainLoopEvent &e)

  {

    int s = vec.size();

    for(int i=0;i<s;i++)

      {

	vec[i]->handle_event(e);

      }

  }

#if 0

  int shader_id() { 

    int s = vec.size();

    for(int i=s-1;i>=0;i--)

      {

	if (vec[i]->shader_id()!=-1) return vec[i]->shader_id();

      }

    return -1; 

  }

#endif

private:

  GameApi::Env &env;

  GameApi::EveryApi &ev;

  std::vector<MainLoopItem*> vec;

};

EXPORT GameApi::ML GameApi::MainLoopApi::array_ml(GameApi::EveryApi &ev, std::vector<ML> vec)

{

  std::vector<MainLoopItem*> vec2;

  int s = vec.size();

  for(int i=0;i<s;i++)

    {

      //std::cout << "array_ml id: " << vec[i].id << std::endl;

      vec2.push_back(find_main_loop(e,vec[i]));

    }

  return add_main_loop(e, new ArrayMainLoop(e,ev,vec2));

}

class QuakeML2 : public MainLoopItem

{

public:

  QuakeML2(GameApi::Env &env, GameApi::EveryApi &ev, MainLoopItem *next, float speed, float rot_speed) : env(env), ev(ev), next(next), speed(speed), rot_speed(rot_speed) { 

    point.id=-1;

  }

  void Prepare() { next->Prepare(); }

  virtual void execute(MainLoopEnv &e)

  {

    g_is_quake=true;

    if (ev.mainloop_api.get_screen_width()<700) {

    GameApi::InteractionApi::quake_movement_frame(ev, pos_x, pos_y, rot_y, dt, speed_x, speed_y, speed, -rot_speed);

    } else {

          GameApi::InteractionApi::quake_movement_frame(ev, pos_x, pos_y, rot_y, dt, speed_x, speed_y, speed, rot_speed);

    }

    quake_pos_x = pos_x;

    quake_pos_y = -pos_y;

    quake_rot_y = rot_y;

    MainLoopEnv eee = e;

    GameApi::M env_m = add_matrix2(env, e.in_MV);

    GameApi::M rot_y2 = ev.matrix_api.yrot(rot_y);

    GameApi::M trans = ev.matrix_api.trans(pos_x, 0.0, pos_y +400.0);

    GameApi::M trans2 = ev.matrix_api.trans(0.0,0.0,-400.0);

    GameApi::M scale = ev.matrix_api.scale(1.0,1.0,-1.0);

    GameApi::M res = ev.matrix_api.mult(env_m, ev.matrix_api.mult(ev.matrix_api.mult(ev.matrix_api.mult(trans,rot_y2),trans2),scale));



    //GameApi::M mat2i = ev.matrix_api.transpose(ev.matrix_api.inverse(res));

    GameApi::SH s1;

    s1.id = e.sh_texture;

    GameApi::SH s2;

    s2.id = e.sh_array_texture;

    GameApi::SH s3;

    s3.id = e.sh_color;



    ev.shader_api.use(s1);

    ev.shader_api.set_var(s1, "in_MV", res);

    ev.shader_api.set_var(s1, "in_T", ev.matrix_api.identity());

    //ev.shader_api.set_var(s1, "in_iMV", mat2i);

    ev.shader_api.use(s2);

    ev.shader_api.set_var(s2, "in_MV", res);

    ev.shader_api.set_var(s2, "in_T", ev.matrix_api.identity());

    //ev.shader_api.set_var(s2, "in_iMV", mat2i);

    ev.shader_api.use(s3);

    ev.shader_api.set_var(s3, "in_MV", res);

    ev.shader_api.set_var(s3, "in_T", ev.matrix_api.identity());

    //ev.shader_api.set_var(s3, "in_iMV", mat2i);



    

    eee.in_MV = find_matrix(env, res); 

    eee.env = find_matrix(env, res);



    next->execute(eee);

    ev.shader_api.unuse(s3);



  }

  virtual void handle_event(MainLoopEvent &e)

  {

    if (point.id==-1) {

      point = add_point(env, 0.0,0.0,0.0);

    }

    Point *pt = find_point(env,point);

    pt->x = e.cursor_pos.x;

    pt->y = e.cursor_pos.y;

    pt->z = e.cursor_pos.z;

    GameApi::MainLoopApi::Event ee;

    ee.type = e.type;

    ee.ch = e.ch;

    ee.button = e.button;

    ee.cursor_pos = point;

    GameApi::InteractionApi::quake_movement_event(ev,ee,pos_x, pos_y, rot_y, dt, speed_x, speed_y, speed, rot_speed);

    next->handle_event(e);

  }

  virtual int shader_id() { return -1; }



private:

  GameApi::Env &env;

  GameApi::EveryApi &ev;

  GameApi::PT point;

  MainLoopItem *next;

  float pos_x=0.0, pos_y=0.0, rot_y=0.0;

  GameApi::InteractionApi::Quake_data dt;

  float speed_x=0.0, speed_y=0.0;

  float speed, rot_speed;

};

GameApi::ML GameApi::MovementNode::quake_ml2(EveryApi &ev, ML ml,float speed, float rot_speed)

{

  GameApi::MN mn = ev.move_api.empty();

  GameApi::MN scale = ev.move_api.scale2(mn, 1.0,1.0,-1.0);

  GameApi::ML ml2 = ev.move_api.move_ml(ev,ml,scale, 1, 10.0);

  MainLoopItem *mml = find_main_loop(e,ml2);

  return add_main_loop(e, new QuakeML2(e,ev, mml, speed, rot_speed));

}

class MainLoopSplitter_win32_and_emscripten : public Splitter

{

public:

  MainLoopSplitter_win32_and_emscripten(GameApi::ML code, bool logo, bool fpscounter, float start_time, float duration, int screen_width, int screen_height) : code(code), logo(logo), fpscounter(fpscounter), timeout(duration), start_time(start_time), screen_width(screen_width), screen_height(screen_height)

  {

    firsttime = true;

  }

  virtual void set_env(GameApi::Env *ei)

  {

    e = ei;

  }

  virtual void set_everyapi(GameApi::EveryApi *evi)

  {

    ev = evi;

  }

  virtual void Init()

  {

    score = 0;

    hidden_score = 0;



    Envi_2 &env = envi;

    env.logo_shown = logo;

    env.fpscounter = fpscounter;

    env.timeout = start_time+timeout;

    env.start_time = start_time;

    env.screen_width = screen_width;

    env.screen_height = screen_height;

    env.ev = ev;

    

    GameApi::SH sh = env.ev->shader_api.colour_shader();

    GameApi::SH sh2 = env.ev->shader_api.texture_shader();

    GameApi::SH sh3 = env.ev->shader_api.texture_array_shader();

    

    // rest of the initializations

    env.ev->mainloop_api.init_3d(sh);

    env.ev->mainloop_api.init_3d(sh2);

    env.ev->mainloop_api.init_3d(sh3);

    env.ev->shader_api.use(sh);

    

    GameApi::ML ml = mainloop(*env.ev);

    if (async_pending_count > 0) { env.logo_shown = true; }

    

    env.mainloop = ml;

    

    env.color_sh = sh;

    env.texture_sh = sh2;

    env.arr_texture_sh = sh3;

    

    env.ev->mainloop_api.reset_time();

    if (env.logo_shown) {

      if (gameapi_seamless_url == "") {

	env.ev->mainloop_api.display_logo(*env.ev);

      } else {

	env.ev->mainloop_api.display_seamless(*env.ev);

      }

    } else {

	env.ev->mainloop_api.advance_time(env.start_time/10.0*1000.0);

    }

     env.ev->mainloop_api.alpha(true);

     g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

     GameApi::MainLoopApi::Event e;

     while((e = env.ev->mainloop_api.get_event()).last==true)

       {

	 /* this eats all events from queue */

       }

     g_hide_container.clear();



  }

  virtual int Iter()

  {

    Envi_2 *env = (Envi_2*)&envi;





    //std::cout << "async: " << async_pending_count << std::endl;

    if ((async_pending_count > 0 && !async_is_done)||no_draw_count>0) { env->logo_shown = true; }

    if (async_pending_count != async_pending_count_previous)

      {

	//std::cout << "ASync pending count=" << async_pending_count << std::endl;

	async_pending_count_previous = async_pending_count;

      }

    if (env->logo_shown)

      {

	bool b = false;

	if (gameapi_seamless_url=="") {

	  //std::cout << "Logo iter" << std::endl;

	  b = env->ev->mainloop_api.logo_iter();

	  //std::cout << "End of Logo iter" << std::endl;

	} else {

	  b = env->ev->mainloop_api.seamless_iter();

	}

	if (b && async_pending_count==0 && no_draw_count==0) { env->logo_shown = false;

	  env->ev->mainloop_api.reset_time();

	  env->ev->mainloop_api.advance_time(env->start_time/10.0*1000.0);

	}

	//if (g_shows_hundred) { env->logo_shown=false; }

	if (async_pending_count==0 && no_draw_count>0) { /* pass through */}

	else

	  return -1;

      }

    async_is_done = true;



    if (firsttime) {

      MainLoopItem *item = find_main_loop(env->ev->get_env(),code);

      //std::cout << "Splitter/Prepare:" << std::endl;

      item->Prepare();

      //std::cout << "Splitter/End of Prepare:" << std::endl;

      firsttime = false;

    }



    

    if (no_draw_count==0)

      env->ev->mainloop_api.clear_3d(0xff000000);

    

    // handle esc event

    GameApi::MainLoopApi::Event e;

    while((e = env->ev->mainloop_api.get_event()).last==true)

      {

	//std::cout << e.ch << " " << e.type << std::endl;

#ifndef EMSCRIPTEN

	if (e.ch==27 && e.type==0x300) { /*std::cout << "Esc pressed2!" << std::endl;*/ env->exit = true; return 0; }

#endif

	

	//GameApi::InteractionApi::quake_movement_event(*env->ev,e, env->pos_x, env->pos_y, env->rot_y,

	//					      env->data, env->speed_x, env->speed_y,

	//			   1.0, 1.0*3.14159*2.0/360.0);

	//std::cout << "Splitter/Event:" << std::endl;

	env->ev->mainloop_api.event_ml(env->mainloop, e);

	//std::cout << "Splitter/End of Event:" << std::endl;

	

      }

    //GameApi::InteractionApi::quake_movement_frame(*env->ev, env->pos_x, env->pos_y, env->rot_y,

    //						  env->data, env->speed_x, env->speed_y,

    //						  1.0, 1.0*3.14159*2.0/360.0);

    

    GameApi::M mat = env->ev->matrix_api.identity();

    if (screen_width<600) {

      mat = env->ev->matrix_api.scale(-1.0,-1.0,1.0);

    }

    env->ev->shader_api.use(env->color_sh);

    env->ev->shader_api.set_var(env->color_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->color_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    env->ev->shader_api.use(env->texture_sh);

    env->ev->shader_api.set_var(env->texture_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->texture_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    

    env->ev->shader_api.use(env->arr_texture_sh);

    env->ev->shader_api.set_var(env->arr_texture_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->arr_texture_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    env->ev->shader_api.use(env->color_sh);

    

    GameApi::M in_MV = mat; //env->ev->mainloop_api.in_MV(*env->ev, true);

    GameApi::M in_T = env->ev->mainloop_api.in_T(*env->ev, true);

    GameApi::M in_N = env->ev->mainloop_api.in_N(*env->ev, true);

    

    //std::cout << "Splitter/execute_ml" << std::endl;

    env->ev->mainloop_api.execute_ml(env->mainloop, env->color_sh, env->texture_sh, env->texture_sh, env->arr_texture_sh, in_MV, in_T, in_N, env->screen_width, env->screen_height);

    //std::cout << "Splitter/end of execute_ml" << std::endl;



    if (env->fpscounter)

      env->ev->mainloop_api.fpscounter();

    if (env->ev->mainloop_api.get_time()/1000.0*10.0 > env->timeout)

      {

	//env->exit = true;

	std::cout << "Timeout2, exiting.." << std::endl;

      }

    

    // swapbuffers

    env->ev->mainloop_api.swapbuffers();

    //xsg_low->ogl->glGetError();

    return -1;

  }

  virtual void Destroy()

  {

	float scale_x = 1.0;

	float scale_y = 1.0;

	if (g_event_screen_y!=-1) {

	  scale_x = float(g_event_screen_x)/float(screen_width);

	  scale_y = float(g_event_screen_y)/float(screen_height);

	}

	g_low->ogl->glViewport(0,0,screen_width*scale_x, screen_height*scale_y);

    // this is needed for win32 build in editor

      g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

  }

  virtual Splitter* NextState(int code)

  {

    return 0;

  }

  GameApi::ML mainloop(GameApi::EveryApi &ev)

  {

    return code;

  }



private:

  GameApi::ML code;

  bool logo;

  bool fpscounter;

  float timeout;

  float start_time;

  int screen_width;

  int screen_height;

  Envi_2 envi;

  bool firsttime;

};

EXPORT GameApi::RUN GameApi::BlockerApi::game_window2(GameApi::EveryApi &ev, ML ml, bool logo, bool fpscounter, float start_time, float duration)

{

  Splitter *spl = new MainLoopSplitter_win32_and_emscripten(ml,logo, fpscounter, start_time, duration, ev.mainloop_api.get_screen_sx(), ev.mainloop_api.get_screen_sy());

  return add_splitter(e, spl);

}

class MainLoopSplitter_win32_and_emscripten : public Splitter

{

public:

  MainLoopSplitter_win32_and_emscripten(GameApi::ML code, bool logo, bool fpscounter, float start_time, float duration, int screen_width, int screen_height) : code(code), logo(logo), fpscounter(fpscounter), timeout(duration), start_time(start_time), screen_width(screen_width), screen_height(screen_height)

  {

    firsttime = true;

  }

  virtual void set_env(GameApi::Env *ei)

  {

    e = ei;

  }

  virtual void set_everyapi(GameApi::EveryApi *evi)

  {

    ev = evi;

  }

  virtual void Init()

  {

    score = 0;

    hidden_score = 0;



    Envi_2 &env = envi;

    env.logo_shown = logo;

    env.fpscounter = fpscounter;

    env.timeout = start_time+timeout;

    env.start_time = start_time;

    env.screen_width = screen_width;

    env.screen_height = screen_height;

    env.ev = ev;

    

    GameApi::SH sh = env.ev->shader_api.colour_shader();

    GameApi::SH sh2 = env.ev->shader_api.texture_shader();

    GameApi::SH sh3 = env.ev->shader_api.texture_array_shader();

    

    // rest of the initializations

    env.ev->mainloop_api.init_3d(sh);

    env.ev->mainloop_api.init_3d(sh2);

    env.ev->mainloop_api.init_3d(sh3);

    env.ev->shader_api.use(sh);

    

    GameApi::ML ml = mainloop(*env.ev);

    if (async_pending_count > 0) { env.logo_shown = true; }

    

    env.mainloop = ml;

    

    env.color_sh = sh;

    env.texture_sh = sh2;

    env.arr_texture_sh = sh3;

    

    env.ev->mainloop_api.reset_time();

    if (env.logo_shown) {

      if (gameapi_seamless_url == "") {

	env.ev->mainloop_api.display_logo(*env.ev);

      } else {

	env.ev->mainloop_api.display_seamless(*env.ev);

      }

    } else {

	env.ev->mainloop_api.advance_time(env.start_time/10.0*1000.0);

    }

     env.ev->mainloop_api.alpha(true);

     g_low->ogl->glEnable(Low_GL_DEPTH_TEST);

     GameApi::MainLoopApi::Event e;

     while((e = env.ev->mainloop_api.get_event()).last==true)

       {

	 /* this eats all events from queue */

       }

     g_hide_container.clear();



  }

  virtual int Iter()

  {

    Envi_2 *env = (Envi_2*)&envi;





    //std::cout << "async: " << async_pending_count << std::endl;

    if ((async_pending_count > 0 && !async_is_done)||no_draw_count>0) { env->logo_shown = true; }

    if (async_pending_count != async_pending_count_previous)

      {

	//std::cout << "ASync pending count=" << async_pending_count << std::endl;

	async_pending_count_previous = async_pending_count;

      }

    if (env->logo_shown)

      {

	bool b = false;

	if (gameapi_seamless_url=="") {

	  //std::cout << "Logo iter" << std::endl;

	  b = env->ev->mainloop_api.logo_iter();

	  //std::cout << "End of Logo iter" << std::endl;

	} else {

	  b = env->ev->mainloop_api.seamless_iter();

	}

	if (b && async_pending_count==0 && no_draw_count==0) { env->logo_shown = false;

	  env->ev->mainloop_api.reset_time();

	  env->ev->mainloop_api.advance_time(env->start_time/10.0*1000.0);

	}

	//if (g_shows_hundred) { env->logo_shown=false; }

	if (async_pending_count==0 && no_draw_count>0) { /* pass through */}

	else

	  return -1;

      }

    async_is_done = true;



    if (firsttime) {

      MainLoopItem *item = find_main_loop(env->ev->get_env(),code);

      //std::cout << "Splitter/Prepare:" << std::endl;

      item->Prepare();

      //std::cout << "Splitter/End of Prepare:" << std::endl;

      firsttime = false;

    }



    

    if (no_draw_count==0)

      env->ev->mainloop_api.clear_3d(0xff000000);

    

    // handle esc event

    GameApi::MainLoopApi::Event e;

    while((e = env->ev->mainloop_api.get_event()).last==true)

      {

	//std::cout << e.ch << " " << e.type << std::endl;

#ifndef EMSCRIPTEN

	if (e.ch==27 && e.type==0x300) { /*std::cout << "Esc pressed2!" << std::endl;*/ env->exit = true; return 0; }

#endif

	

	//GameApi::InteractionApi::quake_movement_event(*env->ev,e, env->pos_x, env->pos_y, env->rot_y,

	//					      env->data, env->speed_x, env->speed_y,

	//			   1.0, 1.0*3.14159*2.0/360.0);

	//std::cout << "Splitter/Event:" << std::endl;

	env->ev->mainloop_api.event_ml(env->mainloop, e);

	//std::cout << "Splitter/End of Event:" << std::endl;

	

      }

    //GameApi::InteractionApi::quake_movement_frame(*env->ev, env->pos_x, env->pos_y, env->rot_y,

    //						  env->data, env->speed_x, env->speed_y,

    //						  1.0, 1.0*3.14159*2.0/360.0);

    

    GameApi::M mat = env->ev->matrix_api.identity();

    if (screen_width<600) {

      mat = env->ev->matrix_api.scale(-1.0,-1.0,1.0);

    }

    env->ev->shader_api.use(env->color_sh);

    env->ev->shader_api.set_var(env->color_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->color_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    env->ev->shader_api.use(env->texture_sh);

    env->ev->shader_api.set_var(env->texture_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->texture_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    

    env->ev->shader_api.use(env->arr_texture_sh);

    env->ev->shader_api.set_var(env->arr_texture_sh, "in_MV", mat);

    //env->ev->shader_api.set_var(env->arr_texture_sh, "in_iMV", env->ev->matrix_api.transpose(env->ev->matrix_api.inverse(mat)));

    env->ev->shader_api.use(env->color_sh);

    

    GameApi::M in_MV = mat; //env->ev->mainloop_api.in_MV(*env->ev, true);

    GameApi::M in_T = env->ev->mainloop_api.in_T(*env->ev, true);

    GameApi::M in_N = env->ev->mainloop_api.in_N(*env->ev, true);

    

    //std::cout << "Splitter/execute_ml" << std::endl;

    env->ev->mainloop_api.execute_ml(env->mainloop, env->color_sh, env->texture_sh, env->texture_sh, env->arr_texture_sh, in_MV, in_T, in_N, env->screen_width, env->screen_height);

    //std::cout << "Splitter/end of execute_ml" << std::endl;



    if (env->fpscounter)

      env->ev->mainloop_api.fpscounter();

    if (env->ev->mainloop_api.get_time()/1000.0*10.0 > env->timeout)

      {

	//env->exit = true;

	std::cout << "Timeout2, exiting.." << std::endl;

      }

    

    // swapbuffers

    env->ev->mainloop_api.swapbuffers();

    //xsg_low->ogl->glGetError();

    return -1;

  }

  virtual void Destroy()

  {

	float scale_x = 1.0;

	float scale_y = 1.0;

	if (g_event_screen_y!=-1) {

	  scale_x = float(g_event_screen_x)/float(screen_width);

	  scale_y = float(g_event_screen_y)/float(screen_height);

	}

	g_low->ogl->glViewport(0,0,screen_width*scale_x, screen_height*scale_y);

    // this is needed for win32 build in editor

      g_low->ogl->glDisable(Low_GL_DEPTH_TEST);

  }

  virtual Splitter* NextState(int code)

  {

    return 0;

  }

  GameApi::ML mainloop(GameApi::EveryApi &ev)

  {

    return code;

  }



private:

  GameApi::ML code;

  bool logo;

  bool fpscounter;

  float timeout;

  float start_time;

  int screen_width;

  int screen_height;

  Envi_2 envi;

  bool firsttime;

};

EXPORT GameApi::RUN GameApi::BlockerApi::game_window2(GameApi::EveryApi &ev, ML ml, bool logo, bool fpscounter, float start_time, float duration)

{

  float screen_x = ev.mainloop_api.get_screen_sx();

  float screen_y = ev.mainloop_api.get_screen_sy();



  ml = ev.mainloop_api.display_background(ev,ml);

  Splitter *spl = new MainLoopSplitter_win32_and_emscripten(ml,logo, fpscounter, start_time, duration, screen_x, screen_y);

  return add_splitter(e, spl);

}

int main()
{
PT I1=ev.point_api.point(0.0,0.0,0.0);
PT I2=ev.point_api.point(0,256,0);
BM I3=ev.bitmap_api.gradient(I1,I2,ff223388,ff2244ff,256,256);
BM I4=ev.bitmap_api.scale_bitmap_fullscreen(ev,I3);
ML I5=ev.sprite_api.vertex_array_render(ev,I4);
ML I6=ev.sprite_api.turn_to_2d(ev,I5,0.0,0.0,800.0,600.0);
ML I7=ev.mainloop_api.bind_obj_type(ev,https://meshpage.org/assets/objtype.txt);
ML I8=ev.mainloop_api.read_obj_pos(https://meshpage.org/assets/objpos.txt);
BM I9=ev.bitmap_api.noise_vectors(256,256);
FB I10=ev.float_bitmap_api.from_red(I9);
FB I11=ev.bitmap_api.mul_fb(I10,0.2);
BM I12=ev.bitmap_api.newbitmap(128,128,ff00ff00);
BM I13=ev.bitmap_api.newbitmap(100,100,ff008800);
ML I14=ev.mainloop_api.parse_areatype(ev,https://meshpage.org/assets/areatype_grass.txt,I11,I12,I13);
BM I15=ev.bitmap_api.newbitmap(128,128,00000000);
FB I16=ev.float_bitmap_api.from_green(I15);
BM I17=ev.bitmap_api.chessboard(16,16,8,8,ffff8800,ff884400);
BM I18=ev.bitmap_api.chessboard(16,16,1,1,ffff8800,ff884400);
ML I19=ev.mainloop_api.parse_areatype(ev,https://meshpage.org/assets/areatype_empty.txt,I16,I17,I18);
BM I20=ev.bitmap_api.newbitmap(128,128,00000000);
FB I21=ev.float_bitmap_api.from_green(I20);
BM I22=ev.bitmap_api.chessboard(16,16,8,8,ffff8800,ff884400);
BM I23=ev.bitmap_api.chessboard(16,16,1,1,ffff8800,ff884400);
ML I24=ev.mainloop_api.parse_areatype(ev,https://meshpage.org/assets/areatype_empty2.txt,I21,I22,I23);
BM I25=ev.bitmap_api.mandelbrot(false,-2,1,-1,1,0,0,256,256,64);
FB I26=ev.float_bitmap_api.from_red(I25);
BM I27=ev.bitmap_api.mandelbrot(false,-2,1,-1,1,0,0,256,256,64);
FB I28=ev.float_bitmap_api.from_red(I27);
BM I29=ev.float_bitmap_api.to_grayscale_color(I28,255,128,0,255,128,64,0,255);
BM I30=ev.bitmap_api.chessboard(16,16,1,1,ffff8800,ff884400);
ML I31=ev.mainloop_api.parse_areatype(ev,https://meshpage.org/assets/areatype.txt,I26,I29,I30);
ML I32=ev.mainloop_api.create_landscape(ev,https://meshpage.org/assets/landscape.txt);
ML I33=ev.mainloop_api.create_objs(ev,0);
ML I34=ev.mainloop_api.array_ml(ev,std::vector<ML>{I7,I8,I14,I19,I24,I31,I32,I33});
ML I35=ev.mainloop_api.array_ml(ev,std::vector<ML>{I6,I34});
ML I36=ev.move_api.quake_ml2(ev,I35,5,0.02);
RUN I37=ev.blocker_api.game_window2(ev,I36,false,false,0.0,100000.0);

}