#include "Level.h"
#include "Globals.h"
#include "rapidxml.hpp"
#include "Rabbit.h"
#include "Wumbo-KeyboardInput.h"
#include "Wumbo-Quicky.h"
#include "FjordsSound.h"
Transport::Transport(int _x, int _y, char *_name, int _destX, int _destY)
{
	name = new char[32];
	int len = strlen(_name);
	if (len > 31)
		len = 31;
	x = _x;
	y = _y;
	w = 1;
	h = 1;
	destX = _destX;
	destY = _destY;
	memcpy(name,_name,len+1);
}
bool Transport::isAtGridPosition(int _x, int _y)
{
	return (_x >= x && _x < x+w && _y >= y && _y < y+h);
}




Level::Level(Wumbo::Program *prog, std::string name, int x, int y, bool fall, int rot) : Wumbo::Scene(prog)
{
	startX = x;
	startY = y;
	startName = name;
	startFall = fall;
	startRot = rot;
	width = 0;
	height = 0;
}
Level::~Level()
{
	delete data;
}
unsigned int Level::lastRoomType = -1;
void Level::begin()
{
	mdl_rabbit = new Batch();
	mdl_rabbit->begin();
		mdl_rabbit->addCube(-7,2,-2,-5,4,2,SHARECART_WHITE);

		mdl_rabbit->addCube(-5,0,-5,5,6,5,SHARECART_GREEN);

		mdl_rabbit->addCube(1,6,-4,3,10,-2,SHARECART_GREEN,1,0);
		mdl_rabbit->addCube(1,6,1,3,10,3,SHARECART_GREEN,1,0);

		mdl_rabbit->addCube(1,6,-4,3,10,-2,SHARECART_LIGHTGREEN,0,1,0,0,0,0);
		mdl_rabbit->addCube(1,6,1,3,10,3,SHARECART_LIGHTGREEN,0,1,0,0,0,0);
	mdl_rabbit->finish();

	mdl_rabbit_shadow = new Batch();
	mdl_rabbit_shadow->begin();
		mdl_rabbit_shadow->addFloor(-5,0,-5,5,0,5,(SHARECART_BLACK & 0x00FFFFFF) | 0x66000000);
	mdl_rabbit_shadow->finish();

	mdl_bird = new Batch();
	mdl_bird->begin();
		mdl_bird->addCube(-5+2,4,-5+2,5-2,10,5-2,SHARECART_BLACK,1,1,1,1,1,0);
		mdl_bird->addCube(5-2,5,-5+3,5,7,-5+7,SHARECART_RED,1,1,1,1,1,0);

		mdl_bird->addCube(-5+3,5,-5,5-3,7,-5+2,SHARECART_BLACK,1,1,1,1,1,0);
		mdl_bird->addCube(-5+3,5,5-2,5-3,7,5,SHARECART_BLACK,1,1,1,1,1,0);

		mdl_bird->addCube(5-4,10,-5+2,5-2,12,-5+4,SHARECART_WHITE,1,1,1,1,1,0);

		mdl_bird->addCube(5-4,10,5-4,5-2,12,5-2,SHARECART_WHITE,1,1,1,1,1,0);
	mdl_bird->finish();

	mdl_bird_shadow = new Batch();
	mdl_bird_shadow->begin();
		mdl_bird_shadow->addFloor(-5+2,.4f,-5+2,5-2,.4f,5-2,SHARECART_BLACK & 0x00FFFFFF | 0x66000000);
		mdl_bird_shadow->addFloor(-5+3,.4f,-5,5-3,.4f,-5+2,SHARECART_BLACK & 0x00FFFFFF | 0x66000000);
		mdl_bird_shadow->addFloor(-5+3,.4f,5-2,5-3,.4f,5,SHARECART_BLACK & 0x00FFFFFF | 0x66000000);
	mdl_bird_shadow->finish();


	displayingDialog = false;
	PREPARETRANSFER_name = "";
	PREPARETRANSFER_x = 0;
	PREPARETRANSFER_y = 0;
	PREPARETRANSFER_animate = -1;
	cameraXoffset = 0;
	cameraYoffset = 0;
	model = NULL;
	levelname = "null";
	textbatch = new Batch();
	FILE *f = fopen(std::string("Rooms/"+startName+".oel").c_str(),"rb");
	if (f == NULL)
	{
		printf("FAILED TO LOAD ROOM: %s\n",startName.c_str());
		rabbit = new Rabbit(this);
		rabbit->init();
		roomType = RT_NULL;
		lastRoomType = RT_NULL;
		stopAllMusic();
		playLevelMusic(roomType);
		//rabbit->x = 15;
		//rabbit->z = 15;
		return;
	}
	fseek(f,SEEK_SET,SEEK_END);
	fpos_t pos;
	fgetpos(f,&pos);
	fseek(f,SEEK_SET,0);
	char *contents = new char[pos+1];
	memset(contents,0,pos+1);
	fread(contents,pos,1,f);
	fclose(f);
	rapidxml::xml_document<> doc;
	doc.parse<0>(contents);
	roomType = RT_OUTSIDE;
	width = atoi(doc.first_node("level")->first_attribute("width")->value())/32;
	height = atoi(doc.first_node("level")->first_attribute("height")->value())/32;
	char *style = doc.first_node("level")->first_attribute("ROOMSTYLE")->value();
	levelname = doc.first_node("level")->first_attribute("name")->value();
	if (strcmp(style,"OUTSIDE") == 0)
		roomType = RT_OUTSIDE;
	else if (strcmp(style,"MAGIC") == 0)
		roomType = RT_MAGIC;
	else if (strcmp(style,"UNDERGROUND") == 0)
		roomType = RT_UNDERGROUND;
	else if (strcmp(style,"null") == 0)
		roomType = RT_NULL;
	data = new unsigned int[width*height];
	
	memset(data,0,sizeof(unsigned int)*width*height);
	rapidxml::xml_node<char> *XMLentities = doc.first_node("level")->first_node("Entities");
	for(rapidxml::xml_node<char> *iter = XMLentities->first_node();iter != NULL;iter = iter->next_sibling())
	{
		int x = atoi(iter->first_attribute("x")->value());
		int y = atoi(iter->first_attribute("y")->value());
		if (strcmp(iter->name(),"Bunny") == 0)
		{
			rabbit = new Rabbit(this);
			rabbit->init();
			rabbit->x = 10*(x/32)+5;
			rabbit->z = 10*(y/32)+5;
		}
		if (strcmp(iter->name(),"Skull") == 0)
			set(x/32,y/32,TILE_SKULL);
		if (strcmp(iter->name(),"Tree") == 0)
			set(x/32,y/32,TILE_TREE);
		if (strcmp(iter->name(),"Rock") == 0)
			set(x/32,y/32,TILE_ROCK);
		if (strcmp(iter->name(),"Spike") == 0)
			set(x/32,y/32,TILE_SPIKE);
		if (strcmp(iter->name(),"Light") == 0)
			set(x/32,y/32,TILE_LIGHT);
		if (strcmp(iter->name(),"Brick") == 0)
			set(x/32,y/32,TILE_BRICK);
		if (strcmp(iter->name(),"BrickWindow") == 0)
			set(x/32,y/32,TILE_BRICKWINDOW);
		if (strcmp(iter->name(),"Dirt") == 0)
			set(x/32,y/32,TILE_DIRT);
		if (strcmp(iter->name(),"Fence") == 0)
			set(x/32,y/32,TILE_FENCE);
		if (strcmp(iter->name(),"Talker") == 0)
		{
			char *type = iter->first_attribute("Type")->value();
			int T = -1;
			int V = VC_DEFAULT;
			if (strcmp(type,"sign") == 0)
			{
				T = TILE_SIGN;
				V = VC_DEFAULT;
			}
			if (strcmp(type,"bird") == 0)
			{
				T = TILE_BIRD;
				V = VC_BIRD;
			}
			if (strcmp(type,"scribble") == 0)
			{
				T = TILE_SCRIBBLE;
				V = VC_SCRIBBLE;
			}
			if (strcmp(type,"gravestone") == 0)
			{
				T = TILE_GRAVESTONE;
				V = VC_DEFAULT;
			}
			if (strcmp(type,"bookshelf") == 0)
			{
				T = TILE_BOOKSHELF;
				V = VC_DEFAULT;
			}
			set(x/32,y/32,T);
			talkers.push_back(Talker(this,x/32,y/32,V,atoi(iter->first_attribute("ValueCount")->value()),T,iter->first_attribute("Text1")->value(),iter->first_attribute("Text2")->value(),iter->first_attribute("Text3")->value()));
			talkers.at(talkers.size()-1).immobile = true;
			if (T == TILE_BIRD)
				talkers.at(talkers.size()-1).immobile = false;
			if (T == TILE_SCRIBBLE)
				talkers.at(talkers.size()-1).immobile = false;
		}
		if (strcmp(iter->name(),"Door") == 0)
		{
			set(x/32,y/32,TILE_DOOR);
			transports.push_back(Transport(x/32,y/32,iter->first_attribute("Destination")->value(),atoi(iter->first_attribute("DestX")->value()),atoi(iter->first_attribute("DestY")->value())));
			if (iter->first_attribute("width") != NULL)
				transports.at(transports.size()-1).w = atoi(iter->first_attribute("width")->value())/32;
			if (iter->first_attribute("height") != NULL)
				transports.at(transports.size()-1).h = atoi(iter->first_attribute("height")->value())/32;
			int T = TILE_DOOR;
			char *type = iter->first_attribute("type")->value();
			if (strcmp(type,"door") == 0)
				T = TILE_DOOR;
			if (strcmp(type,"stairsup") == 0)
				T = TILE_STAIRSUP;
			if (strcmp(type,"stairsdown") == 0)
				T = TILE_STAIRSDOWN;
			if (strcmp(type,"whoosh") == 0)
				T = TILE_WHOOSHDOOR;
			for(int i=0;i<transports.at(transports.size()-1).w;i++)
				for(int j=0;j<transports.at(transports.size()-1).h;j++)
					set(x/32+i,y/32+j,T);
		}
		if (strcmp(iter->name(),"Hole") == 0)
		{
			set(x/32,y/32,TILE_HOLE);
			transports.push_back(Transport(x/32,y/32,iter->first_attribute("Destination")->value(),atoi(iter->first_attribute("DestX")->value()),atoi(iter->first_attribute("DestY")->value())));
			if (iter->first_attribute("width") != NULL)
				transports.at(transports.size()-1).w = atoi(iter->first_attribute("width")->value())/32;
			if (iter->first_attribute("height") != NULL)
				transports.at(transports.size()-1).h = atoi(iter->first_attribute("height")->value())/32;
			for(int i=0;i<transports.at(transports.size()-1).w;i++)
				for(int j=0;j<transports.at(transports.size()-1).h;j++)
					set(x/32+i,y/32+j,TILE_HOLE);
		}
	}
	unsigned int floorColor = -1;
	floorColor = SHARECART_YELLOW;
	if (roomType == RT_UNDERGROUND)
		floorColor = SHARECART_DARKBROWN;
	if (roomType == RT_NULL)
		floorColor = SHARECART_BLACK;
	model = new Batch();
	model->begin();
	int L, U, R, D;
	int bookshelfboost = 5;
	for(int i=0;i<width;i++)
		for(int j=0;j<height;j++)
		{
			switch(get(i,j))
			{
			case TILE_NONE:
				if (roomType != RT_NULL)
					model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				break;
			case TILE_GRAVESTONE:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				model->addFloor(10*i,.4f,10*j,10*(i+1),.4f,10*(j+1),SHARECART_BLACK & 0x00FFFFFF | 0x66000000);
				model->addCube(10*i+1,0,10*j+3,10*(i+1)-1,7,10*(j+1)-3,SHARECART_GRAY,1,1,1,1,1,0);
				break;
			case TILE_BOOKSHELF:
				// left
				model->addCube(10*i,0,10*j,10*i+1,10+bookshelfboost,10*(j+1),SHARECART_RED,1,1,1,1,1,0);
				// right
				model->addCube(10*(i+1)-1,0,10*j,10*(i+1),10+bookshelfboost,10*(j+1),SHARECART_RED,1,1,1,1,1,0);
				// bottom
				model->addCube(10*i,0,10*j,10*(i+1),1+bookshelfboost,10*(j+1),SHARECART_RED,1,1,1,1,1,0);
				//top
				model->addCube(10*i,9+bookshelfboost,10*j,10*(i+1),10+bookshelfboost,10*(j+1),SHARECART_RED,1,1,1,1,1,0);

				model->addCube(10*i+1,1+bookshelfboost,10*(j+1)-1,10*i+3,7+bookshelfboost,10*(j+1)-5,SHARECART_GREEN,1,1,1,1,1,0);
				model->addCube(10*i+3,1+bookshelfboost,10*(j+1)-1,10*i+6,8+bookshelfboost,10*(j+1)-5,SHARECART_BLUE,1,1,1,1,1,0);
				model->addCube(10*i+6,1+bookshelfboost,10*(j+1)-1,10*i+7,6+bookshelfboost,10*(j+1)-5,SHARECART_GRAY,1,1,1,1,1,0);
				break;
			case TILE_SKULL:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				model->addFloor(10*i,.4f,10*j,10*(i+1),.4f,10*(j+1),SHARECART_BLACK & 0x00FFFFFF | 0x66000000);

				model->addCube(10*i+1,2,10*j+1,10*(i+1)-1,10,10*(j+1)-1,SHARECART_WHITE,1,1,1,1,1,0);

				model->addCube(10*i+2,7,10*(j+1),10*i+4,9,10*(j+1)+1,SHARECART_BLACK,1,1,0,1,1,0);
				model->addCube(10*(i+1)-4,7,10*(j+1),10*(i+1)-2,9,10*(j+1)+1,SHARECART_BLACK,1,1,0,1,1,0);
				break;
			case TILE_TREE:
				if (get(i-1,j-1) != TILE_TREE || get(i,j-1) != TILE_TREE || get(i+1,j-1) != TILE_TREE ||
					get(i-1,j) != TILE_TREE || get(i,j) != TILE_TREE || get(i+1,j) != TILE_TREE ||
					get(i-1,j+1) != TILE_TREE || get(i,j+1) != TILE_TREE || get(i+1,j+1) != TILE_TREE)
				{
					model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
					model->addFloor(10*i,.4f,10*j,10*(i+1),.4f,10*(j+1),SHARECART_BLACK & 0x00FFFFFF | 0x66000000);
					model->addCube(10*i+2,0,10*j+2,10*(i+1)-2,5,10*(j+1)-2,SHARECART_RED,1,1,1,1,0,0);
				}
				// frontfacing
				model->addTriangle(10*(i+1),5,10*(j+1), 10*i+5,20,10*j+5,  10*i,5,10*(j+1), SHARECART_GREEN, 0,0.70710678118654752440084436210485f,1);
				// right
				model->addTriangle(10*(i+1),5,10*j, 10*i+5,20,10*j+5, 10*(i+1),5,10*(j+1),SHARECART_GREEN,1,0.70710678118654752440084436210485f,0);
				//left
				model->addTriangle(10*i,5,10*(j+1), 10*i+5,20,10*j+5, 10*i,5,10*j, SHARECART_GREEN,-1,0.70710678118654752440084436210485f,0);
				//back
				model->addTriangle(10*i,5,10*j, 10*i+5,20,10*j+5,  10*(i+1),5,10*j, SHARECART_GREEN, 0,0.70710678118654752440084436210485f,-1);
				//model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				break;
			case TILE_SPIKE:
				// frontfacing
				model->addTriangle(10*(i+1),0,10*(j+1), 10*i+5,20,10*j+5,  10*i,0,10*(j+1), SHARECART_GRAY, 0,0.24253562503f,1);
				// right
				model->addTriangle(10*(i+1),0,10*j, 10*i+5,20,10*j+5, 10*(i+1),0,10*(j+1),SHARECART_GRAY,1,0.24253562503f,0);
				//left
				model->addTriangle(10*i,0,10*(j+1), 10*i+5,20,10*j+5, 10*i,0,10*j, SHARECART_GRAY,-1,0.24253562503f,0);
				//back
				model->addTriangle(10*i,0,10*j, 10*i+5,20,10*j+5,  10*(i+1),0,10*j, SHARECART_GRAY, 0,0.24253562503f,-1);
				//model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				break;
			case TILE_LIGHT:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				//model->addFloor(10*i-2,.4f,10*j-2,10*(i+1)+2,.4f,10*(j+1)+2,SHARECART_WHITE & 0x00FFFFFF | 0xAA000000);
				model->addFloor(10*i,.4f,10*j,10*(i+1),.4f,10*(j+1),SHARECART_WHITE & 0x00FFFFFF | 0xAA000000);
				break;
			case TILE_ROCK:
				model->addCube(10*i,-5,10*j,10*(i+1),5,10*(j+1),SHARECART_GRAY,tileIsBlocking(get(i-1,j)),tileIsBlocking(get(i+1,j)),tileIsBlocking(get(i,j-1)),tileIsBlocking(get(i,j+1)),1,0);
				break;
			case TILE_HOLE:
				if (get(i-1,j) != TILE_HOLE)
					model->addCube(10*(i-1),-82,10*j,10*i,0,10*(j+1),SHARECART_DARKRED,0,1,0,0,0,0);
				if (get(i+1,j) != TILE_HOLE)
					model->addCube(10*(i+1),-82,10*j,10*(i+2),0,10*(j+1),SHARECART_DARKRED,1,0,0,0,0,0);
				if (get(i,j-1) != TILE_HOLE)
					model->addCube(10*i,-82,10*(j-1),10*(i+1),0,10*j,SHARECART_DARKRED,0,0,0,1,0,0);
				if (get(i,j+1) != TILE_HOLE)
					model->addCube(10*i,-40,10*(j+1),10*(i+1),0,10*(j+2),SHARECART_DARKRED,0,0,1,0,0,0);
				break;
			case TILE_BRICK:
				model->addCube(10*i,0,10*j,10*(i+1),30,10*(j+1),SHARECART_RED,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
				model->addCube(10*i,30,10*j,10*(i+1),35,10*(j+1),SHARECART_GRAY,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
				break;
			case TILE_BRICKWINDOW:
				model->addCube(10*i,0,10*j,10*(i+1),30,10*(j+1),SHARECART_RED,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
				model->addCube(10*i,30,10*j,10*(i+1),35,10*(j+1),SHARECART_GRAY,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
				model->addCube(10*i,10,10*(j+1),10*(i+1),20,10*(j+1)+1,SHARECART_SKYBLUE,1,0,1,1,1,0);
				// bottom
				model->addCube(10*i-1,9,10*(j+1),10*(i+1)+1,11,10*(j+1)+2,SHARECART_YELLOW,1,0,1,1,1,0);
				// top
				model->addCube(10*i-1,19,10*(j+1),10*(i+1)+1,21,10*(j+1)+2,SHARECART_YELLOW,1,0,1,1,1,0);
				// left
				model->addCube(10*i-1,9,10*(j+1),10*i+1,21,10*(j+1)+2,SHARECART_YELLOW,1,0,1,1,1,0);
				// right
				model->addCube(10*(i+1)-1,9,10*(j+1),10*(i+1)+1,21,10*(j+1)+2,SHARECART_YELLOW,1,0,1,1,1,0);
				break;
			case TILE_DOOR:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				if (get(i-1,j) == TILE_BRICK || get(i,j-1) == TILE_BRICK || get(i+1,j) == TILE_BRICK)
				{
					model->addCube(10*i,0,10*j,10*(i+1),20,10*j+6,SHARECART_BLACK,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
					model->addCube(10*i,20,10*j,10*(i+1),30,10*(j+1),SHARECART_RED,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
					model->addCube(10*i,30,10*j,10*(i+1),35,10*(j+1),SHARECART_GRAY,get(i-1,j)!=TILE_BRICK,get(i+1,j)!=TILE_BRICK,get(i,j-1)!=TILE_BRICK,get(i,j+1)!=TILE_BRICK,1,0);
				}
				break;
			case TILE_DIRT:
				model->addCube(10*i,0,10*j,10*(i+1),5,10*(j+1),SHARECART_DARKRED,tileIsBlocking(get(i-1,j)),tileIsBlocking(get(i+1,j)),tileIsBlocking(get(i,j-1)),tileIsBlocking(get(i,j+1)),1,0);
				break;
			case TILE_FENCE:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				L = (get(i-1,j) == TILE_FENCE) || (get(i-1,j) == TILE_WHOOSHDOOR);
				R = (get(i+1,j) == TILE_FENCE) || (get(i+1,j) == TILE_WHOOSHDOOR);
				U = (get(i,j-1) == TILE_FENCE) || (get(i,j-1) == TILE_WHOOSHDOOR);
				D = (get(i,j+1) == TILE_FENCE) || (get(i,j+1) == TILE_WHOOSHDOOR);
				model->addCube(10*i+4,0,10*j+4,10*i+6,6,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				if (L && R)
					model->addCube(10*i,6,10*j+4,10*(i+1),8,10*j+6,SHARECART_DARKYELLOW,0,0,1,1,1,0);
				else if (L)
					model->addCube(10*i,6,10*j+4,10*i+6,8,10*j+6,SHARECART_DARKYELLOW,0,1,1,1,1,0);
				else if (R)
					model->addCube(10*i+4,6,10*j+4,10*(i+1),8,10*j+6,SHARECART_DARKYELLOW,1,0,1,1,1,0);

				if (U && D)
					model->addCube(10*i+4,6,10*j,10*i+6,8,10*(j+1),SHARECART_DARKYELLOW,1,1,0,0,1,0);
				else if (U)
					model->addCube(10*i+4,6,10*j,10*i+6,8,10*j+6,SHARECART_DARKYELLOW,1,1,0,1,1,0);
				else if (D)
					model->addCube(10*i+4,6,10*j+4,10*i+6,8,10*(j+1),SHARECART_DARKYELLOW,1,1,1,0,1,0);
				break;
			case TILE_STAIRSUP:
				model->addCube(10*i,0,10*j,10*i+3.33f,3.33f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				model->addCube(10*i+3.33f,0,10*j,10*i+6.66f,6.66f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				model->addCube(10*i+6.66f,0,10*j,10*i+9.99f,9.99f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				break;
			case TILE_STAIRSDOWN:
				model->addCube(10*i,-10,10*j,10*i+3.33f,-10+9.99f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				model->addCube(10*i+3.33f,-10,10*j,10*i+6.66f,-10+6.66f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				model->addCube(10*i+6.66f,-10,10*j,10*i+9.99f,-10+3.33f,10*(j+1),SHARECART_GRAY,1,1,0,1,1,0);
				if (get(i+1,j) != TILE_HOLE)
					model->addCube(10*(i+1),-40,10*j,10*(i+2),0,10*(j+1),SHARECART_DARKRED,1,0,0,0,0,0);
				if (get(i,j-1) != TILE_HOLE)
					model->addCube(10*i,-40,10*(j-1),10*(i+1),0,10*j,SHARECART_DARKRED,0,0,0,1,0,0);
				if (get(i,j+1) != TILE_HOLE)
					model->addCube(10*i,-40,10*(j+1),10*(i+1),0,10*(j+2),SHARECART_DARKRED,0,0,1,0,0,0);
				break;
			case TILE_SIGN:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				model->addCube(10*i+4,0,10*j+4,10*i+6,4,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				model->addCube(10*i,4,10*j+4,10*(i+1),10,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				break;
			case TILE_BIRD:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				//model->addCube(10*i+4,0,10*j+4,10*i+6,4,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				//model->addCube(10*i,4,10*j+4,10*(i+1),10,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				break;
			case TILE_WHOOSHDOOR:
				model->addFloor(10*i,0,10*j,10*(i+1),0,10*(j+1),floorColor);
				L = (get(i-1,j) == TILE_WHOOSHDOOR);
				R = (get(i+1,j) == TILE_WHOOSHDOOR);
				U = (get(i,j-1) == TILE_WHOOSHDOOR);
				D = (get(i,j+1) == TILE_WHOOSHDOOR);
				if ((L || R) || (!L && !R && !U && !D))
					model->addCube(10*i,0,10*j+4,10*(i+1),16,10*j+6,SHARECART_DARKYELLOW,1,1,1,1,1,0);
				else if (U || D)
					model->addCube(10*i+4,0,10*j,10*i+6,16,10*(j+1),SHARECART_DARKYELLOW,1,1,1,1,1,0);
				if (L || R && !U && !D)
				{
					if (L)
						model->addCube(10*i+2,6,10*j+3,10*i+4,8,10*j+7,SHARECART_YELLOW,1,1,1,1,1,0);
					else
						model->addCube(10*i+6,6,10*j+3,10*i+8,8,10*j+7,SHARECART_YELLOW,1,1,1,1,1,0);
				}
				else if (U || D && !R && !L)
				{
					if (U)
						model->addCube(10*i+3,6,10*j+2,10*i+7,8,10*j+4,SHARECART_YELLOW,1,1,1,1,1,0);
					else
						model->addCube(10*i+3,6,10*j+6,10*i+7,8,10*j+8,SHARECART_YELLOW,1,1,1,1,1,0);
				}
				else if (!L && !R && !U && !D)
				{
					if (rand()%2)
						model->addCube(10*i+2,6,10*j+3,10*i+4,8,10*j+7,SHARECART_YELLOW,1,1,1,1,1,0);
					else
						model->addCube(10*i+6,6,10*j+3,10*i+8,8,10*j+7,SHARECART_YELLOW,1,1,1,1,1,0);
				}
				break;
			}
		}
	model->finish();
	delete contents;
	if (startX != -1 && startY != -1)
	{
		rabbit->x = rabbit->targetX = 10*startX + 5;
		rabbit->z = rabbit->targetZ = 10*startY + 5;
		if (startRot != -1)
			rabbit->rotation = rabbit->targetRotation = startRot;
		else
			rabbit->rotation = rabbit->targetRotation = 90*(rand()%4);
		if (startFall)
			rabbit->y = 128;
	}
	if (lastRoomType != roomType)
	{
		stopAllMusic();
		playLevelMusic(roomType);
		lastRoomType = roomType;
	}
}
void Level::set(int x, int y, unsigned int tile)
{
	if (x < 0 || y < 0 || x >= width || y >= height)
		return;
	data[width*y+x] = tile;
}
unsigned int Level::get(int x, int y)
{
	if (x < 0 || y < 0 || x >= width || y >= height)
		return TILE_OUTOFBOUNDS;
	return data[width*y+x];
}
void Level::update()
{
	rabbit->update();
}
void Level::render()
{
	unsigned int TOPBARHEIGHT = 30;
#if PLATFORM_IOS
	if (Wumbo::Platform_iOS::iPad())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,768,1024,768,1024));
	else if (Wumbo::Platform_iOS::FourInch())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,568,320,568));
	else
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,480,320,480));
#else
	program->getRenderer()->setVirtualRenderTarget(VirtualRenderTarget(0,TOPBARHEIGHT*WINDOW_SCALE,WINDOW_WIDTH*WINDOW_SCALE,WINDOW_WIDTH*WINDOW_SCALE,WINDOW_WIDTH,WINDOW_WIDTH));
#endif
	glBindTexture(GL_TEXTURE_2D,white->getTexture());
	glClearColor(SHARECART_SKYBLUE);
	if (roomType == RT_UNDERGROUND)
		glClearColor(SHARECART_BLACK);
	if (roomType == RT_NULL)
		glClearColor(SHARECART_BLACK);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	static float degrees = 0;
	degrees += 5.f;// * glm::pi<float>() / 180.f;

	static float bob;
	bob += .2f;

	bool doswitch = false;
	if (PREPARETRANSFER_animate == 2)
	{
		if (cameraXoffset < -10*width+15)
			doswitch = true;
		else
			cameraXoffset -= 5;
	}
	if (PREPARETRANSFER_animate == 0)
	{
		if (cameraXoffset > 10*width-15)
			doswitch = true;
		else
			cameraXoffset += 5;
	}
	if (PREPARETRANSFER_animate == 1)
	{
		if (cameraYoffset < -10*height+15)
			doswitch = true;
		else
			cameraYoffset -= 5;
	}
	if (PREPARETRANSFER_animate == 3)
	{
		if (cameraYoffset > 10*height-15)
			doswitch = true;
		else
			cameraYoffset += 5;
	}
	if (doswitch)
	{
		sf::sleep(sf::seconds(.25f));
		program->setScene(new Level(program,PREPARETRANSFER_name,PREPARETRANSFER_x,PREPARETRANSFER_y,false,degreemod(rabbit->rotation)));
		return;
	}

	int xdist = 0;
	int ydist = 180;
	int zdist = 120;

	VIEW = glm::lookAt(glm::vec3(10*width/2+xdist+cameraXoffset,ydist,10*width/2+zdist+cameraYoffset),glm::vec3(10*width/2+cameraXoffset,0.f,10*height/2+cameraYoffset),glm::vec3(0.f,1.f,0.f));//glm::ortho(-1.f,1.f,1.f,-1.f,-10.f,10.f);// * glm::translate(glm::mat4(1.0f), glm::vec3(-10.f,-10.f,0)) * glm::scale(glm::mat4(1.0f),glm::vec3(2.f/320.f,2.f/480.f,0.f));
	PROJ = glm::perspectiveFov(45.f,(float)WINDOW_WIDTH,(float)WINDOW_WIDTH,1.f,5000.f);

	matrixBegin();
	matrixUpload();
	if (model != NULL)
		model->draw();
	// DRAW SPINNY THING
	/*matrixBegin();
	matrixTranslate(105,5,105);
	matrixRotate(degrees,0,1,0);
	matrixRotate(45,0,0,1);
	matrixUpload();
	potato->draw();*/
	rabbit->render();

	for(int i=0;i<talkers.size();i++)
	{
		talkers.at(i).update();
		talkers.at(i).render();
	}
// BEGIN ORTHO STUFF
	glBindTexture(GL_TEXTURE_2D,tex->getTexture());
	glClearColor(SHARECART_BLACK);

#if PLATFORM_IOS
	if (Wumbo::Platform_iOS::iPad())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,768,1024,768,1024));
	else if (Wumbo::Platform_iOS::FourInch())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,568,320,568));
	else
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,480,320,480));
#else
	program->getRenderer()->setVirtualRenderTarget(VirtualRenderTarget(0,0,WINDOW_WIDTH*WINDOW_SCALE,TOPBARHEIGHT*WINDOW_SCALE,WINDOW_WIDTH,TOPBARHEIGHT));
#endif
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	VIEW = glm::mat4x4(1.f);//glm::lookAt(glm::vec3(10*width/2+xdist,ydist,10*width/2+zdist),glm::vec3(10*width/2,0.f,10*height/2),glm::vec3(0.f,1.f,0.f));//glm::ortho(-1.f,1.f,1.f,-1.f,-10.f,10.f);// * glm::translate(glm::mat4(1.0f), glm::vec3(-10.f,-10.f,0)) * glm::scale(glm::mat4(1.0f),glm::vec3(2.f/320.f,2.f/480.f,0.f));
	PROJ = glm::ortho(0.f,(float)WINDOW_WIDTH,(float)TOPBARHEIGHT,0.f);

	draw_rectangle(0,0,WINDOW_WIDTH,TOPBARHEIGHT);
	//glm::ortho(
	draw_text(160-(levelname.size()/2.f)*10,10,levelname);

#if PLATFORM_IOS
	if (Wumbo::Platform_iOS::iPad())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,768,1024,768,1024));
	else if (Wumbo::Platform_iOS::FourInch())
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,568,320,568));
	else
		renderer->setVirtualRenderTarget(VirtualRenderTarget(0,0,320,480,320,480));
#else
	program->getRenderer()->setVirtualRenderTarget(VirtualRenderTarget(0,(WINDOW_WIDTH+TOPBARHEIGHT)*WINDOW_SCALE,WINDOW_WIDTH*WINDOW_SCALE,(WINDOW_HEIGHT-WINDOW_WIDTH-TOPBARHEIGHT)*WINDOW_SCALE,WINDOW_WIDTH,WINDOW_HEIGHT-WINDOW_WIDTH-TOPBARHEIGHT));
#endif
	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	VIEW = glm::mat4x4(1.f);//glm::lookAt(glm::vec3(10*width/2+xdist,ydist,10*width/2+zdist),glm::vec3(10*width/2,0.f,10*height/2),glm::vec3(0.f,1.f,0.f));//glm::ortho(-1.f,1.f,1.f,-1.f,-10.f,10.f);// * glm::translate(glm::mat4(1.0f), glm::vec3(-10.f,-10.f,0)) * glm::scale(glm::mat4(1.0f),glm::vec3(2.f/320.f,2.f/480.f,0.f));
	PROJ = glm::ortho(0.f,(float)WINDOW_WIDTH,(float)(WINDOW_HEIGHT-WINDOW_WIDTH)-TOPBARHEIGHT,0.f);

	draw_rectangle(0,0,WINDOW_WIDTH,(WINDOW_HEIGHT-WINDOW_WIDTH)-TOPBARHEIGHT);
	if (phrases.size() > 0)
	{
		if (talkTicker == 0)
		{
			if (talkPosition != phrases.at(0).text.size()*2)
			{
				if (talkPosition % 2 == 0 && (phrases.at(0).text.at(talkPosition/2) == 13))
				{
					talkPosition += 4;
				}
				else
				{
					if (talkPosition % 2 == 0 && phrases.at(0).text.at(talkPosition/2) == '`')
					{
						std::vector<double> *vec = NULL;
						if (phrases.at(0).voice == VC_DEFAULT)
							vec = &snd_voice_default;
						if (phrases.at(0).voice == VC_BIRD)
							vec = &snd_voice_bird;
						if (phrases.at(0).voice == VC_SCRIBBLE)
							vec = &snd_voice_scribble;
						ss_playsound_distort_vector(vec);
						talkPosition += 2;
					}
					else if (talkPosition < phrases.at(0).text.size()*2)
						talkPosition++;
				}
			}
		}
		talkTicker++;
		if (talkTicker == 1)
			talkTicker = 0;
		if (phrases.size() > 0)
		{
			if (Wumbo::__quickyKeyboard->isKeyPressed(Wumbo::Key::X))
			{
				if (talkPosition == phrases.at(0).text.size()*2)
				{
					phrases.erase(phrases.begin());
					if (phrases.size() > 0)
					{
						talkTicker = 0;
						talkPosition = 0;
					}
					else
						displayingDialog = false;
				}
				else
					talkPosition = phrases.at(0).text.size()*2;
			}
			if (phrases.size() > 0)
			{
				draw_text(10,10,phrases.at(0).text,talkPosition);
				if (talkPosition == phrases.at(0).text.size()*2 && phrases.size() > 1)
					draw_text(300,(WINDOW_HEIGHT-WINDOW_WIDTH-TOPBARHEIGHT)-10,"\x1F");
			}
		}
	}
}
void Level::addPhrase(std::string text, int voice)
{
	talkPosition = 0;
	talkTicker = 0;
	TalkerPhrase bob;
	bob.text = text;
	bob.voice = voice;
	phrases.push_back(bob);
}