#include "sys_interaction.h"
#include "system.h"
#include "sys_vr.h"
#include "sys_vr_passthru.h"
#include "sys_render.h"
#include "sys_undo.h"
#include "sys_tilestore.h"

#define PICK_LEN (0.03f)
#define PICK_OFF {0.0,PICK_LEN * -0.7071067811865476f, PICK_LEN * -0.7071067811865476f,1.0f}
#define PICK_DIR {0.0,-0.7071067811865476f,-0.7071067811865476f,0.0f}
#define PICK_NOTDIR {0.0,0.7071067811865476f,-0.7071067811865476f,0.0f}

#define DIST_MIN 0.0f
#define DIST_MAX 64.0f

#define WND_WIDTH (0.37f)
#define WND_HEIGHT (0.24f)
#define WND_H_TOP (0.039f)
#define WND_H_BOT (0.03f)
#define WND_H_MID (WND_HEIGHT - WND_H_TOP - WND_H_BOT)

#define clamp(l,h,v) (((h)>(v))?(((v)<(l))?(l):(v)):(h))

//TODO: haptic poke feedback

static uint32_t tracked_id = 0xfffffffful;
static unsigned toolidx = 0;
static int touchdown;
static int trigdown;
static yrModel mdl_tip = NULL;
static yrTexture tex_fill = NULL;
static mat4f saved_mat;
static int poslocked;
static int selecting;
static yrQuad selected_restore;
static yrQuad* selected = NULL;
static yrTexture tex_tab[3] = {NULL};
static yrTexture tex_label[10] = {NULL};
static yrTexture tex_target = NULL;
static yrTexture tex_nobg = NULL;
static yrTexture tex_arrow = NULL;
static yrTexture tpadbut_target = NULL;
static yrTexture tpadbut_target_glow = NULL;
static yrTexture tpadbut_arrows = NULL;
static yrTexture tpadbut_arrows_glow[5] = {NULL};
enum uibut { ubUp, ubDown, ubLeft, ubRight, ubCenter, ubRelease, ubNone};
static struct {
	int tab;
	int uisection;
	int pokereset;
	//colors tab
	struct {
		int selected;
		int active;
		yrColor colors[8];
	}
	colors;
	//backgrounds tab
	struct {
		int selected;
		int active;
		float row;
		int count;
	}
	backgrounds;
	//positioning tab
	struct {
		float off_x;
		float off_y;
		float xbound[2];
		float ybound[2];
		float scale_x;
		float scale_y;
		float row;
		int fit;
		int flipx;
		int flipy;
		int pin;
		int ar11;
		int repeat;
		int selected;
		enum uibut held;
		uint64_t nexttick;
	}
	positioning;
}
uistate = {0};
static struct {
	yrTexture tex;
	size_t w;
	size_t h;
}
*bg_images = NULL;
static size_t bg_count = 0;

static void background_shutdown(void);
static void background_settrackedid(uint32_t, unsigned);
static void background_tick(void);
static int  background_canfreeze(void);
static void background_forceidle(void);
static int	background_getpokepos(vec4f* pos, vec4f* dir, float* len);
static void background_renderwindow(void);
static void background_poke(void);

int tool_background_init(func_tool_shutdown* st_sd,
						 func_tool_settrackedid* ft_sti,
						 func_tool_tick* ft_t,
						 func_tool_canfreeze* ft_cf,
						 func_tool_forceidle* ft_fi,
						 func_tool_getpokepos* ft_gpp,
						 func_tool_renderwindow* ft_rw,
						 func_tool_poke* ft_p)
{
	*st_sd	= background_shutdown;
	*ft_sti	= background_settrackedid;
	*ft_t	= background_tick;
	*ft_cf	= background_canfreeze;
	*ft_fi	= background_forceidle;
	*ft_gpp = background_getpokepos;	
	*ft_rw	= background_renderwindow;
	*ft_p	= background_poke;

	tracked_id = 0xfffffffful;
	touchdown = 0;
	poslocked = 0;
	toolidx = 0;
	selected = NULL;
	memset(&uistate, 0, sizeof(uistate));
	uistate.colors.active = -1;
	uistate.backgrounds.active = 0;
	uistate.pokereset = 1;
	tex_fill	= yrTexture_loadfile("data/vr/empty.png");			if(!tex_fill) return -1;
	tex_target	= yrTexture_loadfile("data/vr/button_target.png");	if(!tex_target) return -1;
	tex_tab[0]	= yrTexture_loadfile("data/vr/tab_color.png");		if(!tex_tab[0]) return -1;
	tex_tab[1]	= yrTexture_loadfile("data/vr/tab_image.png");		if(!tex_tab[1]) return -1;
	tex_tab[2]	= yrTexture_loadfile("data/vr/tab_position.png");	if(!tex_tab[2]) return -1;
	tex_label[0]= yrTexture_loadfile("data/vr/label_x.png");		if(!tex_label[0]) return -1;
	tex_label[1]= yrTexture_loadfile("data/vr/label_y.png");		if(!tex_label[1]) return -1;
	tex_label[2]= yrTexture_loadfile("data/vr/label_w.png");		if(!tex_label[2]) return -1;
	tex_label[3]= yrTexture_loadfile("data/vr/label_h.png");		if(!tex_label[3]) return -1;
	tex_label[4]= yrTexture_loadfile("data/vr/label_flipx.png");	if(!tex_label[4]) return -1;
	tex_label[5]= yrTexture_loadfile("data/vr/label_flipy.png");	if(!tex_label[5]) return -1;
	tex_label[6]= yrTexture_loadfile("data/vr/label_fit.png");		if(!tex_label[6]) return -1;
	tex_label[7]= yrTexture_loadfile("data/vr/label_tile.png");	if(!tex_label[7]) return -1;
	tex_label[8]= yrTexture_loadfile("data/vr/label_ar11.png");	if(!tex_label[8]) return -1;
	tex_label[9]= yrTexture_loadfile("data/vr/label_pin.png");		if(!tex_label[9]) return -1;
	tex_nobg	= yrTexture_loadfile("data/vr/label_nobg.png");	if(!tex_nobg) return -1;
	tex_arrow	= yrTexture_loadfile("data/vr/but_arrow.png");		if(!tex_arrow) return -1;
	tpadbut_target			= yrTexture_loadfile("data/vr/tpadbut_target.png");		if(!tpadbut_target) return -1;
	tpadbut_target_glow		= yrTexture_loadfile("data/vr/tpadbut_target_glow.png");	if(!tpadbut_target_glow) return -1;
	tpadbut_arrows			= yrTexture_loadfile("data/vr/tpadbut_arrows.png");		if(!tpadbut_arrows) return -1;
	tpadbut_arrows_glow[0]	= yrTexture_loadfile("data/vr/tpadbut_arrows_center.png");	if(!tpadbut_arrows_glow[0]) return -1;
	tpadbut_arrows_glow[1]	= yrTexture_loadfile("data/vr/tpadbut_arrows_right.png");	if(!tpadbut_arrows_glow[1]) return -1;
	tpadbut_arrows_glow[2]	= yrTexture_loadfile("data/vr/tpadbut_arrows_up.png");		if(!tpadbut_arrows_glow[2]) return -1;
	tpadbut_arrows_glow[3]	= yrTexture_loadfile("data/vr/tpadbut_arrows_left.png");	if(!tpadbut_arrows_glow[3]) return -1;
	tpadbut_arrows_glow[4]	= yrTexture_loadfile("data/vr/tpadbut_arrows_down.png");	if(!tpadbut_arrows_glow[4]) return -1;
	mdl_tip = yrModel_load("data/vr/pen_tip.ymd"); if(!mdl_tip) return -1;

	//load background image data
	bg_count = yrRender_get_bgcount();
	uistate.backgrounds.count = (int) bg_count;
	if(bg_count) {
		bg_images = malloc(bg_count * sizeof(*bg_images));
		if(!bg_images) return -1;
		for(size_t i = 0; i < bg_count; ++i) {
			yrRender_get_bgdata(i, &bg_images[i].tex, &bg_images[i].w, &bg_images[i].h);
		}
	}
	return 0;
}

static void background_shutdown(void)
{
	yrTexture_unload(tex_fill);
	yrTexture_unload(tex_target);
	yrTexture_unload(tex_tab[0]);
	yrTexture_unload(tex_tab[1]);
	yrTexture_unload(tex_tab[2]);
	yrTexture_unload(tex_label[0]);
	yrTexture_unload(tex_label[1]);
	yrTexture_unload(tex_label[2]);
	yrTexture_unload(tex_label[3]);
	yrTexture_unload(tex_label[4]);
	yrTexture_unload(tex_label[5]);
	yrTexture_unload(tex_label[6]);
	yrTexture_unload(tex_label[7]);
	yrTexture_unload(tex_label[8]);
	yrTexture_unload(tex_label[9]);
	yrTexture_unload(tex_nobg);
	yrTexture_unload(tex_arrow);
	yrTexture_unload(tpadbut_arrows_glow[0]);
	yrTexture_unload(tpadbut_arrows_glow[1]);
	yrTexture_unload(tpadbut_arrows_glow[2]);
	yrTexture_unload(tpadbut_arrows_glow[3]);
	yrTexture_unload(tpadbut_arrows);
	yrTexture_unload(tpadbut_target_glow);
	yrTexture_unload(tpadbut_target);
	yrModel_unload(mdl_tip);
	tex_fill = NULL;
	tex_target = NULL;
	tex_tab[0] = NULL;
	tex_tab[1] = NULL;
	tex_tab[2] = NULL;
	tex_label[0] = NULL;
	tex_label[1] = NULL;
	tex_label[2] = NULL;
	tex_label[3] = NULL;
	tex_label[4] = NULL;
	tex_label[5] = NULL;
	tex_label[6] = NULL;
	tex_label[7] = NULL;
	tex_label[8] = NULL;
	tex_label[9] = NULL;
	tex_nobg = NULL;
	tex_arrow = NULL;
	tpadbut_arrows_glow[0] = NULL;
	tpadbut_arrows_glow[1] = NULL;
	tpadbut_arrows_glow[2] = NULL;
	tpadbut_arrows_glow[3] = NULL;
	tpadbut_arrows_glow[4] = NULL;
	tpadbut_arrows = NULL;
	tpadbut_target_glow = NULL;
	tpadbut_target = NULL;
	mdl_tip = NULL;
	free(bg_images);
	bg_images = NULL;
	bg_count = 0;
}

static void background_settrackedid(uint32_t tr_id, unsigned tool_idx)
{
	background_forceidle();
	tracked_id = tr_id;
	toolidx = tool_idx;
}

static float ar11_width(yrQuad* q, float height)
{
	if(!q || q->texture_bg >= bg_count) return height;
	size_t bgidx = q->texture_bg;
	float h = fabsf(height);
	float w = q->uv_back[1][0] - q->uv_back[0][0];
	return copysignf((h * bg_images[bgidx].h * q->width) / (bg_images[bgidx].w * q->height), w);
}

static float ar11_height(yrQuad* q, float width)
{
	if(!q || q->texture_bg >= bg_count) return width;
	size_t bgidx = q->texture_bg;
	float w = fabsf(width);
	float h = q->uv_back[1][1] - q->uv_back[0][1];
	return copysignf((w * bg_images[bgidx].w * q->height) / (bg_images[bgidx].h * q->width), h);
}

static void uistate_update(yrQuad* q)
{
	if(!q) return;
	uistate.colors.active = -1;
	uistate.backgrounds.active = selected->texture_bg + 1;
	uistate.positioning.off_x = selected->uv_back[0][0];
	uistate.positioning.off_y = selected->uv_back[0][1];
	uistate.positioning.scale_x = 1.0f/fabsf(selected->uv_back[1][0] - selected->uv_back[0][0]);
	uistate.positioning.scale_y = 1.0f/fabsf(selected->uv_back[1][1] - selected->uv_back[0][1]);
	uistate.positioning.repeat = (selected->flags & QUAD_BG_TILE) != 0;
	uistate.positioning.fit = 0;
	uistate.positioning.flipx = selected->uv_back[1][0] < selected->uv_back[0][0];
	uistate.positioning.flipy = selected->uv_back[1][1] < selected->uv_back[0][1];
	uistate.positioning.ar11 = (selected->flags & QUAD_BG_AR11) != 0;
	uistate.positioning.pin = (selected->flags & QUAD_BG_PIN) != 0;

	//limit range
	uistate.positioning.scale_x = clamp(0.0078125f, 128.0f, uistate.positioning.scale_x);
	uistate.positioning.scale_y = clamp(0.0078125f, 128.0f, uistate.positioning.scale_y);
	float lox = (-1.0f/uistate.positioning.scale_x) - 1.0f;
	float hix = 1.0f;
	float loy = (-1.0f/uistate.positioning.scale_y) - 1.0f;
	float hiy = 1.0f;
	uistate.positioning.off_x = clamp(lox, hix, uistate.positioning.off_x);
	uistate.positioning.off_y = clamp(loy, hiy, uistate.positioning.off_y);
	uistate.positioning.xbound[0] = lox;
	uistate.positioning.xbound[1] = hix;
	uistate.positioning.ybound[0] = loy;
	uistate.positioning.ybound[1] = hiy;
}

static void uiaction_setcolor(int index)
{
	uistate.colors.active = index;
	yrInteraction_setbgcolor(uistate.colors.colors[index]);
	if(selected) selected->color = uistate.colors.colors[index];
}

static void uiaction_setimage(int index)
{
	uistate.backgrounds.active = index;
	int img = index ? (index - 1) : 125;
	yrInteraction_setbgimage(img);
	if(selected) {
		if(selected->texture_bg != (unsigned char) img) {
			selected->texture_bg = (unsigned char) img;
			if(selected->flags & QUAD_BG_AR11) {
				float w = selected->uv_back[1][0] - selected->uv_back[0][0];
				float h = ar11_height(selected, w);
				selected->uv_back[1][1] = selected->uv_back[0][1] + h;
				uistate_update(selected);
			}
		}
	}
}

static void uiaction_toggle_flipx(void)
{
	uistate.positioning.flipx = !uistate.positioning.flipx;
	if(selected) {
		float swap = selected->uv_back[0][0];
		selected->uv_back[0][0] = selected->uv_back[1][0];
		selected->uv_back[1][0] = swap;
		uistate_update(selected);
	}
}

static void uiaction_toggle_flipy(void)
{
	uistate.positioning.flipy = !uistate.positioning.flipy;
	if(selected) {
		float swap = selected->uv_back[0][1];
		selected->uv_back[0][1] = selected->uv_back[1][1];
		selected->uv_back[1][1] = swap;
		uistate_update(selected);
	}
}

static void uiaction_toggle_repeat(void)
{
	if(selected) {
		if(selected->flags & QUAD_BG_TILE) {
			selected->flags &= ~QUAD_BG_TILE;
		} else {
			selected->flags |= QUAD_BG_TILE;
		}
		uistate.positioning.repeat = (selected->flags & QUAD_BG_TILE)!=0;
	}
	else {
		uistate.positioning.repeat = !uistate.positioning.repeat;
	}
}

static void uiaction_toggle_fit(void)
{
	uistate.positioning.fit = !uistate.positioning.fit;
	if(selected && uistate.positioning.fit)
	{
		selected->uv_back[0][0] = roundf(selected->uv_back[0][0]);
		selected->uv_back[0][1] = roundf(selected->uv_back[0][1]);
		selected->uv_back[1][0] = roundf(selected->uv_back[1][0]);
		selected->uv_back[1][1] = roundf(selected->uv_back[1][1]);
		//no zero-scale
		if((selected->uv_back[1][0] - selected->uv_back[0][0]) == 0.0f) {
			selected->uv_back[1][0] += 1.0f;
		}
		if((selected->uv_back[1][1] - selected->uv_back[0][1]) == 0.0f) {
			selected->uv_back[1][1] += 1.0f;
		}
		//respect aspect ratio
		if(selected->flags & QUAD_BG_AR11) {
			float w = selected->uv_back[1][0] - selected->uv_back[0][0];
			float h = ar11_height(selected, w);
			selected->uv_back[1][1] = selected->uv_back[0][1] + h;
		}
		//update ui
		uistate_update(selected);
	}
}

static void uiaction_toggle_ar11(void)
{
	if(selected) {
		if(selected->flags & QUAD_BG_AR11) {
			selected->flags &= ~QUAD_BG_AR11;
		} else {
			selected->flags |= QUAD_BG_AR11;
			if(selected->texture_bg < bg_count) {
				float w = selected->uv_back[1][0] - selected->uv_back[0][0];
				float h = ar11_height(selected, w);
				selected->uv_back[1][1] = selected->uv_back[0][1] + h;
				uistate_update(selected);
			}
		}
		uistate.positioning.ar11 = (selected->flags & QUAD_BG_AR11)!=0;
	}
	else {
		uistate.positioning.ar11 = !uistate.positioning.ar11;
	}
}

static void uiaction_toggle_pin(void)
{
	if(selected) {
		if(selected->flags & QUAD_BG_PIN) {
			selected->flags &= ~QUAD_BG_PIN;
		} else {
			selected->flags |= QUAD_BG_PIN;
		}
		uistate.positioning.pin = (selected->flags & QUAD_BG_PIN)!=0;
	}
	else {
		uistate.positioning.pin = !uistate.positioning.pin;
	}
}

static void uiaction_slide_x(int val)
{
	if(!selected) return;
	uistate.positioning.fit = 0;

	float milli = 0.001f * UV_PER_METER / (uistate.positioning.scale_x * selected->width);
	float diff = selected->uv_back[1][0] - selected->uv_back[0][0];
	selected->uv_back[0][0] = uistate.positioning.off_x + val*milli;
	selected->uv_back[1][0] = selected->uv_back[0][0] + diff;
	uistate_update(selected);
}

static void uiaction_slide_y(int val)
{
	if(!selected) return;
	uistate.positioning.fit = 0;

	float milli = 0.001f * UV_PER_METER / (uistate.positioning.scale_y * selected->height);
	float diff = selected->uv_back[1][1] - selected->uv_back[0][1];
	selected->uv_back[0][1] = uistate.positioning.off_y + val*milli;
	selected->uv_back[1][1] = selected->uv_back[0][1] + diff;
	uistate_update(selected);
}

static void uiaction_slide_w(int val)
{
	if(!selected) return;
	uistate.positioning.fit = 0;

	float factor = powf(1.05f, -(float) val);
	float w = 1.0f / (uistate.positioning.scale_x * factor);
	selected->uv_back[0][0] /= factor;
	selected->uv_back[1][0] = selected->uv_back[0][0] + copysignf(w, selected->uv_back[1][0] - selected->uv_back[0][0]);
	if(selected->flags & QUAD_BG_AR11) {
		float h = ar11_height(selected, w);
		selected->uv_back[0][1] /= factor;
		selected->uv_back[1][1] = selected->uv_back[0][1] + h;
	}
	uistate_update(selected);
}

static void uiaction_slide_h(int val)
{
	if(!selected) return;
	uistate.positioning.fit = 0;

	float factor = powf(1.05f, -(float) val);
	float h = 1.0f / (uistate.positioning.scale_y * factor);
	selected->uv_back[0][1] /= factor;
	selected->uv_back[1][1] = selected->uv_back[0][1] + copysignf(h, selected->uv_back[1][1] - selected->uv_back[0][1]);
	if(selected->flags & QUAD_BG_AR11) {
		float w = ar11_width(selected, h);
		selected->uv_back[0][0] /= factor;
		selected->uv_back[1][0] = selected->uv_back[0][0] + w;
	}
	uistate_update(selected);
}

static void uiaction_slider(int sld, int val)
{
	switch(sld) {
		case 0: uiaction_slide_x(val); break;
		case 1: uiaction_slide_y(val); break;
		case 2: uiaction_slide_w(val); break;
		case 3: uiaction_slide_h(val); break;
	}
}

static int uibutton_top(enum uibut b)
{
	switch(b) {
		case ubUp:
			return 2;
		case ubDown:
			switch(uistate.tab) {
				case 0:
					uistate.colors.selected = 0;
					break;
				case 1:
					uistate.backgrounds.selected = 0;
					uistate.backgrounds.row = 0.0f;
					break;
				case 2:
					uistate.positioning.selected = 0;
					uistate.positioning.held = 0;
					uistate.positioning.row = 0.0f;
					break;
			}
			return 1;
		case ubLeft:
			uistate.tab -= 1;
			if(uistate.tab < 0) uistate.tab = 2;
			return 0;
		case ubRight:
			uistate.tab += 1;
			if(uistate.tab > 2) uistate.tab = 0;
			return 0;
	}
	return 0;
}
static int uibutton_mid(enum uibut b)
{
	switch(uistate.tab) {
		//colors tab
		case 0: {
			int sel = uistate.colors.selected;
			if(b == ubUp) {
				if(sel < 3) return 0;
				else if(sel == 3) sel = 0;
				else if(sel < 7) sel -= 4;
				else sel = 2;
			}
			if(b == ubDown) {
				if(sel < 3) sel += 4;
				else return 2;
			}
			if(b == ubLeft) sel -= 1;
			if(b == ubRight) sel += 1;
			if(sel < 0) sel = 7;
			if(sel > 7) sel = 0;
			uistate.colors.selected = sel;
			if(b == ubCenter) {
				uiaction_setcolor(sel);
			}
			break;
		}
		//image tab
		case 1: {
			int sel = uistate.backgrounds.selected;
			if(b == ubUp) sel -= 5;
			if(b == ubDown) sel += 5;
			if(sel < 0) return 0;
			if(sel >= uistate.backgrounds.count + 1) return 2;
			if(b == ubLeft) sel -= 1;
			if(b == ubRight) sel += 1;
			if(sel < 0) sel = uistate.backgrounds.count;
			if(sel >= uistate.backgrounds.count + 1) sel = 0;
			uistate.backgrounds.selected = sel;
			if(b==ubUp || b==ubDown || b==ubLeft || b==ubRight) {
				int rowoff = ((int) uistate.backgrounds.row) * 5;
				if(sel < rowoff) uistate.backgrounds.row = (float)(sel/5);
				if(sel >= rowoff + 15) uistate.backgrounds.row = (float)(sel/5) - 2.0f;
			}
			if(b == ubCenter) {
				uiaction_setimage(sel);
			}
			break;
		}
		//positioning tab
		case 2: {
			int sel = uistate.positioning.selected;
			if(b == ubUp) sel -= 1;
			if(b == ubDown) sel += 1;
			if(sel < 0) return 0;
			if(sel >= 10) return 2;
			uistate.positioning.selected = sel;

			if(b==ubUp || b==ubDown) {
				int rowoff = ((int) floorf(uistate.positioning.row));
				if(sel < rowoff) uistate.positioning.row = (float) sel;
				if(sel >= rowoff + 4) uistate.positioning.row = (float)(sel-3);
			}

			//x and y
			if(sel < 4) {
				uint64_t t = yr_get_microtime();
				uint64_t n = uistate.positioning.nexttick;
				if(b == ubLeft) {
					uiaction_slider(sel, 1);
					uistate.positioning.nexttick = t + 1000000;
				}
				else if(b == ubRight) {
					uiaction_slider(sel, -1);
					uistate.positioning.nexttick = t + 1000000;
				}
				else if(t > n && uistate.positioning.held == ubLeft) {
					uiaction_slider(sel, 5); //TODO: time-varying value?
					uistate.positioning.nexttick = t + 250000;
				}
				else if(t > n && uistate.positioning.held == ubRight) {
					uiaction_slider(sel, -5); //TODO: time-varying value?
					uistate.positioning.nexttick = t + 250000;
				}
			}
			//checkboxes, handle center button
			else {
				if(b == ubCenter) {
					switch(sel) {
						case 4: uiaction_toggle_flipx(); break;
						case 5: uiaction_toggle_flipy(); break;
						case 6: uiaction_toggle_fit(); break;
						case 7: uiaction_toggle_repeat(); break;
						case 8: uiaction_toggle_ar11(); break;
						case 9: uiaction_toggle_pin(); break;
					}
				}
			}
			if(b != ubNone) uistate.positioning.held = b;
			break;
		}
	}
	return 1;
}
static int uibutton_bot(enum uibut b)
{
	switch(b) {
	case ubCenter: selecting = 1; break;
	case ubDown: return 0;
	case ubUp: 
		switch(uistate.tab) {
			case 0:
				uistate.colors.selected = 7;
				break;
			case 1:
				uistate.backgrounds.selected = uistate.backgrounds.count;
				uistate.backgrounds.row = (uistate.backgrounds.selected/5) - 2.0f;
				if(uistate.backgrounds.row < 0.0f) uistate.backgrounds.row = 0.0f;
				break;
			case 2:
				uistate.positioning.selected = 9;
				uistate.positioning.held = 0;
				uistate.positioning.row = 6.0f;
				break;
		}
		return 1;
	}
	return 2;
}

static void uidraw_tabclr(void)
{
	uistate.colors.colors[0] = yrInteraction_getpencolor();
	uistate.colors.colors[1] = 0xFF101010;
	uistate.colors.colors[2] = 0xFFF0F0F0;
	uistate.colors.colors[3] = yrInteraction_getsavedcolor(0);
	uistate.colors.colors[4] = yrInteraction_getsavedcolor(1);
	uistate.colors.colors[5] = yrInteraction_getsavedcolor(2);
	uistate.colors.colors[6] = yrInteraction_getsavedcolor(3);
	uistate.colors.colors[7] = yrInteraction_getsavedcolor(4);

	float hsize = (WND_WIDTH - 2 * 0.01f) * UV_PER_METER;
	float vsize = (WND_H_MID - 2 * 0.02f) * UV_PER_METER;
	float dx = hsize / 5;
	float dy = -vsize / 3;
	float basex = 0.01f * UV_PER_METER;
	float basey = (WND_HEIGHT - WND_H_TOP - 0.02f) * UV_PER_METER + dy/3;

	size_t idx = 0;
	for(size_t r = 0; r < 2; ++r)
	{
		size_t basec = r ? 0 : 1;
		size_t maxc = r ? 5 : 4;
		for(size_t c = basec; c < maxc; ++c, ++idx)
		{
			float lox = basex + c * dx;
			float hix = lox + dx - 0.01f * UV_PER_METER;
			float hiy = basey + r * (dy + dy/3);
			float loy = hiy + dy + 0.01f * UV_PER_METER;
			//border
			float w = (idx == uistate.colors.active) ? 0.02f : 0.006f;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - w, loy - w, hix + w, hiy + w, 0xFFFFFFFFul);
			//color
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, uistate.colors.colors[idx]);
			//selection border
			if(uistate.uisection == 1 && idx == uistate.colors.selected)
			{
				yrColor foo = 0xFF000000ul | ~uistate.colors.colors[idx];
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, loy + 0.01f, hix - 0.01f, loy + 0.02f, foo);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, hiy - 0.02f, hix - 0.01f, hiy - 0.01f, foo);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, loy + 0.01f, lox + 0.02f, hiy - 0.01f, foo);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, hix - 0.02f, loy + 0.01f, hix - 0.01f, hiy - 0.01f, foo);
			}
		}
	}
}

static void uidraw_tabimg(void)
{
	//items
	float hsize = (WND_WIDTH - 2 * 0.01f) * UV_PER_METER;
	float vsize = (WND_H_MID - 2 * 0.02f) * UV_PER_METER;
	float dx = hsize / 5;
	float dy = -vsize / 3;
	float basex = 0.01f * UV_PER_METER;
	float basey = (WND_HEIGHT - WND_H_TOP - 0.02f) * UV_PER_METER - uistate.backgrounds.row * dy;
	size_t idxbase = ((size_t) uistate.backgrounds.row) * 5;

	if(uistate.backgrounds.count == 0) {
		float lox = (WND_WIDTH - 0.26f)/2 * UV_PER_METER;
		float hix = (WND_WIDTH + 0.26f)/2 * UV_PER_METER;
		float loy = (WND_HEIGHT - 0.032f)/2 * UV_PER_METER;
		float hiy = (WND_HEIGHT + 0.032f)/2 * UV_PER_METER;
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_nobg, lox, loy, hix, hiy, 0xFFFFFFFFul);
	}
	else {
		for(size_t r = 0; r < 4; ++r)
		for(size_t c = 0; c < 5; ++c)
		{
			size_t idx = idxbase + r*5 + c;
			if(idx >= uistate.backgrounds.count + 1) break;
			float lox = basex + c * dx;
			float hix = lox + dx - 0.01f * UV_PER_METER;
			float hiy = basey + (r + floorf(uistate.backgrounds.row)) * dy;
			float loy = hiy + dy + 0.01f * UV_PER_METER;
			//border
			float w = (idx == uistate.backgrounds.active) ? 0.015f : 0.006f;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - w, loy - w, hix + w, loy    , 0xFFFFFFFFul);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - w, hiy    , hix + w, hiy + w, 0xFFFFFFFFul);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - w, loy - w, lox    , hiy + w, 0xFFFFFFFFul);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, hix    , loy - w, hix + w, hiy + w, 0xFFFFFFFFul);
			//image
			if(idx) yrRenderOverlay_draw(OVERLAY_BACKGROUND, bg_images[idx-1].tex, lox, loy, hix, hiy, 0xFFFFFFFFul);
			//selection border
			if(uistate.uisection == 1 && idx == uistate.backgrounds.selected)
			{
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, loy + 0.01f, hix - 0.01f, loy + 0.02f, 0xFF0000FFul);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, hiy - 0.02f, hix - 0.01f, hiy - 0.01f, 0xFF0000FFul);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox + 0.01f, loy + 0.01f, lox + 0.02f, hiy - 0.01f, 0xFF0000FFul);
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, hix - 0.02f, loy + 0.01f, hix - 0.01f, hiy - 0.01f, 0xFF0000FFul);
			}
		}
	}
	//scroll buttons
	{
		float lox = 0.0f;
		float hix = WND_WIDTH * UV_PER_METER;
		float loxarrow = (WND_WIDTH - 0.02f)/2 * UV_PER_METER;
		float hixarrow = (WND_WIDTH + 0.02f)/2 * UV_PER_METER;
		if(uistate.backgrounds.row > 0.0f) {
			float hiy = (WND_HEIGHT - WND_H_TOP) * UV_PER_METER;
			float loy = hiy - 0.02f * UV_PER_METER;
			float hiyarrow = (WND_HEIGHT - WND_H_TOP - 0.005f) * UV_PER_METER;
			float loyarrow = hiyarrow - 0.01f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFF);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_arrow, loxarrow, loyarrow, hixarrow, hiyarrow, 0xFF000000);
		}
		float rowmax = (float)((bg_count + 1 + 4)/5) - 3.0f;
		if(uistate.backgrounds.row < rowmax) {
			float hiy = WND_H_BOT * UV_PER_METER;
			float loy = hiy + 0.02f * UV_PER_METER;
			float hiyarrow = (WND_H_BOT + 0.005f) * UV_PER_METER;
			float loyarrow = hiyarrow + 0.01f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFF);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_arrow, loxarrow, loyarrow, hixarrow, hiyarrow, 0xFF000000);
		}
	}
}

static void uidraw_tabpos(void)
{
	//items
	float vsize = (WND_H_MID - 2 * 0.02f) * UV_PER_METER;
	float dy = -vsize / 4;
	float basey = (WND_HEIGHT - WND_H_TOP - 0.02f) * UV_PER_METER - uistate.positioning.row * dy;
	for(size_t r = 0; r < 10; ++r)
	{
		int selected = (uistate.uisection == 1 && r == uistate.positioning.selected);
		yrColor bg = selected ? 0xFFFFFFFFul : 0x00000000ul;
		yrColor fg = selected ? 0xFF000000ul : 0xFFFFFFFFul;
		float lox = 0.01f * UV_PER_METER;
		float hix = (WND_WIDTH - 0.01f) * UV_PER_METER;
		float hiy = basey + r * dy;
		float loy = hiy + dy;
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, bg);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_label[r], lox, loy, lox - 4*dy, hiy, fg);

		//xywh
		if(r < 4) {
			lox = -1.5f*dy;
			hix = (WND_WIDTH - 0.01f) * UV_PER_METER;
			hiy -= 0.005f * UV_PER_METER;
			loy += 0.005f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFF);
			lox += 0.001f * UV_PER_METER;
			hix -= 0.001f * UV_PER_METER;
			hiy -= 0.001f * UV_PER_METER;
			loy += 0.001f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFF000000);

			float val = 0.0f;
			switch(r) {
				case 0:
					val = uistate.positioning.xbound[1]-uistate.positioning.off_x;
					val /= (uistate.positioning.xbound[1]-uistate.positioning.xbound[0]);
					break;
				case 1:
					val = uistate.positioning.ybound[1]-uistate.positioning.off_y;
					val /= (uistate.positioning.ybound[1]-uistate.positioning.ybound[0]);
					break;
				case 2:
					val = logf(uistate.positioning.scale_x)/logf(128.0f) + 1.0f;
					val /= 2.0f;
					break;
				case 3:
					val = logf(uistate.positioning.scale_y)/logf(128.0f) + 1.0f;
					val /= 2.0f;
					break;
			}
			lox += 0.001f * UV_PER_METER;
			hix -= 0.001f * UV_PER_METER;
			hiy -= 0.001f * UV_PER_METER;
			loy += 0.001f * UV_PER_METER;
			float w = (hix - lox);
			float start = lox;
			float end = lox + val*w;			
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, start, loy, end, hiy, 0xFFFFFFFF);
		}
		//checkboxes
		else {
			int checked = 0;
			switch(r) {
				case 4: checked = uistate.positioning.flipx; break;
				case 5: checked = uistate.positioning.flipy; break;
				case 6: checked = uistate.positioning.fit; break;
				case 7: checked = uistate.positioning.repeat; break;
				case 8: checked = uistate.positioning.ar11; break;
				case 9: checked = uistate.positioning.pin; break;
			}
			lox = 0.0135f * UV_PER_METER;
			hix = lox - dy - 0.007f * UV_PER_METER;
			hiy -= 0.0035f * UV_PER_METER;
			loy += 0.0035f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFF000000ul);
			if(checked) {
				lox += 0.002f * UV_PER_METER;
				hix -= 0.002f * UV_PER_METER;
				hiy -= 0.002f * UV_PER_METER;
				loy += 0.002f * UV_PER_METER;
				yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFFul);
			}
		}
	}
	//scroll buttons
	{
		float lox = 0.0f;
		float hix = WND_WIDTH * UV_PER_METER;
		float loxarrow = (WND_WIDTH - 0.02f)/2 * UV_PER_METER;
		float hixarrow = (WND_WIDTH + 0.02f)/2 * UV_PER_METER;
		if(uistate.positioning.row > 0.0f) {
			float hiy = (WND_HEIGHT - WND_H_TOP) * UV_PER_METER;
			float loy = hiy - 0.02f * UV_PER_METER;
			float hiyarrow = (WND_HEIGHT - WND_H_TOP - 0.005f) * UV_PER_METER;
			float loyarrow = hiyarrow - 0.01f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFF);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_arrow, loxarrow, loyarrow, hixarrow, hiyarrow, 0xFF000000);
		}
		if(uistate.positioning.row < 6.0f) {
			float hiy = WND_H_BOT * UV_PER_METER;
			float loy = hiy + 0.02f * UV_PER_METER;
			float hiyarrow = (WND_H_BOT + 0.005f) * UV_PER_METER;
			float loyarrow = hiyarrow + 0.01f * UV_PER_METER;
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox, loy, hix, hiy, 0xFFFFFFFF);
			yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_arrow, loxarrow, loyarrow, hixarrow, hiyarrow, 0xFF000000);
		}
	}
}

static void uidraw_tabbar(void)
{
	float loy = (WND_HEIGHT - WND_H_TOP) * UV_PER_METER;
	float hiy = WND_HEIGHT * UV_PER_METER;
	float lox = 0.01f * UV_PER_METER;
	float dx = (WND_WIDTH - 2 * 0.01f)/3 * UV_PER_METER;
	float icow = (WND_H_TOP - 2 * 0.005f) * UV_PER_METER;
	float icox = (dx - icow) / 2;
	//tabs
	yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, 0.0f, loy, WND_WIDTH * UV_PER_METER, hiy + 0.01f, 0xFF000000ul);
	for(int i = 0; i < 3; ++i) {
		yrColor fgc = (i == uistate.tab) ? 0xFF000000ul : 0xFFFFFFFFul;
		//background
		float basex = lox + i*dx;
		if(i == uistate.tab) yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, basex, loy, basex + dx, hiy, 0xFFFFFFFFul);
		//icon
		basex += icox;
		float icoloy = loy + 0.004f * UV_PER_METER;
		float icohiy = icoloy + icow;
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_tab[i], basex, icoloy, basex + icow, icohiy, fgc);
	}
	//active border
	if(uistate.uisection == 0) {
		float basex = lox + uistate.tab*dx;
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, basex + 0.01f, loy + 0.01f, basex + dx - 0.02f, loy + 0.02f, 0xFF000000ul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, basex + 0.01f, hiy - 0.02f, basex + dx - 0.02f, hiy - 0.01f, 0xFF000000ul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, basex + 0.01f, loy + 0.01f, basex + 0.02f, hiy - 0.01f, 0xFF000000ul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, basex + dx - 0.02f, loy + 0.01f, basex + dx - 0.01f, hiy - 0.01f, 0xFF000000ul);
	}
}
static void uidraw_buttons(void)
{
	//background
	float loy = 0.005f * UV_PER_METER;
	float hiy = (WND_H_BOT - 0.005f) * UV_PER_METER;
	float hix = (WND_WIDTH - 0.01f) * UV_PER_METER;
	float lox = hix - (hiy-loy) * 7.5f;
	yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, 0.0f, 0.0f, WND_WIDTH * UV_PER_METER, WND_H_BOT * UV_PER_METER, 0xFF000000ul);
	//button
	yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_target, lox, loy, hix, hiy, (tracked_id == 0xFFFFFFFFul) ? 0xFF808080 : 0xFFFFFFFFul);
	//active border
	if(uistate.uisection == 2) {
		float top = 0.03f * UV_PER_METER;
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - 0.03f, 0.01f, hix + 0.03f, 0.02f, 0xFFFFFFFFul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - 0.03f, top - 0.02f, hix + 0.03f, top - 0.01f, 0xFFFFFFFFul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, lox - 0.03f, 0.01f, lox - 0.02f, top - 0.01f, 0xFFFFFFFFul);
		yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, hix + 0.02f, 0.01f, hix + 0.03f, top - 0.01f, 0xFFFFFFFFul);
	}
}

static void uibutton(enum uibut b)
{
	switch(uistate.uisection) {
		case 0: uistate.uisection = uibutton_top(b); break;
		case 1: uistate.uisection = uibutton_mid(b); break;
		case 2: uistate.uisection = uibutton_bot(b); break;
	}
}

static void uipoke_top(float x, float y)
{
	float dx = (WND_WIDTH - 2 * 0.01f) / 3;
	int uisel = (int) floorf((x - 0.01f)/dx);
	if(uisel < 0) return;
	if(uisel > 2) return;
	uistate.tab = uisel;
	uistate.uisection = 0;
}

static void uipoke_mid(float x, float y)
{
	switch(uistate.tab) {
		//colors tab
		case 0: {
			float hsize = (WND_WIDTH - 2 * 0.01f);
			float vsize = (WND_H_MID - 2 * 0.02f);
			float dx = hsize / 5;
			float dy = -vsize / 3;
			float basex = 0.01f;
			float basey = (WND_HEIGHT - WND_H_TOP - 0.02f) + dy/3;
			
			int col = (int)((x - basex)/dx);
			int row = (int)((y - basey)/(dy + dy/2));
			if(row < 0 || row > 1) break;
			if(row == 0 && (col < 1 || col > 3)) break;
			if(row == 1 && (col < 0 || col > 4)) break;

			if(x > (basex + dx * col + dx - 0.01f)) break;
			if(y < (basey + (dy + dy/2) * row + dy + 0.01f)) break;
			int idx = (row == 0) ? (col - 1) : (col + 3);
			uiaction_setcolor(idx);
			uistate.uisection = 1;
			uistate.colors.selected = idx;
			break;
		}
		//image tab
		case 1: {
			float vsize = (WND_H_MID - 2 * 0.02f);
			float hsize = (WND_WIDTH - 2 * 0.01f);
			float dx = hsize / 5;
			float dy = -vsize / 3;
			float basex = 0.01f;
			float basey = (WND_HEIGHT - WND_H_TOP - 0.02f);
			//scroll up
			if(y > basey) {
				uistate.backgrounds.row -= 0.04f;
				if(uistate.backgrounds.row < 0.0f) uistate.backgrounds.row = 0.0f;
				break;
			}
			//scroll down
			if(y < (WND_H_BOT + 0.02f)) {
				uistate.backgrounds.row += 0.04f;
				float rowmax = (float)((bg_count + 1 + 4)/5) - 3.0f;
				if(rowmax < 0.0f) rowmax = 0.0f;
				if(uistate.backgrounds.row > rowmax) uistate.backgrounds.row = rowmax;
				break;
			}
			//set image
			int col = (int)((x - basex)/dx);
			int row = (int)((y - basey)/dy + uistate.backgrounds.row);
			if(col < 0 || col > 4 ||
			   row < 0 || (row*5+col > bg_count))
			{
				break;
			}
			if(x > (basex + dx * (col + 1) - 0.01f)) break;
			if(y < (basex + dy * (row + 1) + 0.01f)) break;
			int idx = row * 5 + col;
			uiaction_setimage(idx);
			uistate.uisection = 1;
			uistate.backgrounds.selected = idx;
			break;
		}
		//positioning tab
		case 2: {
			float basey = WND_HEIGHT - WND_H_TOP - 0.02f;
			float vsize = WND_H_MID - 2 * 0.02f;
			float dy = -vsize / 4;
			//scroll up
			if(y > basey) {
				uistate.positioning.row -= 0.04f;
				if(uistate.positioning.row < 0.0f) uistate.positioning.row = 0.0f;
				break;
			}
			//scroll down
			if(y < (WND_H_BOT + 0.02f)) {
				uistate.positioning.row += 0.04f;
				if(uistate.positioning.row > 6.0f) uistate.positioning.row = 6.0f;
				break;
			}
			int row = (int)((y - basey)/dy + uistate.positioning.row);
			if(row < 0 || row > 9) break;
			uistate.uisection = 1;
			if(uistate.pokereset) {
				uistate.positioning.selected = row;
			} else {
				row = uistate.positioning.selected;
			}
			//xywh
			if(row < 4) {
				uistate.pokereset = 0;
				if(selected) {
					float lox = -1.5f*dy + 0.002f;
					float hix = WND_WIDTH - 0.012f;
					float w = (hix - lox);
					float val = (x - lox) / w;
					val = clamp(0.0f, 1.0f, val);
					switch(row) {
						case 0: {
							val *= (uistate.positioning.xbound[1]-uistate.positioning.xbound[0]);
							uistate.positioning.off_x = uistate.positioning.xbound[1] - val;
							float diff = selected->uv_back[1][0] - selected->uv_back[0][0];
							selected->uv_back[0][0] = uistate.positioning.off_x;
							selected->uv_back[1][0] = selected->uv_back[0][0] + diff;
							uistate_update(selected);
							break;
						}
						case 1: {
							val *= (uistate.positioning.ybound[1]-uistate.positioning.ybound[0]);
							uistate.positioning.off_y = uistate.positioning.ybound[1] - val;
							float diff = selected->uv_back[1][1] - selected->uv_back[0][1];
							selected->uv_back[0][1] = uistate.positioning.off_y;
							selected->uv_back[1][1] = selected->uv_back[0][1] + diff;
							uistate_update(selected);
							break;
						}
						case 2: {
							val *= 2.0f;
							float newscale = powf(128.0f, (val - 1.0f));
							float factor = newscale / uistate.positioning.scale_x;
							uistate.positioning.scale_x = newscale;
							float w = 1.0f / uistate.positioning.scale_x;
							selected->uv_back[0][0] /= factor;
							selected->uv_back[1][0] = selected->uv_back[0][0] + copysignf(w, selected->uv_back[1][0] - selected->uv_back[0][0]);
							if(selected->flags & QUAD_BG_AR11) {
								float h = ar11_height(selected, w);
								selected->uv_back[0][1] /= factor;
								selected->uv_back[1][1] = selected->uv_back[0][1] + h;
							}
							uistate_update(selected);
							break;
						}
						case 3: {
							val *= 2.0f;
							float newscale = powf(128.0f, (val - 1.0f));
							float factor = newscale / uistate.positioning.scale_y;
							uistate.positioning.scale_y = newscale;
							float h = 1.0f / uistate.positioning.scale_y;
							selected->uv_back[0][1] /= factor;
							selected->uv_back[1][1] = selected->uv_back[0][1] + copysignf(h, selected->uv_back[1][1] - selected->uv_back[0][1]);
							if(selected->flags & QUAD_BG_AR11) {
								float w = ar11_width(selected, h);
								selected->uv_back[0][0] /= factor;
								selected->uv_back[1][0] = selected->uv_back[0][0] + w;
							}
							uistate_update(selected);
							break;
						}
					}
				}
			}
			//checkboxes
			else {
				if(uistate.pokereset) {
					uistate.pokereset = 0;
					switch(row) {
						case 4: uiaction_toggle_flipx(); break;
						case 5: uiaction_toggle_flipy(); break;
						case 6: uiaction_toggle_fit(); break;
						case 7: uiaction_toggle_repeat(); break;
						case 8: uiaction_toggle_ar11(); break;
						case 9: uiaction_toggle_pin(); break;
					}
				}
			}			
			break;
		}
	}
}

static void uipoke_bot(float x, float y)
{
	float loy = 0.005f;
	float hiy = (WND_H_BOT - 0.005f);
	float hix = (WND_WIDTH - 0.01f);
	float lox = hix - (hiy-loy) * 7.5f;
	if(x > lox && y > loy &&
	   x < hix && y < hiy &&
	   uistate.pokereset &&
	   (tracked_id != 0xFFFFFFFF))
	{
		uistate.pokereset = 0;
		uistate.uisection = 2;
		selecting = !selecting;
	}
}

static void uiunpoke(void) {
	uistate.pokereset = 1;
}

static int uipoke(vec4f pos, vec4f dir, float len)
{
	//position to point on plane
	pos = vec4f_sub(pos, saved_mat.col[3]);
	vec4f zero = {0.0f,0.0f,0.0f,1.0f};
	mat4f inv = saved_mat;
	inv.col[3] = zero;
	inv = mat4f_invert(inv);
	pos = mat4f_apply(inv, pos);
	dir = mat4f_apply(inv, dir);
	float dist = -pos.z / dir.z;
	if(dist < -len) {return 0;}
	if(dist > 0.0f) {return 0;}
	pos = vec4f_add(pos, vec4f_mul(dist, dir));

	if(pos.x < 0.0f)		{return 0;}
	if(pos.y < 0.0f)		{return 0;}
	if(pos.x > WND_WIDTH)	{return 0;}
	if(pos.y > WND_HEIGHT)	{return 0;}
	if(pos.y > (WND_HEIGHT-WND_H_TOP))	uipoke_top(pos.x, pos.y);
	else if(pos.y > WND_H_BOT)			uipoke_mid(pos.x, pos.y);
	else								uipoke_bot(pos.x, pos.y);
	return 1;
}

static void background_tick(void)
{
	VRControllerState_t cbuttons = {0};
	ovrSystem_GetControllerState(tracked_id, &cbuttons);
	mat4f mat = yrVR_world_from_tracked(tracked_id);
	vec4i off = yrVR_get_coord_offset();

	//virtual screen mat
	mat4f screenmat = {{
		{1.0f,0.0f,0.0f,0.0f},
		{0.0f,0.7071067811865476f,-0.7071067811865476f, 0.0f},
		{0.0f,0.7071067811865476f,0.7071067811865476f, 0.0f},
		{-WND_WIDTH/2,0.01f,-0.01f,1.0f},
	}};
	screenmat = mat4f_combine(mat, screenmat);
	if(!poslocked) saved_mat = screenmat;

	//selection beam
	tracehit h;
	if(selecting) {
		vec4i o = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat.col[3])));
		h = yrInteraction_trace(o, vec4f_neg(mat.col[2]), DIST_MIN, DIST_MAX);
		vec4f n = h.q ? h.q->normal : mat.col[2];
		yrRender_beam(toolidx, mat.col[3], vec4f_neg(mat.col[2]), n, h.dist, 0xFF808040);
	}
	else if(selected) {
		vec4i o = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, saved_mat.col[3])));
		vec4i beamdest = vec4i_add(selected->v[1], selected->v[2]);
		beamdest.m = _mm_srai_epi32(beamdest.m, 1); //divide by 2
		vec4f dir = vec4f_from_vec4i(vec4i_sub(beamdest, o));
		float dist = vec3f_length(dir);
		dir = vec4f_mul(1.0f/dist, dir);
		yrRender_beam(toolidx, saved_mat.col[3], dir, selected->normal, dist / YR_ACCURACY, 0xFF2020C0);
	}

	//interaction
	float touchx = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Touchpad - EVRButtonId_k_EButton_Axis0].x;
	float touchy = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Touchpad - EVRButtonId_k_EButton_Axis0].y;
	int touchd = 0!=(cbuttons.ulButtonPressed & (1ull << EVRButtonId_k_EButton_SteamVR_Touchpad));
	float trig = cbuttons.rAxis[EVRButtonId_k_EButton_SteamVR_Trigger - EVRButtonId_k_EButton_Axis0].x;
	
	//draw buttons
	yrRenderTrackedOverlay_clear(toolidx);
	if(selecting) {
		if(touchd || touchx != 0.0f || touchy != 0.0f) {
			yrRenderTrackedOverlay_draw(toolidx, tpadbut_target_glow, -1.0f, -1.0f, 1.0f, 1.0f, touchd ? 0xFFFF8010 : 0x80FF8010);
		}
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_target, -1.0f, -1.0f, 1.0f, 1.0f, 0xFFFFFFFF);
	} else {
		if(touchd || touchx != 0.0f || touchy != 0.0f) {
			int glowidx;
			if((touchx*touchx + touchy*touchy) < 0.25f)	glowidx = 0;
			else if(fabsf(touchx) > fabsf(touchy))		glowidx = (touchx > 0.0f) ? 1:3;
			else										glowidx = (touchy > 0.0f) ? 2:4;
			yrRenderTrackedOverlay_draw(toolidx, tpadbut_arrows_glow[glowidx], -1.0f, -1.0f, 1.0f, 1.0f, touchd ? 0xFFFF8010 : 0x80FF8010);
		}
		yrRenderTrackedOverlay_draw(toolidx, tpadbut_arrows, -1.0f, -1.0f, 1.0f, 1.0f, 0xFFFFFFFF);
	}
	yrRenderTrackedOverlay_render(toolidx);

	//touchpad "buttons"
	if(!touchdown && touchd) {
		if(selecting) {
			if(selected) {
				yrUndo_append(utQuad, &selected_restore, selected, NULL, NULL);
				yrQuadStore_editlock(NULL);
				selected = NULL;
			}
			selected = h.q;
			if(selected) {
				yrQuadStore_editlock(h.q); //select quad
				yrTileStore_important(h.q->ext->tile_max_idx, (TileID*) h.q->ext->tiles);
				uistate_update(selected);
				selected_restore = *selected;
			}
			selecting = 0;
		}
		else {
			if((touchx*touchx + touchy*touchy) < 0.25f) {
				uibutton(ubCenter);
			}
			else if(fabsf(touchx) > fabsf(touchy)) {
				uibutton((touchx > 0.0f) ? ubRight : ubLeft);
			} else {
				uibutton((touchy > 0.0f) ? ubUp : ubDown);
			}
		}
	}
	else if(touchdown && !touchd) {
		uibutton(ubRelease);
	}
	else uibutton(ubNone);
	touchdown = touchd;

	//poke with pen
	if(!trigdown && trig > 0.3f) poslocked = !poslocked;
	trigdown = (trig > 0.3f);

	if(poslocked) {
		mat4f tipmat = {{{0.0f,0.0f,0.0f,0.0f},PICK_NOTDIR,PICK_DIR,PICK_OFF}};
		tipmat.col[0] = vec3f_cross(tipmat.col[1],tipmat.col[2]);
		vec4i zero = {0,0,0,0};
		yrModel_render(mdl_tip, tex_fill, tipmat, zero, yrInteraction_getpencolor(), tracked_id);
	}
}

static int background_canfreeze(void)
{
	return selected == NULL && !selecting;
}

static void	background_forceidle(void)
{
	selecting = 0;
	if(selected) {
		yrUndo_append(utQuad, &selected_restore, selected, NULL, NULL);
		yrQuadStore_editlock(NULL);
		selected = NULL;
	}
}

static int background_getpokepos(vec4f* pos, vec4f* dir, float* len)
{
	if(poslocked) {
		mat4f mat = yrVR_world_from_tracked(tracked_id);
		mat4f tipmat = {{{0.0f,0.0f,0.0f,0.0f},PICK_NOTDIR,PICK_DIR,PICK_OFF}};
		tipmat.col[0] = vec3f_cross(tipmat.col[1],tipmat.col[2]);
		vec4i zero = {0,0,0,0};

		tipmat = mat4f_combine(mat, tipmat);
		*len = PICK_LEN;
		*pos = tipmat.col[3];
		*dir = tipmat.col[2];

		return 1;
	}
	else {
		return 0;
	}
}

static void background_renderwindow(void)
{
	if(!poslocked && tracked_id == 0xFFFFFFFFul) return;
	vec4i off = yrVR_get_coord_offset();
	//draw ui
	yrRenderOverlay_clear(OVERLAY_BACKGROUND);
	yrRenderOverlay_draw(OVERLAY_BACKGROUND, tex_fill, 0.0f, 0.0f, WND_WIDTH * UV_PER_METER, WND_HEIGHT * UV_PER_METER, 0x80000000ul);
	switch(uistate.tab) {
		case 0: uidraw_tabclr(); break;
		case 1: uidraw_tabimg(); break;
		case 2: uidraw_tabpos(); break;
	}
	uidraw_tabbar();
	uidraw_buttons();
	
	//ui overlay
	yrQuad foo;
	foo.uv_draw[0] = 0.0f;
	foo.uv_draw[1] = 0.0f;
	foo.width = WND_WIDTH;
	foo.height = WND_HEIGHT;
	vec4f bar[3] = {{0.0f,0.0f,0.0f,1.0f},{WND_WIDTH,0.0f,0.0f,1.0f},{0.0f,WND_HEIGHT,0.0f,1.0f}};
	foo.v[0] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat4f_apply(saved_mat, bar[0]))));
	foo.v[1] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat4f_apply(saved_mat, bar[1]))));
	foo.v[2] = vec4i_add(off, vec4i_from_vec4f(vec4f_mul(YR_ACCURACY, mat4f_apply(saved_mat, bar[2]))));
	yrRenderOverlay_render(OVERLAY_BACKGROUND, &foo, 0);
}

static void background_poke(void)
{
	if(!poslocked && tracked_id == 0xFFFFFFFFul) return;

	vec4f pickpos;
	vec4f pickdir;
	float picklen;
	size_t i = 0;
	
	while(1) {
		i = yrInteraction_getpokepos(&pickpos,&pickdir,&picklen, i);
		if(picklen > 0.0f) {
			if(uipoke(pickpos, pickdir, picklen)) break;
		}
		else break;
	}
	if(picklen <= 0.0f) uiunpoke();
}