local framecount = 0

local tool = {toollist = {}, tex = "editor/noicon.tga", level = nil, 
	clickspace = dspacehash.new(), colmeshs = {}, camlookat = {0,0,0}, campos = {0,760,1120},
}
tool.active = tool
function tool.new (parent)
	local self = {}
	setmetatable(self,{__index = parent or tool})
	
	tool.cam = tool.cam or 
		followcamera.new (function () return unpack(tool.campos) end ,{},
			function () return unpack(tool.camlookat) end,{},0.1,0,0)
	
	self.btn = gui.button.new(self.tex,40 + table.getn(tool.toollist)*40,480-32,0,32,32,
		function () self:btnclicked() end)
	
	self.actor = actornode.new("tool")
	self.body = dbody.new()
	self.body:autodisable(false)
	self.body:gravity(false)
	self.actor:link(self.body)
	
	self.l3ds = {}
	self.geoms = {}
	self.transforms = {}
	self.geomlut = {}
	self.buttons = {}
	
	table.insert(tool.toollist,self)
	return self
end

function tool.addclickmodel (self,name,x,y,z,rx,ry,rz,clickfn)
	local mdl = type(name)=="string" and model.load(name,false,true,false,true)

	tool.colmeshs[name] = tool.colmeshs[name] or getModelColMesh (mdl).data
	local l3d = l3dmodel.new("clickmodell",lset:layer(topviewoffset+1),mdl,false,false)
	l3d:linkinterface(self.actor)
	l3d:uselocal(true)
	l3d:localpos(x,y,z)
	l3d:localrotdeg(rx,ry,rz)
	l3d:rfLitSun(true)
	l3d:rfNodraw(true)
	l3d:rfNovertexcolor(true)
	
	local geom = dgeomtrimesh.new(tool.colmeshs[name])
	geom:pos(x,y,z)
	geom:rotrad(rx/180*math.pi,ry/180*math.pi,rz/180*math.pi)
	local trans = dgeomtransform.new()
	trans:geom(geom)
	trans:body(self.body)
	
	
	table.insert(self.l3ds,l3d)
	table.insert(self.geoms,geom)
	table.insert(self.transforms,trans)
	self.geomlut[luxinia.dataID(geom)] = clickfn

	return l3d
end

function tool.addl3dbutton (self,mdl,x,y,z,rx,ry,rz,w,h,scale,clickfn)
	local btn = gui.l3dbutton.new(mdl, x,y,z,rx,ry,rz,w,h,scale,clickfn)
	table.insert(self.buttons,btn)
	btn:visible(false)
end

function tool.addbutton (self,tex,fn)
	local btn = gui.button.new (tex, 640-48,(table.getn(self.buttons)+0.5)*48,0,32,32,fn)
	table.insert(self.buttons,btn)
	btn:visible(false)
end

local lastmouse
function tool.think (self)
	if (self == tool) then return end

	local x,y = input.mousepos()
	
	if (tool.active.think~=tool.think) then
		tool.active:think()
	end	
	
	if (input.ismousedown(0)) then lastmouse = true return end
	if (not lastmouse) then return end
	lastmouse = false
	if (gui.click(x,y)) then return 
	else tool.active:click(x,y) end

	--_print("think")	
	local self = tool.active
	--if (not mouse[1] and self.mouse) then
	--self.mouse = false
	local hits = raymousetest(tool.clickspace,2^14)
	if (hits[1]) then
		local d = hits[1].d
		local n = 1
		for i,v in ipairs(hits) do 
			if (v.d<d) then
				n,d = i,v.d
			end
		end
		local fn = self.geomlut[luxinia.dataID(hits[n].geom)]
		if (fn) then
			fn(self)
			self.t = framecount
		end
	end
	--end
	if (input.ismousedown(0)) then self.mouse = true end
end


function tool.activate (self) 
	if (self~=tool.active) then 
		tool.active:deactivate() 
		tool.active = self 
		for i,v in ipairs(self.l3ds) do 
			v:rfNodraw(false)
		end
		
		for i,v in ipairs(self.transforms) do
			tool.clickspace:add(v);
		end
		
		for i,v in ipairs(self.buttons) do
			v:visible(true)
		end
	end
end

function tool.click(self,x,y) end
function tool.btnclicked (self) self:activate() end
function tool.deactivate (self) 
	if (self==tool) then return end
	for i,v in ipairs(self.l3ds) do 
		v:rfNodraw(true)
	end
	for i,v in ipairs(self.transforms) do
		tool.clickspace:remove(v);
	end
	for i,v in ipairs(self.buttons) do
		v:visible(false)
	end
end

function tool.cleanup () 

	for i,v in ipairs(tool.toollist) do
		v:delete()
	end
	for i,v in pairs(tool.colmeshs) do
		v:destroy()
	end
	tool.active = tool
	tool.toollist = {}
	entity.removeall()
	tool.clickspace:destroy()
end

function tool.delete (self) 
	self.actor:delete()
	self.body:destroy()
	for i,v in ipairs(self.l3ds) do 
		v:delete()
	end
	for i,v in ipairs(self.geoms) do
		v:destroy()
	end
	for i,v in ipairs(self.transforms) do
		v:destroy()
	end
	for i,v in ipairs(self.buttons) do
		v:delete()
	end
end


local mapper = {tex = "editor/tileplace.tga"}
setmetatable(mapper,{__index = tool})
function mapper.new ()
	local self = tool.new(mapper)
	
	self.x,self.y,self.z = 0,0,0
	self.target = {0,0,0}
	
	local function nn () self:move(0,1,0) end
	local function ss () self:move(0,-1,0) end
	local function ee () self:move(1,0,0) end
	local function ww () self:move(-1,0,0) end
	local function browse() self:toggle(2) end
	local function toggle() self:toggle(1) end
	local function delete() self:toggle(0) end
	local function up () self:move(0,0,1) end
	local function down () self:move(0,0,-1) end

--	self:addclickmodel("editor/sphere.f3d",0, 0, 450,0,0, 0 ,toggle):color(0,1,0,1)
--	self:addclickmodel("editor/sphere.f3d",0, 0, 400,0,0, 0 ,delete):color(1,0,0,1)	
--	self:addclickmodel("editor/sphere.f3d",0, 0, 500,0,0, 0 ,browse):color(1,1,0,1)	
	self:addbutton("editor/kategorie.tga",browse)
	self:addbutton("editor/toggletile.tga",toggle)
	self:addbutton("editor/up.tga",up)
	self:addbutton("editor/down.tga",down)
	self:addbutton("editor/delete.tga",delete)
	
	local plane,border = 
		self:addclickmodel("editor/selectionplane.f3d",0, 0, 0,0,0, 0 ,toggle),
		self:addclickmodel("editor/selectionborder.f3d",0, 0, 0,0,0, 0 ,toggle)
	plane:color(0,1,0,0.3)	
	border:color(0,1,0,0.6)
	plane:rfBlend(true)
	border:rfBlend(true)
	plane:rsBlendmode(blendmode.amodadd())
	border:rsBlendmode(blendmode.amodadd())
	
	local l3ds = {
		self:addclickmodel("editor/selectionplane.f3d", 300,0, 0,0,0, 0 ,ee),
		self:addclickmodel("editor/selectionplane.f3d",-300,0, 0,0,0, 0 ,ww),
		self:addclickmodel("editor/selectionplane.f3d",0, 300, 0,0,0, 0 ,nn),
		self:addclickmodel("editor/selectionplane.f3d",0,-300, 0,0,0, 0 ,ss)
	}
		
	for i,v in pairs(l3ds) do 
		--v:rfNodepthtest(true)
		--v:rfNodepthmask(true)
		v:rfBlend(true)
		v:rsBlendmode(blendmode.amodadd())
		v:color(0.1,0.7,0.1,0.3)
	end

	return self
end

function mapper.toggle (self,dir)
	local level = tool.level
	local fits = level:getfits(self.x,self.y)
	local categories = {}
	local list = {}
	
	for a,b in (fits) do table.insert(list,a) end
	
	node = level:get(self.x,self.y)
	if (dir == 0) then
		level:clear(self.x,self.y)
		return
	end
	if (math.abs(dir) == 1) then
		list = {}
		for i,v in pairs(fits) do 
			--_print(i)
			if (categories[v.categoryname]) then
			else
				categories[v.categoryname] = true
				table.insert(list,v.id)
			end
		end
	end
	if (math.abs(dir) == 2 and node) then
		local name = levelnodes.nodeids[node.id].categoryname
		list = {}
		for i,v in pairs(fits) do 
			if (name ~= v.categoryname) then
				fits[i] = nil
			else
				table.insert(list,v.id)
			end
		end	
	end
	if (node) then
		dir = dir>0 and 1 or -1
		local index = 1
		for a,b in pairs(list) do if(b==node.id) then index = a break end end
		
		local id = list[index+dir] and index+dir or (dir>0 and 1 or table.getn(list))
		id = list[id]
		level:set(id,self.x,self.y,self.z)
	else
		level:set(list[1],self.x,self.y,self.z)
	end
end

function mapper.move (self,x,y,z)
	self.x,self.y,self.z = self.x + x, self.y + y, self.z + z
	if (z==0) then
		local node = tool.level:getz(self.x,self.y)
		if (node) then self.z = node end
	end
	x,y,z = config.quadsize*self.x,config.quadsize*self.y,config.heightstep*self.z
	self.target = {x,y,z}
end

function mapper.think (self)
	tool.camlookat = {self.actor:pos()}
	local x,y,z = self.actor:pos()
	tool.campos = {x,y+760,z+1200}

	local s1,s2 = 0.96,0.04
	self.actor:pos(x*s1+self.target[1]*s2,y*s1+self.target[2]*s2,
		z*s1+self.target[3]*s2)
	

	
end

local builder = {tex = "editor/builder.tga"}
setmetatable(builder,{__index = tool})

function builder.new ()
	local self = tool.new(builder)
	
	local i = 0
	local s = 60
	local cnt = 0
	for k,v in pairs(mapobjects) do cnt = cnt + 1 end
	
	for k,v in pairs(mapobjects) do
		i = i+1
		--v = v[1]
		local name = v.name
		local c,s = math.cos(i*math.pi/cnt*2),math.sin(i*math.pi/cnt*2)
		self:addclickmodel("mapobjects/"..v.name, c*200,s*200, 0,0,0, 0 ,function () _print(name) end)
	--	self:addl3dbutton(v.mdl,30+i*100,200,0,140,40,0,30,30, 1,function () end)
	end
	return self
end

function builder.think (self)
	tool.camlookat = {self.actor:pos()}
	local x,y,z = self.actor:pos()
	tool.campos = {x,y+360,z+420}

--	_print("builder think")
end

function leveleditor()
	topview.rClear:depth(true)
	snow.stop()
	viewdist(16,2^14)
	MouseCursor:enable(true)
	
	tool.level = levelmap.new()
	
	mapper.new()
	builder.new()
	
	local function stepthink() 
		entity.thinkall()
		tool.think()
		dworld.quickstep(1)
	end
	
	local ltime = luxinia.time()
	function leveledit ()
		local cnt = 0
		framecount = framecount + 1
		while (ltime<luxinia.time()+4 and cnt<5) do
			cnt = cnt + 1
			ltime = ltime + 5
			stepthink()
		end
	end
	
	Timer.set("leveledit",leveledit)
end

function leveleditorfinish ()
	tool.level:cleanup()
	tool:cleanup()
	gui.cleanup ()
	topview.rClear:depth(false)
	Timer.remove("leveledit")
	disableThink = {}
end

function leveleditorreload ()
	leveleditorfinish()
	dofile("leveleditor.lua")
	leveleditor()
end


--------------------------------------------------------------------------
	

function leveleditor()
--	gui.button.new ("editor/waypoint.tga", 10,400,0,32,32, function() _print("click") end)
	
	console.active(true)
	print("Welcome to the hacky mapeditor for XMAS")
	print("---------------------------------------")
	print("Keys:")
	print(" PageUP:           next tile")
	print(" PageDOWN:         previous tile")
	print(" Delete:           erase")
	print(" g/t:              raise/lower cursor")
	print(" n/p:              next/previouse model")
	print(" m/b:              rotate left right")
	--print(" l/0:              load/save (enter text then and press enter) - not working currently")
	print(" +/-:              change camera distance")
	print(" mousewheel:       rotate model")
	print(" ctrl+mousewheel:  next/previous model")
	print(" left mouse btn:   place/select model")
	print(" right mouse btn:  rotate view")
	print(" arrow keys:       move cursor")
	print(" f1:               show/hide console (THIS HERE)")
	print("Note:")
	print(" This is a developer tool. The xmas game turned out to be more a "..
	      "demo than a real game so we provide you this tool, too.")

	snow.stop()
	viewdist(16,2^14)
	
	MouseCursor:enable(true)
	camnode = actornode.new("")
	cam = l3dcamera.default()
	cam:linkinterface(camnode)
	--cam:backplane(2048)
	camnode:pos(0,0,1000)
	camnode:rotrad(-math.pi*0.5,0,0)
	
	cursor = {
		actor = actornode.new(""),
		node = 1,
		x = 0, y = 0,z = 0,
		mouse = actornode.new(""),
		nextclick = 0,
		place = mapobjects.tanne,
		placerot = 0,
		elev=math.pi*0.35,az=0,dist = 800,curelev=math.pi*0.35,curaz=0,curdist = 800,
		l3d = l3dmodel.new("",lset:layer(1),mapobjects.tanne.mdl,false,false),
		lookat = {0,0,0,0,0}
	}
	
	gamehud.setcurposfn(function () 
		local x,y = cursor.actor:pos()
		return x,y,cursor.az end)
	do 
		l3dquad = l3dprimitive.newbox("",lset:layer(2),300,300,100)
		l3dquad:linkinterface(cursor.actor)
		l3dquad:color(0,0.3,0,1)
		l3dquad:rfLitSun(true)
		l3dquad:rfWireframe(true)
		l3dquad:rsLinewidth(3)
		l3dquad:rsLinestipple("1010101010101010")
		l3dquad:rsLinefactor(10)
		cursor.l3d:linkinterface(cursor.mouse)
		--l3dquad:rfBlend(true)
		--l3dquad:rsBlendmode(blendmode.add())
	
	
		local self = {}
		tex = texture.load("mapplace.tga")
		self.projector = l3dprojector.new("sledshadow",layer)
		self.projector:linkinterface(cursor.mouse)
		self.projector:uselocal(true)
		self.projector:textureid(tex)
		--self.projector:activate(1)
		self.projector:fov(-100)
		self.projector:blend(blendmode:decal())
		self.projector:frontplane(-20)
		--self.projector:rotationlock(0,true)
		--self.projector:rotationlock(1,true)
		self.projector:backplane(200)
		--self.projector:attenuate(true)
		self.projector:localrotdeg(-90,0,0)
	end
	
	level = levelmap.new()
	level:set(1,0,0,0)
	
	--Keyboard.setKeyBinding (string.byte('p'),function () pause = not pause end)
	function movecursor(x,y,z) 
		if (noinput) then return end
		cursor.x,cursor.y,cursor.z = cursor.x+x,cursor.y+y,cursor.z+ (z or 0)
		cursor.actor:pos(cursor.x*config.quadsize,cursor.y*config.quadsize,cursor.z*config.heightstep)
	end
	
	function relmovecursor(x,y,z) 
		if (noinput) then return end
		local angle = cursor.lookat[5]+math.pi*1.75
		angle = math.floor(angle/math.pi*2)/2*math.pi
		angle = angle - math.pi*2
--		if (angle>math.pi*0.25) then angle = angle + math.pi*0.25 
--		elseif (angle>math.pi*0.75) then angle = angle+math.pi*0.75
--		elseif (angle<math.pi*0.25
		local s,c = math.sin(-angle),math.cos(-angle)
		local y,x = (c*x+s*y),-(-s*x+y*c)
		x,y = math.round(x),math.round(y)
		
		cursor.x,cursor.y,cursor.z = cursor.x+x,cursor.y+y,cursor.z+ (z or 0)
		cursor.actor:pos(cursor.x*config.quadsize,cursor.y*config.quadsize,cursor.z*config.heightstep)
	end
	
	function browse(dir)
		if (noinput) then return end
		local fits = level:getfits(cursor.x,cursor.y)
		local list = {}
		for a,b in pairs(fits) do table.insert(list,a) end
		
		node = level:get(cursor.x,cursor.y)
		if (dir == 0) then
			level:clear(cursor.x,cursor.y)
			return
		end
		if (node) then
			local index = 1
			for a,b in pairs(list) do if(b==node.id) then index = a break end end
			
			--local id = levelnodes.nodeids[node.id + dir] and node.id + dir or (dir>0 and 1 or table.getn(levelnodes.nodeids))
			local id = list[index+dir] and index+dir or (dir>0 and 1 or table.getn(list))
			id = list[id]
			level:set(id,cursor.x,cursor.y,cursor.z)
		else
			level:set(list[1],cursor.x,cursor.y,cursor.z)
		end
	end
	

	
	local function mapobjectset(id)
		if (noinput) then return end
		cursor.place = mapobjects[id]
		cursor.l3d:delete()
		cursor.l3d = l3dmodel.new("",lset:layer(1),cursor.place.mdl,false,false)
		cursor.l3d:linkinterface(cursor.mouse)
		cursor.l3d:rfBlend(true)
		cursor.l3d:rsBlendmode(blendmode.decal())
		cursor.l3d:rfNovertexcolor(true)
		cursor.l3d:color(1,1,1,0.5)		
	end
	
	local function mapobject(dir)
		if (noinput) then return end
		if (dir == 0) then return end
		dir = (dir==1) and "next" or "prev"
		mapobjectset(cursor.place[dir].short)
	end
	
	function click(btn,object)
		if (noinput) then return end

		if (not object) then return end
		local type = getmetatable(object).__index
		if (type == mapnode or (Keyboard.isKeyDown(Keyboard.keycode.RCTRL) or Keyboard.isKeyDown(Keyboard.keycode.LCTRL))) then
			--cursor.l3d:rfNodraw(false)
			if (btn==1) then
				local x,y,z = cursor.mouse:pos()
				level:add(cursor.place,x,y,0,0,0,cursor.placerot)
			elseif(btn==2) then
			end
		else
			cursor.placerot = object.rz
			mapobjectset(object.mdl.short)
			object:delete()
			--cursor.l3d:rfNodraw(true)
		end		
	end
	
	local function mapobjectrot(ang)
		cursor.placerot = cursor.placerot + ang
		cursor.mouse:rotrad(0,0,cursor.placerot)
	end
	local function height (step)
		cursor.z = cursor.z + step
		cursor.actor:pos(cursor.x*config.quadsize,cursor.y*config.quadsize,cursor.z*config.heightstep)
	end
	
	local inputarea = gui.textfield.new("",32,20,20);
	function inputarea.onEnter (self)	
		_print ("enter... "..self:text())
		if (inputarea.save) then
			level:save(self:text()..".lvl.lua")
		else
			level:cleanup() level = levelmap.load(self:text()..".lvl.lua") 
		end
		inputarea.save = false
		inputarea:text("  ")
		inputarea.enabled = false
		noinput = false
	end
	
	inputarea.enabled = false
	
	Keyboard.setKeyBinding (Keyboard.keycode.LEFT,function() relmovecursor(-1,0) end)
	Keyboard.setKeyBinding (Keyboard.keycode.RIGHT,function() relmovecursor(1,0) end)
	Keyboard.setKeyBinding (Keyboard.keycode.UP,function() relmovecursor(0,1) end)
	Keyboard.setKeyBinding (Keyboard.keycode.DOWN,function() relmovecursor(0,-1) end)
	Keyboard.setKeyBinding (Keyboard.keycode.PAGEUP,function() browse(1) end)
	Keyboard.setKeyBinding (Keyboard.keycode.PAGEDOWN,function() browse(-1) end)
	Keyboard.setKeyBinding (Keyboard.keycode.DEL,function ()browse(0) end)
	Keyboard.setKeyBinding (string.byte('n'),function () mapobject(1) end)
	Keyboard.setKeyBinding (string.byte('p'),function () mapobject(-1) end)
	Keyboard.setKeyBinding (string.byte('+'),function () if (noinput) then return end cursor.dist = cursor.dist + 50 end)
	Keyboard.setKeyBinding (string.byte('-'),function () if (noinput) then return end cursor.dist = cursor.dist - 50 end)
	Keyboard.setKeyBinding (string.byte('m'),function () mapobjectrot(math.pi*0.05) end,50)
	Keyboard.setKeyBinding (string.byte('b'),function () mapobjectrot(-math.pi*0.05) end,50)
	Keyboard.setKeyBinding (string.byte('0'),function () 
		if (noinput) then return end 
		noinput = true
		inputarea.enabled = true
		inputarea:text("test")
		inputarea.save = true
	end,250)
	Keyboard.setKeyBinding (string.byte('l'),function () 
		if (noinput) then return end
		noinput = true
		inputarea.enabled = true
		inputarea:text("test")
		--level:cleanup() level = levelmap.load("test.lvl.lua") 
	end,250)
	Keyboard.setKeyBinding (string.byte('1'),function () level:cleanup() 
		if (noinput) then return end
		level = levelmap.new() movecursor(-cursor.x,-cursor.y) end,250)
	Keyboard.setKeyBinding (string.byte('t'),function () if (noinput) then return end height(1) end,200)
	Keyboard.setKeyBinding (string.byte('g'),function () if (noinput) then return end height(-1) end,200)
	
	local mwheel = input.mousewheel()
	local mdrag
	
	function stepthink()
		if (MouseCursor.wasButtonPressed(0) and gui.click(input.mousepos())) then return end
		
		local mwheelpos = input.mousewheel()
		local mwheelchange = mwheelpos - mwheel
		mwheel = mwheelpos
		if (Keyboard.isKeyDown(Keyboard.keycode.RCTRL) or Keyboard.isKeyDown(Keyboard.keycode.LCTRL)) then
			mapobject(mwheelchange)
		else 
			mapobjectrot(math.pi*0.05*mwheelchange)
		end
		
		local azc,azs = math.cos(cursor.curaz)*cursor.curdist,	math.sin(cursor.curaz)*cursor.curdist
		local elc,els = math.cos(cursor.curelev),	math.sin(cursor.curelev)
		
		local cx,cy,cz = camnode:pos()
		local tx,ty,tz = azs*elc,azc*elc,-els*cursor.curdist
		local px,py,pz = cursor.actor:pos()
		local dx,dy,dz = px-cx-tx,py-cy-ty,pz-tz-cz
		local va,vai = 0.03, 0.97
		cx,cy,cz = cx + dx*va,cy + dy*va, cz + dz*va
		cursor.curelev = cursor.curelev*0.3 + cursor.elev*0.7
		cursor.curdist = cursor.curdist*0.3 + cursor.dist*0.7
		cursor.curaz = cursor.curaz*0.3 + cursor.az*0.7
		cursor.lookat[1],cursor.lookat[2],cursor.lookat[3] = 
			cursor.lookat[1]*vai+px*va, cursor.lookat[2]*vai+py*va, cursor.lookat[3]*vai+pz*va
		camnode:pos(cx,cy,cz)
		local dx,dy,dz = cx-cursor.lookat[1],cy-cursor.lookat[2],cz-cursor.lookat[3]
		local dist = (dx*dx+dy*dy+dz*dz)^0.5
		cursor.lookat[4],cursor.lookat[5] = -math.asin(dz/dist),-math.atan2(dx,dy)+math.pi
		camnode:rotrad(cursor.lookat[4],0,cursor.lookat[5])
		local count = 0
		local x,y,z = cam:worldpos()
		local mx,my = input.mousepos()
		local dx,dy,dz = cam:toworld(mx,my,1)
		
		dx,dy,dz = dx-x,dy-y,dz-z
		local r = math.round
		
		local cnt,pos,norm,depth,geoms = level:test(x,y,z,dx,dy,dz,2048)
		local function sqdist (x,y,z)
			local cx,cy,cz = cam:worldpos()
			x,y,z = x-cx,y-cy,z-cz
			return x*x+y*y+z*z
		end
		local dist
		local geom = geoms[1]~=raytester and geoms[1] or geoms[2]
		local selected

		for i=1,cnt do
			local j,type = (i-1)*2+1
			geom = geoms[j]~=raytester and geoms[j] or geoms[j+1]
			if (geom) then
				geom = level.geomlut[luxinia.dataID(geom)][1]
				type = geom and getmetatable(geom).__index or nil
			end

			if (type == mapnode or not (Keyboard.isKeyDown(Keyboard.keycode.RCTRL) or Keyboard.isKeyDown(Keyboard.keycode.LCTRL))) then
				local x,y,z = pos[(i-1)*3+1],pos[(i-1)*3+2],pos[(i-1)*3+3]
				local d = sqdist(x,y,z)
				if (not dist or d<=dist) then				
					cursor.mouse:pos(x,y,z)
					dist = d
					selected = geom
				end
			end
		end

		if (selected) then
			local type = getmetatable(selected).__index
			if (type == mapnode or (Keyboard.isKeyDown(Keyboard.keycode.RCTRL) or Keyboard.isKeyDown(Keyboard.keycode.LCTRL))) then
				cursor.l3d:rfNodraw(false)
			else
				cursor.l3d:rfNodraw(true)
			end		
		end
		
		if (input.ismousedown(0) and cnt>0) then
			down = true
		end
		if (not input.ismousedown(0) and down) then
			click(1,selected)
			down = false
		end
		
		if (input.ismousedown(2) or input.ismousedown(1)) then
			mdrag = mdrag or {input.mousepos()}
			local mx,my = input.mousepos()
			cursor.az = cursor.az + (mdrag[1]-mx)*0.01
			cursor.elev = math.min(math.pi*0.5,math.max(0.1,cursor.elev + (mdrag[2]-my)*0.01))
			--_print(mouse.x-mdrag[1],mouse.y-mdrag[2],unpack(mdrag))
			input.mousepos(mdrag[1],mdrag[2])
			--mdrag = {mouse.x,mouse.y}
		elseif(mdrag) then
			input.mousepos(unpack(mdrag))
			mdrag = nil
		end
	end
	local ltime = luxinia.time()
	function leveledit ()
		local cnt = 0
		while (ltime<luxinia.time()+4 and cnt<5) do
			cnt = cnt + 1
			ltime = ltime + 5
			stepthink()
		end
	end
	
	Timer.set("leveledit",leveledit)
end