//
// XVL Player Control Library
//
// (c) 2001 Lattice Technology,Inc.
//
/*
Ver 0.13 2003/??/??

03/05/29 debugobj.hook()
03/09/01 0.10c mozilla support -- Debug Obj (except for hook)
03/09/09 0.11 add chkPlayerVersion
03/09/10 0.11a chkPlayerVersion debug
               debug.info scroll 10000 -> 100000
03/09/12 0.12  add Button.targetnode
03/11/21 0.13  add XVL events
               (OnXvlReady,OnXvlSelectChange,OnXvlWalkCollide,OnXvlExtension)
               add CreatePlayer
*/

var XvlCs = new function ()
{
	this.Math = new function (){
		function _xyz()
		{
				this.x = 0;
				this.y = 0;
				this.z = 0;
				this.setValue = function (cx,cy,cz)
					{
						this.x = cx;
						this.y = cy;
						this.z = cz;
					}
		}
		
		function _xyzr()
		{
				this.x = 0;
				this.y = 1;
				this.z = 0;
				this.r = 0;
				this.setValue = function (cx,cy,cz,cr)
					{
						this.x = cx;
						this.y = cy;
						this.z = cz;
						this.r = cr;
					}
		}
		
		this.vec_rotate = function (vec,ori)
		{
			var ans = new _xyz();
			var n,nx,ny,nz;
			
			n = Math.sqrt(ori.x * ori.x + ori.y * ori.y + ori.z * ori.z);
			if(n){
				nx = ori.x / n;
				ny = ori.y / n;
				nz = ori.z / n;
			}else{
				return vec;
			}
			var par1 = vec.x * ori.x + vec.y * ori.y + vec.z * ori.z;
			var cosr = Math.cos(ori.r);
			var sinr = Math.sin(ori.r);
			var par2x = vec.x - par1 * nx;
			var par2y = vec.y - par1 * ny;
			var par2z = vec.z - par1 * nz;
			var par3x = ny * vec.z - nz * vec.y;
			var par3y = nz * vec.x - nx * vec.z;
			var par3z = nx * vec.y - ny * vec.x;
			
			ans.x = par1 * nx + cosr * par2x + sinr * par3x;
			ans.y = par1 * ny + cosr * par2y + sinr * par3y;
			ans.z = par1 * nz + cosr * par2z + sinr * par3z;
			
			return ans;
		}

		this.vec2ori = function (vec)
		{
			var ans = new _xyzr();
			var rx,ry,rz,rr;
			
			ans.x = vec.y;
			ans.y = -1 * vec.x;
			ans.z = 0;
			if(ans.x == 0 && ans.y == 0 && ans.z == 0){
				ans.y = 1;
			}
			var n = Math.sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
			ans.r = Math.acos((-1 * vec.z)/n);
			
			return ans;
		}
		
		function QuaternionAdd(r1,r2)//r2 * r1のこと
		{
			var ans = new _xyzr();
			
			ans.r = r2.r*r1.r - (r1.x*r2.x+r1.y*r2.y+r1.z*r2.z);
			ans.x = r2.r*r1.x + r1.r*r2.x - r2.y*r1.z + r2.z*r1.y;
			ans.y = r2.r*r1.y + r1.r*r2.y - r2.z*r1.x + r2.x*r1.z;
			ans.z = r2.r*r1.z + r1.r*r2.z - r2.x*r1.y + r2.y*r1.x;
			
			return ans;
		}

		function rot2qt(rot) //quaternion
		{
			var ans = new _xyzr();
			var z;
			
			//規格化
			var nx,ny,nz;
			var l;
			nx = rot.x;
			ny = rot.y;
			nz = rot.z;
			l = nx * nx + ny * ny + nz *nz;
			l = Math.sqrt(l);
			nx /= l; ny /=l; nz /= l;
			
			z = Math.sin(rot.r/2);
			if(z != 0.0)
			{
				ans.x = nx * z;
				ans.y = ny * z;
				ans.z = nz * z;	
				ans.r = Math.cos(rot.r/2);
			}else{
				//rot.r / 2 == 0, Pi /2, Pi
				ans.x = 0.0;
				ans.y = 0.0;
				ans.z = 0.0;
				ans.r = 1.0;
			}
			return ans;
		}


		function qt2rot(qt)
		{
			var ans = new _xyzr();
			var z;
			var A;
			var ac_1, ac_2;
			ac_1 = Math.acos(qt.r);

			ac_2 = 2.0 * Math.PI - ac_1;


			//
			var as_1, as_2;
			var nx, ny, nz;
			var l;
			nx = qt.x; ny = qt.y; nz = qt.z;
			l = nx *nx + ny * ny + nz * nz;
			
			if(l == 0)
			{
				//この場合theta/2 = Pi
				ans.r = 0.0;
				ans.x = 0;
				ans.y = 0;
				ans.z = 1;
//				alert("l = 0");	
			}else{	
				l = Math.sqrt(l);
				nx /= l; ny /= l; nz /= l;
				var df1,df2;
				df1 = (Math.sin(ac_1) - l) * (Math.sin(ac_1) - l);
				df2 = (Math.sin(ac_2) - l) * (Math.sin(ac_2) - l);		
				if(df1 < df2)
				{
					A = 2.0 * ac_1;
				}else{
					A = 2.0 * ac_2;
				}
				ans.r = A;
				ans.x = nx; ans.y = ny; ans.z = nz;
			//	alert("l!=0");
			}

			return ans;
		}

		this.rotateAdd = function (r1,r2)
		{
			var qt1 = rot2qt(r1);
			var qt2 = rot2qt(r2);
			
			var aqt = QuaternionAdd(qt2,qt1);
			
			return qt2rot(aqt);
			
		}
	}
	
	
	this.nstring = function (n,m)  // 桁揃え
	{
		var s,p;
		var i;
		
		s = "" + n;
		p = s.length;
		for(i=0;i<m - p;i++){
			s = "0" + s;
		}
		return s;
	}
	
	
	// CreateDebugObj ///////////////////////////////////////////////////////////
	
	
	this.CreateDebugObj = function (infowin){
		return new debugObj_Constructer(infowin)
	}
	
	function debugObj_Constructer(infowin)
	{
		var _newWin = null;
		var _newWin_info = null;
		this.status = true;
		this.top = true;
		this.fontSize = "11pt";
		
		function _checkWindowOpen()
		{
			
			if(_newWin && !_newWin.closed){
				return;
			}
			
			_newWin = window.open("",infowin,
				"width=200,height=300,resizable=yes,scrollbars=yes"
			);
			if(! _newWin.document.getElementById("info")){
				_newWin.document.open();
				_newWin.document.write("<html><head></head><body>");
				_newWin.document.write("<div id='info'></div>");
				_newWin.document.write("</body></html>");
				_newWin.document.close();
			}
			_newWin_info = _newWin.document.getElementById("info");
			
		}
		
		function get_innertxt(str)
		{
			//<、>、&、" はそれぞれ &lt;、&gt;、&amp;、&quot; 
			var str0 = ""+ str;
			var str1 = str0.replace(/\&/gi, "&amp;");
			var str2 = str1.replace(/\</gi, "&lt;");
			var str3 = str2.replace(/\>/gi, "&gt;");
			var str4 = str3.replace(/\"/gi, "&quot;");
			var str5 = str4.replace(/\n/gi, "<br>");
			
			return str5;
		}
		
		this.info = function (str,color)
		{
			if(!this.status)
				return;
			
			var newNode;
			
			_checkWindowOpen();
			if(this.top)
				_newWin.focus();
			
			newNode = _newWin.document.createElement("div");
			newNode.style.fontSize = this.fontSize;
			if(color)
				newNode.style.color = color;
			newNode.innerHTML = get_innertxt(str);
			_newWin_info.appendChild(newNode);
			
			_newWin.scrollBy(0,100000);
		}
		
		this.infoMember = function (obj,color)
		{
			if(!this.status)
				return;
			
			var i;
			var data;
			var newTable0,tdNode0;
			var newTable,tbodyNode,trNode,tdNode;
			var tbodyNode0,trNode0;
			
			_checkWindowOpen();
			if(this.top)
				_newWin.focus();
			
			newTable0 = _newWin.document.createElement("table");
			newTable0.border = 0;
			newTable0.cellPadding = 0;
			newTable0.cellSpacing = 0;
			if(color)
				newTable0.bgColor = color;
			else
				newTable0.bgColor = "#000000";
			
			tbodyNode0 = _newWin.document.createElement("tbody");
			newTable0.appendChild(tbodyNode0);
			trNode0 = _newWin.document.createElement("tr");
			tbodyNode0.appendChild(trNode0);
			tdNode0 = _newWin.document.createElement("td");
			trNode0.appendChild(tdNode0);
			
			newTable = _newWin.document.createElement("table");
			newTable.border = 0;
//			newTable.borderColor = "#000000";
			newTable.cellPadding = 2;
			newTable.cellSpacing = 1;
			if(color)
				newTable.style.color = color;
			newTable.style.fontSize = this.fontSize;
			newTable.style.border = "1px";
			tdNode0.appendChild(newTable);
			
			tbodyNode = _newWin.document.createElement("tbody");
			newTable.appendChild(tbodyNode);
			for(i in obj){
				trNode = _newWin.document.createElement("tr");
				trNode.bgColor = "#ffffff";
				
				tdNode = _newWin.document.createElement("td");
				tdNode.vAlign = "top";
				tdNode.innerHTML = i;
				trNode.appendChild(tdNode);
				
				tdNode = _newWin.document.createElement("td");
				switch(typeof(obj[i]))
				{
					case "number":
					case "string":
					case "boolean":
						data = obj[i];
						break;
					default:
						data = "["+ typeof(obj[i]) +"]";
						break;
				}
				tdNode.innerHTML = get_innertxt(data);
				trNode.appendChild(tdNode);
				
				tbodyNode.appendChild(trNode);
			}
			_newWin_info.appendChild(newTable0);
			_newWin.scrollBy(0,100000);
		}
		
		this.vecStr = function (vec)
		{
			return "("+ vec.x +" "+ vec.y +" "+ vec.z+")";
		}
		
		this.oriStr = function (ori)
		{
			return "("+ ori.x +" "+ ori.y +" "+ ori.z +" "+ ori.r+")";
		}
		
		this.clear = function ()
		{
			if(!this.status)
				return;
			_checkWindowOpen();
			
			_newWin_info.innerHTML = "";
		}
		
		this.hook = function (_boolean, target)
		{
			if(!this.status)
				return;
			if(!_boolean)
				return;
			
			if(!target)
				target = window;
			window.showModalDialog(
				"xvlcs_dialog1.html", target,
				"width=400px;height=400px;scrollbars=yes;resizable=yes"
			);
		}
		
	}
	
	
	// CreateEventObj ///////////////////////////////////////////////////////////
	
	this.CreateEventObj = function (xvlplayer)
	{ return new eventObj_Constructer(xvlplayer) }
	
	function eventObj_Constructer(xvlplayer)
	{
		function _data(handleStr)
		{
			this.name = handleStr.match(/OnXvl(.+)\(/i)[1];
			this.handleStr = handleStr;
			this.status = false;
			this.scriptNode = null;
		}
		
		var i=0;
		var handler = new Array();
		handler[i]=new _data("OnXvlLoad()");i++;
		handler[i]=new _data("OnXvlReady()");i++;
		handler[i]=new _data("OnXvlKeyDown(key)");i++;
		handler[i]=new _data("OnXvlKeyUp(key)");i++;
		handler[i]=new _data("OnXvlMouseDown(x,y)");i++;
		handler[i]=new _data("OnXvlMouseMove(x,y)");i++;
		handler[i]=new _data("OnXvlMouseUp(x,y)");i++;
		handler[i]=new _data("OnXvlMouseDrag(x,y)");i++;
		handler[i]=new _data("OnXvlGroupPick(object,name)");i++;
		handler[i]=new _data("OnXvlShellPick(object,name)");i++;
		handler[i]=new _data("OnXvlFacePick(object,name)");i++;
		handler[i]=new _data("OnXvlEdgePick(object,name)");i++;
		handler[i]=new _data("OnXvlVertexPick(object,name)");i++;
		handler[i]=new _data("OnXvlLink(url,object)");i++;
		handler[i]=new _data("OnXvlAnimComplete(anim,object)");i++;
		handler[i]=new _data("OnXvlAnimAbort(anim,object)");i++;
		handler[i]=new _data("OnXvlGroupOver(object)");i++;
		handler[i]=new _data("OnXvlGroupOut()");i++;
		handler[i]=new _data("OnXvlShellOver(object)");i++;
		handler[i]=new _data("OnXvlShellOut()");i++;
		handler[i]=new _data("OnXvlFaceOver(object)");i++;
		handler[i]=new _data("OnXvlFaceOut()");i++;
		handler[i]=new _data("OnXvlEdgeOver(object)");i++;
		handler[i]=new _data("OnXvlEdgeOut()");i++;
		handler[i]=new _data("OnXvlVertexOver(object)");i++;
		handler[i]=new _data("OnXvlVertexOut()");i++;
		handler[i]=new _data("OnXvlMenuChange()");i++;
		handler[i]=new _data("OnXvlFileError(eno)");i++;
		handler[i]=new _data("OnXvlSelectChange(type,num)");i++;
		handler[i]=new _data("OnXvlWalkCollide()");i++;
		handler[i]=new _data("OnXvlExtension(name,param)");i++;
		
		for(i=0;i<handler.length;i++){
			eval(
				"this."+ handler[i].name +" = "
				+"function (funcstr){ _setXvlEvent(handler["+ i +"],funcstr) }"
			);
		}
		
		function _setXvlEvent(handleObj, funcstr)
		{
			if(!handleObj.status){
				var scrNode;
				scrNode = xvlplayer.document.createElement("script");
				scrNode.type = "text/javascript";
				scrNode.htmlFor = xvlplayer.id;
				scrNode.event = handleObj.handleStr;
				scrNode.text = funcstr;
				xvlplayer.document.body.appendChild(scrNode);
				handleObj.scriptNode = scrNode;
			}
			handleObj.scriptNode.text = funcstr;
			handleObj.status = true;
		}
		
	}
	
	
	// CreateButtonObj //////////////////////////////////////////////////////////
	
	this.CreateButtonObj = function (obj,type)
	{
		return new _buttonObj(obj,type);
	}

	function _buttonObj(hobj,btntype)
	{
		this.status = null;
		this.mode = new Array();
		this.targetnode = hobj;
		var nowmode = null;
		var chgfunc;
		switch(btntype){
			case "style":
				chgfunc = function (val){ hobj.className = val };
				break;
			case "image":
			default:
				chgfunc = function (val){ hobj.src = val };
				break;
		}
		
		this.addMode = function (index)
		{
			if(0 < arguments.length)
				this.mode[index] = new _buttonMode();
			else
				this.mode[this.mode.length] = new _buttonMode();
		}
		
		this.setMode = function (index)
		{
			if(!this.mode[index])
				return;
			nowmode = this.mode[index];
			this.status = index;
			
			hobj._callBtn = this;
			chgfunc(nowmode.normal);
			hobj.onclick =     function (){this._callBtn.eventFook("onclick")};
			hobj.onmouseover = function (){this._callBtn.eventFook("onmouseover")};
			hobj.onmouseout =  function (){this._callBtn.eventFook("onmouseout")};
			hobj.onmousedown = function (){this._callBtn.eventFook("onmousedown")};
			hobj.onmouseup =   function (){this._callBtn.eventFook("onmouseup")};
			if(nowmode.event.onclick)
				hobj.style.cursor = "hand";
			else
				hobj.style.cursor = "";
		}
		
		this.eventFook = function (eventstr)
		{
			switch(eventstr)
			{
				case "onclick":
					eval(nowmode.event.onclick);
					break;
				case "onmouseover":
					if(nowmode.over)
						chgfunc(nowmode.over);
					eval(nowmode.event.onmouseover);
					break;
				case "onmouseout":
					chgfunc(nowmode.normal);
					eval(nowmode.event.onmouseout);
					break;
				case "onmousedown":
					if(nowmode.down)
						chgfunc(nowmode.down);
					eval(nowmode.event.onmousedown);
					break;
				case "onmouseup":
					if(nowmode.over)
						chgfunc(nowmode.over);
					else
						chgfunc(nowmode.normal);
					eval(nowmode.event.onmouseup);
					break;
				default:
					break;
			}
		}
		
		function _event()
		{
			this.onclick = null;
			this.onmouseover = null;
			this.onmouseout = null;
			this.onmousedown = null;
			this.onmouseup = null;
		}
		
		function _buttonMode()
		{
			this.normal = null;
			this.over = null;
			this.down = null;
			this.event = new _event();
		}
		
	}
	
	// XvlCs members //////////////////////////////////////////////////////////
	
	this.info2 = function (obj)
	{
		var i;
		var str = "";
		
		for(i in obj){
			str += i +" : "+ obj[i] +"\n";
		}
		alert(str);
	}
	
	this.chkPlayerVersion = function (player,verstr)
	{
		var apps1,apps2;
		var i;
		
		apps1 = player.appVersion.split(".");
		apps2 = verstr.split(".");
		
		for(i=0;i<4;i++){
			if(! isNaN(apps1[i] -0))
				apps1[i] -= 0;
			else
				apps1[i] = 0;
			if(! isNaN(apps2[i] -0))
				apps2[i] -= 0;
			else
				apps2[i] = 0;
		}
		
		for(i=0;i<4;i++){
			if(apps1[i] > apps2[i])
				return true;
			else if(apps1[i] == apps2[i])
				continue;
			else
				return false;
		}
		return true;
	}
	
	this.CreatePlayer = function (player)
	{
		var i,opNode,values,opvalue;
		
		values = "";
		for(i=1;i<arguments.length;i++){
			if((opvalue = arguments[i].split("=")).length >= 2){
				opNode = player.document.createElement("param");
				opNode.setAttribute("name",opvalue[0]);
				opNode.setAttribute("value",opvalue[1]);
				player.appendChild(opNode);
			}else{
				values += arguments[i] +",";
			}
		}
		opNode = player.document.createElement("param");
		opNode.setAttribute("name","options");
		opNode.setAttribute("value",values);
		player.appendChild(opNode);
		
//		player.classid = "clsid:C0975880-11DF-11D5-8084-0040B4116A31";
		player.type = "application/x-xvlplayer";
	}
}



