/*
Class.create = function ()
{
    return function ()
    {
	this.extend = function (object){ return Object.extend(this, object); };
	this.initialize.apply(this, arguments);
    };
};
*/


if(typeof D3L == 'undefined')
	D3L = {};

function D3LCameraCreate(camera)
{
	if(typeof camera == 'string')
		camera = $(camera);
	Object.extend(camera, new D3L.Camera() );
	
	return camera;
};

D3L.Camera = Class.create();
Object.extend(D3L.Camera.prototype, {
	initialize: function()
	{
		this.x = 0;
		this.y = 0;
		this.w = 0;
		this.h = 0;
		this.z = 100;
		this.Scenes = new Array();
		
		this.vx = 0;
		this.vy = 0;
		this.vw = 0;
		this.vh = 0;
		
		this.oldy = null;
	},
	
	add: function(scene)
	{
		if(typeof scene == 'string')
			scene = $(scene);
		if(!scene)
			return;
		
		
		Object.extend(scene, new D3L.Scene() );
		
		scene.setCamera(this);
		
		this.Scenes.push(scene);
		
		return scene;
	},
	
	draw: function()
	{
		var pos = Position.cumulativeOffset(this);
		var posp = Position.positionedOffset(this);
		this.x = pos[0];
		this.y = posp[1];
		this.w = this.getWidth();
		this.h = this.getHeight();
		
		for(var si=0;si<this.Scenes.length;si++)
			this.Scenes[si].draw();
		
	},
	setViewPosition: function($x, $y, $w, $h)
	{
		this.vx = $x;
		this.vy = $y;
		this.vw = $w;
		this.vh = $h;
	}
	
});

D3L.Scene = Class.create();
Object.extend(D3L.Scene.prototype, {
	initialize: function()
	{
		this.z = 0;
		this.zdepth = 10000;
		this.cameradepth = 1000;
		this.Xrad = 0;
		this.Yrad = 0;
		this.Zrad = 0;
		this.Camera = null;
		this.Panels = new Array();
		
		this.first_Flag = true;
	},
	
	add: function(panel)
	{
		panel = $(panel);
		if(!panel)
			return;
		panel = Object.extend(panel, new D3L.Panel());
		
		panel.setScene(this);
		
		if(panel.getAttribute("d3l_ztop"))
			panel.setZTop(panel.getAttribute("d3l_ztop"));
		
		if(panel.getAttribute("d3l_zbottom"))
			panel.setZBottom(panel.getAttribute("d3l_zbottom"));
		
		if(panel.getAttribute("d3l_zselect"))
			panel.setZSelect(panel.getAttribute("d3l_zselect"));
		
		if(panel.getAttribute("d3l_zindexdiff"))
			panel.setZIndexDiff(panel.getAttribute("d3l_zindexdiff"));
		
		var pos = Position.cumulativeOffset(panel);
		var posp = Position.positionedOffset(panel);
		panel.setParentXY(pos[0]- posp[0], pos[1]- posp[1]);

		panel.setX(posp[0]);
		panel.setY(posp[1]);
		panel.setW(panel.getWidth());
		panel.setH(panel.getHeight());
		
		this.Panels.push(panel);
		panel.draw();
		
		return panel;
	},
	
	setCamera: function(camera)
	{
		this.Camera = camera;
	},
	
	setXrad: function(xrad)
	{
		this.Xrad = xrad;
	},
	setYrad: function(yrad)
	{
		this.Yrad = yrad;
	},
	setZrad: function(zrad)
	{
		this.Zrad = zrad;
	},
	
	calcXY: function(x,y,z)
	{
		var s = this.cameradepth;	//視点から投影平面までの距離.
		var d = this.cameradepth;	//視点から原点までの距離.
		var Xrad = this.Xrad, Yrad = this.Yrad, Zrad = this.Zrad;	//回転角度.
		
		x = x - this.Camera.w/2 - this.Camera.x;
		y = y - this.Camera.h/2 - this.Camera.y;
		var xs = s / (d - (y * Math.sin(Xrad) + (-x * Math.sin(Yrad) + z * Math.cos(Yrad)) * Math.cos(Xrad))) * ((x * Math.cos(Yrad) + z * Math.sin(Yrad)) * Math.cos(Zrad) - (y * Math.cos(Xrad) - z * Math.sin(Xrad)) * Math.sin(Zrad));
		var ys = - s / (d - (y * Math.sin(Xrad) + (-x * Math.sin(Yrad) + z * Math.cos(Yrad)) * Math.cos(Xrad))) * ((x * Math.cos(Yrad) + z * Math.sin(Yrad)) * Math.sin(Zrad) - (y * Math.cos(Xrad) - z * Math.sin(Xrad)) * Math.cos(Zrad));

//		var xs = s / (d - z) * (x);
//		var ys = - s / (d - z) * ( - y);


		return new Array(parseInt(xs+this.Camera.w/2+this.Camera.x+0.5), parseInt(ys+this.Camera.h/2+this.Camera.y+0.5));
	},
	
	draw: function()
	{
		var cnt = 0;
		var pl = this.Panels.length;
		for(var pi=0;pi<pl;pi++)
		{
//			if(!this.first_Flag && pi > pl/5)
//				return;
			if(this.Panels[pi]._y + this.Panels[pi].py <= (this.Camera.vy + this.Camera.vh) + 200 && this.Camera.vy - 200 <= (this.Panels[pi]._y + this.Panels[pi]._h + this.Panels[pi].py) || this.Panels[pi]._z_top > 0 || this.Panels[pi]._z_bottom > 0)
			{
				this.Panels[pi].draw();
				cnt++;
			}
		}
		this.first_Flag = false;
		
		print_d("splite " + cnt);
	}
});


D3L.Panel = Class.create();
Object.extend(D3L.Panel.prototype, {
	initialize: function()
	{
		this.Scene = null;
		this._x = 0;
		this._y = 0;
		this.px = 0;	//親の座標.
		this.py = 0;	//親の座標.
		this._z_top = 0;
		this._z_bottom = null;
		this._w = 0;
		this._h = 0;
		this._select = null;
		this._z_indexdiff = 0;
	},
	
	setScene: function($scene)
	{
		this.Scene = $scene;
	},
	
	setZSelect: function($z_select)
	{
		this._select = $z_select;
	},
	
	setZIndexDiff: function($z_indexdiff)
	{
		this._z_indexdiff = parseFloat($z_indexdiff);
	},
	
	getAutoZoom: function()
	{
		return (this._z_bottom != null);
	},
	
	setParentXY: function($x, $y)
	{
		this.px = parseInt($x);
		this.py = parseInt($y);
		
	},
	setW: function($w)
	{
		this._w = parseInt($w);
	},
	
	getW: function()
	{
		return this._w;
	},
	
	setH: function($h)
	{
		this._h = parseInt($h);
	},
	
	getH: function()
	{
		return this._h;
	},
	
	setX: function($x)
	{
		this._x = parseInt($x);
	},
	
	getX: function()
	{
		return this._x;
	},
	
	setY: function($y)
	{
		this._y = parseInt($y);
	},
	
	getY: function()
	{
		return this._y;
	},
	
	getZTop: function()
	{
		return this._z_top;
	},
	
	getZBottom: function()
	{
		if(this._z_bottom == null)
			return this._z_top;
		else
			return this._z_bottom;
	},
	
	getZMiddle: function()
	{
		if(this._z_bottom == null)
			return parseFloat(this._z_top)+parseFloat(this._z_indexdiff);
		else
		{
			return parseFloat(this._z_top)+(parseFloat(this._z_bottom)-parseFloat(this._z_top))/2+parseFloat(this._z_indexdiff);
		}
	},
	
	getZOrder: function()
	{
		if(this._z_bottom == null)
			return this._z_top+this._z_indexdiff;
		else if(this._z_top == null)
		{
			return this._z_bottom+this._z_indexdiff;
		}
		else
		{
			if(this._z_bottom > this._z_top)
				return this._z_top+this._z_indexdiff;
			else
				return this._z_bottom+this._z_indexdiff;
		}
	},
	
	setZTop: function($z)
	{
		this._z_top = parseFloat($z);
	},
	
	setZBottom: function($z)
	{
		this._z_bottom = parseFloat($z);
	},
	
	draw: function()
	{
		var scene = this.Scene;
		
//		xy_top = scene.calcXY(this._x+this.px, this._y+this.py, this._z_top);
		xy_top[0] = ((scene.cameradepth / (scene.cameradepth - (this._z_top)) * ((this._x+this.px) - scene.Camera.w/2 - scene.Camera.x)) + scene.Camera.w/2+scene.Camera.x);
		xy_top[1] = ((- scene.cameradepth / (scene.cameradepth - (this._z_top)) * ( - ((this._y+this.py) - scene.Camera.h/2 - scene.Camera.y))) + scene.Camera.h/2+scene.Camera.y);
		
		l_zb = this.getZBottom();
		l_az = this.getAutoZoom();
		if(this._select == "bottom")
		{
			if(l_az)
			{
//					xy_temp = scene.calcXY(this._x+this.px, this._y+this.py, this.getZBottom());

				xy_temp[0] = ((scene.cameradepth / (scene.cameradepth - (l_zb)) * ((this._x+this.px) - scene.Camera.w/2 - scene.Camera.x)) + scene.Camera.w/2+scene.Camera.x);
//				xy_temp[1] = ((- scene.cameradepth / (scene.cameradepth - (this.getZBottom())) * ( - ((this._y+this.py) - scene.Camera.h/2 - scene.Camera.y))) + scene.Camera.h/2+scene.Camera.y);

				xy_top[0] = xy_temp[0];
			}
			else
			{
//					xy_temp = scene.calcXY(this._x+this.px, this._y+this.py+this._h, this.getZBottom());

				xy_temp[1] = ((- scene.cameradepth / (scene.cameradepth - (l_zb)) * ( - ((this._y+this.py+this._h) - scene.Camera.h/2 - scene.Camera.y))) + scene.Camera.h/2+scene.Camera.y);

				xy_top[1] = xy_temp[1] -this._h;
			}
			
		}
		
		l_visibility = null;
		l_left = (xy_top[0]-this.px);
		l_top = (xy_top[1]-this.py);
		if(l_az)
		{
//			xy_bottom = scene.calcXY(this._x+this.px+this._w, this._y+this.py+this._h, this.getZBottom());

			xy_bottom[0] = ((scene.cameradepth / (scene.cameradepth - (this.getZBottom())) * ((this._x+this.px+this._w) - scene.Camera.w/2 - scene.Camera.x)) + scene.Camera.w/2+scene.Camera.x);
			xy_bottom[1] = ((- scene.cameradepth / (scene.cameradepth - (this.getZBottom())) * ( - ((this._y+this.py+this._h) - scene.Camera.h/2 - scene.Camera.y))) + scene.Camera.h/2+scene.Camera.y);

			if(this._select == "top")
			{
//				xy_temp =  scene.calcXY(this._x+this.px+this._w, this._y+this.py, this._z_top);

				xy_temp[0] = ((scene.cameradepth / (scene.cameradepth - (this._z_top)) * ((this._x+this.px+this._w) - scene.Camera.w/2 - scene.Camera.x)) + scene.Camera.w/2+scene.Camera.x);
				xy_bottom[0] = xy_temp[0];
			
			}
			
			
			if((xy_bottom[1]-xy_top[1])>=0)
			{
				l_width = (xy_bottom[0]-xy_top[0]);
				l_height = (xy_bottom[1]-xy_top[1]);
				l_visibility = true;
			}
			else
			{
				l_width = 0;
				l_height = 0;
				l_visibility = false;
			}
		}
		else
		{
			l_width = this._w;
			l_height = this._h;
		}

		if(this.id == 'test')
		{
			print_d("x) "+parseInt(l_left+this.px) +" <= "+ parseInt(scene.Camera.vx + scene.Camera.vw) +" && "+ parseInt(scene.Camera.vx) +" <= "+parseInt(l_left+l_width+this.px));
			print_d("y) "+parseInt(l_top+this.py) +" <= "+ parseInt(scene.Camera.vy + scene.Camera.vh) +" && "+ parseInt(scene.Camera.vy) +" <= "+parseInt(l_top+l_height+this.py));
			
		}
		
/*		view_flag = false;
		if(l_left+this.px <= (scene.Camera.vx + scene.Camera.vw) && scene.Camera.vx <= (l_left+l_width+this.px))
		{
			if(l_top+this.py <= (scene.Camera.vy + scene.Camera.vh) && scene.Camera.vy <= (l_top+l_height+this.py))
			{
				view_flag = true;
			}
		}
		
		if(this._z_top > 0)
			view_flag = true;
		if(view_flag)
*/		
		{
			this.style.left = parseInt(l_left+0.5)+"px";
			this.style.top = parseInt(l_top+0.5)+"px";
			this.style.width = parseInt(l_width+0.5)+"px";
			this.style.height = parseInt(l_height+0.5)+"px";
			
			if(initedFlag)
			{
				if(l_visibility == true)
					this.style.visibility = 'visible';
				else if(l_visibility == false)
					this.style.visibility = 'hidden';
			}

			
			this.style.zIndex =  scene.zdepth+parseInt(this.getZOrder());
		}
		
	}
});
//速度アップのため外に逃がす.
var xy_top = {};
var xy_bottom = {};
var xy_temp = {};
var l_left = 0, l_top = 0, l_width = 0, l_height = 0,l_visibility = true;
var l_az = false, l_zb = 0;
var view_flag = false;

D3L.Move = Class.create();
Object.extend(D3L.Move.prototype, {
	initialize: function()
	{
		this.Panel = null;
		this._x = null;
		this._y = null;
		this._z_top = null;
		this._z_bottom = null;
		this._w = null;
		this._h = null;
		
		this.oldtime = getMilli();
		this.oldcount = (getMilli() - starttime) / frameInterval;
		this.da = 10;	//減速係数.
		
	},
	
	setPanel: function(panel)
	{
		if(typeof panel == 'string')
			panel = $(panel);
		if(!panel)
			return;
		
		this.Panel = panel;
		
		this._x = this.Panel._x;
		this._y = this.Panel._y;
		this._z_top = this.Panel._z_top;
		this._z_bottom = this.Panel._z_bottom;
		this._w = this.Panel._w;
		this._h = this.Panel._h;
		
		this.evalstr = null;
		
	},
	
	setW: function($w)
	{
		this._w = parseInt($w);
	},
	
	setH: function($h)
	{
		this._h = parseInt($h);
	},
	
	setX: function($x)
	{
		this._x = parseInt($x);
	},
	
	setY: function($y)
	{
		this._y = parseInt($y);
	},
	
	setZTop: function($z)
	{
		this._z_top = parseFloat($z);
	},
	
	setZBottom: function($z)
	{
		this._z_bottom = parseFloat($z);
	},
	
	setDa: function($da)
	{
		this.da = parseFloat($da);
	},
	
	setEval: function($evalstr)
	{
		this.evalstr = $evalstr;
	},
	
	calcNext: function()
	{
		if(!this.Panel)
			return true;	//終了.

//		var nowMilli = getMilli();
		var nowcount = (getMilli() - starttime) / frameInterval;
		
		for(var ii=0;ii<nowcount-this.oldcount;ii++)
		{
			
			if(
				(this._x == null || parseInt(this.Panel._x) == parseInt(this._x)) && 
				(this._y == null || parseInt(this.Panel._y) == parseInt(this._y)) && 
				(this._z_top == null || parseInt(this.Panel._z_top) == parseInt(this._z_top)) && 
				(this._z_bottom == null || parseInt(this.Panel._z_bottom) == parseInt(this._z_bottom)) && 
				(this._w == null || parseInt(this.Panel._w) == parseInt(this._w)) && 
				(this._h == null || parseInt(this.Panel._h) == parseInt(this._h))
			)
			{
				return true;	//終了.
			}
			
			
			
			if(this._x != null)
			{
				var dn = (this._x - this.Panel._x)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setX(this.Panel._x + dn);
			}
			if(this._y != null)
			{
				var dn = (this._y - this.Panel._y)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setY(this.Panel._y + dn);
			}
			if(this._z_top != null)
			{
				var dn = (this._z_top - this.Panel._z_top)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setZTop(this.Panel._z_top + dn);
			}
			
			if(this._z_bottom != null)
			{
				var dn = (this._z_bottom - this.Panel._z_bottom)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setZBottom(this.Panel._z_bottom + dn);
			}
			
			if(this._w != null)
			{
				var dn = (this._w - this.Panel._w)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setW(this.Panel._w + dn);
			}
			
			if(this._h != null)
			{
				var dn = (this._h - this.Panel._h)/this.da;
				if(0 < dn && dn < 1)
					dn = 1;
				if(-1 < dn && dn < 0)
					dn = -1;
				
				this.Panel.setH(this.Panel._h + dn);
			}
			
		}
		this.oldcount = nowcount;
		
		
		return false;	//続く.
	}
});



