見出し画像

ティラノスクリプトの3D その9:バグ修正タグ

初めに

今回は、バグが有って使えなかった既存のタグの修正版です。タグは以降の3つです。
[3d_gyro] シーンで、カメラを多少動かして辺りを眺めることが出来るタグです。ただ、現状では、マウスを動かすと妙な挙動で意図した方向に向いたり動いたりできません。
[3d_debug] 本来のタグは、現時点は three.jsTransformControls を使ってマニュピュレータで操作を楽にするものなのですが、どうも意図した挙動をしません。旧版も挙動が今一です。
[3d_debug_camera] このタグは、一応意図通りには動くのですが、終了させた後でも、終わらずにマウスを動かすとカメラが動いたままになります。
これらは、それなりに使いたいタグなので、色々デバッグした結果一応まともに動くようになったので、公開します。

[3d_gyro]

マウスの動きに応じて実行される部分を解析した結果、どうも軸の指定がおかしいような気がしましたので、修正したところPC対応部分はそれなりに動くようになりました。ただ、スマホ対応部分のソースは未チェックです。また、操作仕様としては、マウスの位置が画面の中央にあるときが初期方向として、マウスの上下左右でそちらの方を向くような計算にしました。
以下にコードを示します。

tyrano.plugin.kag.tag["3d_gyro"] = {
	vital : [],
	pm : {
		max_x:"30",
		max_y:"30",
		mode:"rotation", // rotation or position
		next:"true",
	},
	start : function(pm) {
		//debugger;
		var three = this.kag.tmp.three;
		var camera = three.camera;
		var renderer = three.renderer;
		if(pm.mode=="rotation"){
			three.stat.gyro.mode = 1;
			three.stat.gyro.x = camera.rotation.x;
			three.stat.gyro.y = camera.rotation.y;				
		}else if( pm.mode=="position"){
			three.stat.gyro.mode = 2;
			three.stat.gyro.x = camera.positon.x;
			three.stat.gyro.y = camera.positon.y;					
		}
		//ジャイロ設定
		if(true){
			const GyroMonitor = (device_type) => {
				var first_beta = 0;
				var first_gamma = 0;
				var first_flag = true;
				var cnt = 0;
				var max_y = parseFloat(pm.max_y);
				var max_x = parseFloat(pm.max_x);
				var default_camera_y = camera.rotation.y ;
				var default_camera_x = camera.rotation.x ;
				var default_camera_pos_y = camera.position.y;
				var default_camera_pos_x = camera.position.x;
				var angle = 0;
				var frame = parseInt(pm.frame);
				three.stat.gyro.pm = pm;
				//var sc_width = parseInt(this.kag.config.scWidth);
				//var sc_height = parseInt(this.kag.config.scHeight);
				var sc_width = window.innerWidth;
				var sc_height = window.innerHeight;
				var sc_x = sc_width/2;
				var sc_y = sc_height/2;
				//PC版のイベントマウス動かす。
				if(device_type =="pc"){
					const mouseMoveEvent = (e) => {
						//マウスがどう動いたか
						//debugger;
						var x = e.clientX;
						x = ( x < 0 )? 0: x;
						x = ( sc_width < x )? sc_width : x;
						var y = e.clientY;
						y = ( y < 0 )? 0 : y ;
						y = ( sc_height < y )? sc_height : y;
						x = x - sc_x;
						y = (y - sc_y)*-1;
						//-1 〜 1 の間で進捗を出す。
 						var p_x = x / sc_x ;
 						var p_y = y / sc_y ;
 						//座標を調整する。
						var max_x = parseFloat(pm.max_x);
						var max_y = parseFloat(pm.max_y);
						var gyro_x = 0;
						var gyro_y = 0;
						//最大値以上になってたら、止める
						if(three.stat.gyro.mode == 1 ){
							//rotation 変更 ここバグ!!
							gyro_x = default_camera_x + (max_x * p_y * ( Math.PI / 180 ));
							gyro_y = default_camera_y - (max_y * p_x * ( Math.PI / 180 ));
						}else if(three.stat.gyro.mode == 2 ){
							//position  変更
							gyro_x =  default_camera_pos_x + max_x * p_x  ;
							gyro_y =  default_camera_pos_y + max_y * p_y  ;
						}
							// ここ修正
						three.stat.gyro.x = gyro_x;
						three.stat.gyro.y = gyro_y;
					}
					//イベントの登録と削除。マシンの場合
					$(".tyrano_base").get(0).removeEventListener('mousemove', mouseMoveEvent);
					$(".tyrano_base").get(0).addEventListener('mousemove', mouseMoveEvent, true);
				}else{
					//スマホの場合
					const orientEvent = (e) =>{
						//let angle_code = $.getAngle();
						//console.log(angle);
						if(first_flag == true){
							first_flag = false;
							first_beta = e.beta;
							first_gamma = e.gamma;
							angle = this.kag.tmp.angle;
							if(angle!=0){
								//値の入れ替え
								[max_x, max_y] = [max_y, max_x];
							}else {
								max_x = pm.max_x;
								max_y = pm.max_y;
							}
						}
						if(angle != this.kag.tmp.angle){
							first_flag = true;
							return;
						}
						if(angle!=0){
							var t_gamma = e.gamma;
							if(angle==-90){
								if(t_gamma < 0 ){
									return ;
								}
							}else if(angle==90){
								if(t_gamma > 0 ){
									return ;
								}
							}
						}
						var hen_y = first_beta - e.beta;
						var hen_x = first_gamma - e.gamma;
						if(Math.abs(hen_y) > max_y){
							 if(hen_y>0){ hen_y = max_y }else{hen_y=(-1*max_y)}
						}
						if(Math.abs(hen_x) > max_x){
							 if(hen_x>0){ hen_x = max_x }else{hen_x=(-1*max_x)}
						}
						//カメラのローテーション
						var gyro_x = 0;
						var gyro_y = 0;
						if(three.stat.gyro.mode == 1 ){
							//縦持ち
							if(angle==0){
								gyro_y = default_camera_x - (hen_x * ( Math.PI / 180 ));
								gyro_x = default_camera_y - (hen_y * ( Math.PI / 180 ));
							}else if(angle==-90){
								gyro_y = default_camera_y + (hen_y * ( Math.PI / 180 ));
								gyro_x = default_camera_x - (hen_x * ( Math.PI / 180 ));
							}else if(angle==90){
								gyro_y = default_camera_y + (hen_y*-1 * ( Math.PI / 180 ));
								gyro_x = default_camera_x - (hen_x*-1 * ( Math.PI / 180 ));
							}
						}else if(three.stat.gyro.mode == 2 ){
							//縦持ち
							if(angle==0){
								//position  変更
								gyro_x =  default_camera_pos_y + (hen_x*10) ;
								gyro_y =  default_camera_pos_x + (hen_y*10) ;
							}else if(angle==-90){
								gyro_y =  default_camera_pos_y + (hen_x*10)  ;
								gyro_x =  default_camera_pos_x + (hen_y*10)  ;
							}else if(angle==90){
								//position  変更
								gyro_y =  default_camera_pos_y + (hen_x*10)  ;
								gyro_x =  default_camera_pos_x + (hen_y*10)  ;
							}
						}
						three.stat.gyro.x = gyro_x;
						three.stat.gyro.y = gyro_y;
					}
					window.removeEventListener('deviceorientation', orientEvent);
					window.addEventListener('deviceorientation', orientEvent, true);
				}
			}
			const requestDeviceMotionPermission = () => {
				if (DeviceMotionEvent) {
					if(typeof DeviceMotionEvent.requestPermission === 'function'){
						DeviceMotionEvent.requestPermission().then(permissionState => {
							if (permissionState === 'granted') {
								GyroMonitor("sp");
						  	} else {
								// 許可を得られなかった場合の処理
						  	}
						})
						.catch(console.error) // https通信でない場合などで許可を取得できなかった場合
					}else{
						//アンドロイド
						GyroMonitor("sp");
					}
				}
			}
			if( $.userenv()!="pc"){
				requestDeviceMotionPermission();
			}
			else{
				GyroMonitor("pc");
			}

		}
		if(pm.next=="true"){
			this.kag.ftag.nextOrder();
		}
	}
},
TYRANO.kag.ftag.master_tag["3d_gyro"] = TYRANO.kag.tag["3d_gyro"];
TYRANO.kag.ftag.master_tag["3d_gyro"].kag = TYRANO.kag;

タグの仕様は、基本的に変わってはいません。

[3d_debug]

今回は、旧版の [3d_debug] をベースに修正しました。新版の方は今の所マニュピュレータの感応がおかしい点や、左上の操作板に本来あるべき項目がないなど未完成状態のようなので、ある程度動いている旧版をベースに修正しました。この版の場合、水平方向の動きはちゃんとうごくのですが、上下方向の動きが、水平方向が既に動いているとき場合は、意図した動きにならない点でした。これは、マウスの動きのx,yをそのまま、モデルのx,yに対応させているのが問題でした。それで、three.jsObject3D のメソッドの rotateOnWorldAxis を使うようにしたところ納得する動きになりました。あと、移動でカクカクしていた点や、Z軸回転や移動の仕様をちょっと変えて実装しました。それで、タグ名は、 [3d_debug_legacy] としました。 以下がコードです。

tyrano.plugin.kag.tag["3d_debug_legacy"] = {
	vital : ["name"],
	pm : {
		name:"",
		button_text:"3Dインスペクタを閉じる",
		menu:"true", 
		overlap:"false",
		reset:"false",
		scale:"true",
	},
	start : function(pm) {
		//debugger;
		var three = this.kag.tmp.three;
		// gyroをキャンセル
		three.stat.gyro.mode = 0;
		//一番前にもってきて、うごかせるようにする。
		var j_canvas = three.j_canvas;
		var target_layer = three.target_layer;
		var old_target_layer_zindex = target_layer.css("z-index");
		var old_canvas_zindex = j_canvas.css("z-index");
		/*
		j_canvas.css("z-index",9999999);
		target_layer.css("z-index",9999999);
		*/
		var model_obj = this.kag.tmp.three.models[pm.name];
		var model = model_obj.model;
		var renderer = three.renderer;
		var camera   = three.camera;
		//var sc_width = parseInt(this.kag.config.scWidth);
		//var sc_height = parseInt(this.kag.config.scHeight);
		var sc_width = window.innerWidth;
		var sc_height = window.innerHeight;
		var prevPosition ={};
		var mousedown = false;
		var button = 0;
		//オブジェクトの移動
		var vec = new THREE.Vector3(); // create once and reuse
		var pos = new THREE.Vector3(); // create once and reuse
		var original_pos = new THREE.Vector3(); // create once and reuse
		var hen_pos = {
			x:0,
			y:0,
			z:0,
		}
		var original_v = $.setVector(model);
		var first_client_y = 0; 
		var first_model_z = 0;
		var scale_flag = (pm.scale == "true")? true : false;
		function evt_mousewheel(e){
			// スケール
			var delta = e.wheelDelta;
			if( scale_flag == true ){
				if(delta < 0){
					model.scale.x -= model.scale.x*0.01;
					model.scale.y -= model.scale.y*0.01
					model.scale.z -= model.scale.z*0.01;
				}else{
					model.scale.x += model.scale.x*0.01;
					model.scale.y += model.scale.y*0.01
					model.scale.z += model.scale.z*0.01;
				}				
			}
			else {
				model.position.z = model.position.z + delta * 0.01;
			}
			evt_mouseup();
			e.preventDefault();
		}
		let first_rotation = model.rotation;
		let first_mouse_pos = {x: 0, y: 0 };
		function evt_mousedown(e){
			if (e.button == 0) {
				// xy回転
				first_rotation = model.rotaton;
				first_mouse_pos = { x: e.clientX, y: e.clientY};
				//console.log ( "***first mouse pos (" + first_mouse_pos.x + "," + first_mouse_pos.y + ")" );
				button = 0;
			}
			else if (e.button == 1) {
				//target.innerHTML = "中ボタンが押されました。";
				// z軸回転回転?移動?
				button = 1;
				first_rotation = model.rotaton;
				first_mouse_pos = { x: e.clientX, y: e.clientY};
				first_client_y = e.clientY;
				first_model_z = model.position.z;
			}
			else if (e.button == 2) {
				// xy移動
				button = 2;
				vec.set(
				( e.clientX / window.innerWidth ) * 2 - 1,
					- ( e.clientY / window.innerHeight ) * 2 + 1,
				0.5 );
				//console.log( "***vec [" + vec.x + "," + vec.y + "," + vec.z + "]" );
				vec.unproject(camera);
				vec.sub(camera.position).normalize();
				var distance = 0;
				if(camera.position.z > 0){
					distance =  - camera.position.z / vec.z ;
				}else{
					distance =  camera.position.z / vec.z ;
				}
				original_pos.copy( camera.position ).add(vec.multiplyScalar( distance));
				hen_pos.x = model.position.x - original_pos.x;
				hen_pos.y = model.position.y - original_pos.y;
			}
			mousedown = true;
			prevPosition = {x: e.clientX, y: e.clientY};
		}
		function evt_mousemove(e){
			if (!mousedown) return;
			j_close_button.hide();
			if(button==0){
				let D = {x: e.clientX - prevPosition.x , y: -e.clientY + prevPosition.y };
				let l = Math.sqrt( D.x*D.x + D.y*D.y );
				const r = new THREE.Vector3( -D.y/l, D.x/l , 0 );
				model.rotateOnWorldAxis( r, l * 0.003 );
				prevPosition = {x: e.clientX, y: e.clientY};
			}else if(button==1){
				let D =  e.clientX - prevPosition.x ;
				const r = new THREE.Vector3( 0, 0 , 1 );
				model.rotateOnWorldAxis( r, D * 0.003 );
				prevPosition = {x: e.clientX, y: e.clientY};
			}else if(button ==2){
				vec.set(
				( e.clientX / window.innerWidth ) * 2 - 1,
					- ( e.clientY / window.innerHeight ) * 2 + 1,
				0.5 );
				vec.unproject(camera);
				vec.sub(camera.position).normalize();
				console.log( "***vecs [" + vec.x + "," + vec.y + "," + vec.z + "]" );
				var distance = 0;
				if(camera.position.z > 0){
					distance =  - camera.position.z / vec.z;
				}else{
					distance =  camera.position.z / vec.z;
				}
				console.log( "distance :" + distance );
				pos.copy( camera.position ).add(vec.multiplyScalar( distance));
				console.log ( "pos: [" + pos.x + "," + pos.y + "," + pos.z + "]" )
				model.position.x = hen_pos.x + pos.x;
				model.position.y = hen_pos.y + pos.y;
			}
		}
		function evt_mouseup(e){	
			j_close_button.show();
			if(button==0){
				var str = $.orgFloor(model.rotation.x,100) + "," + $.orgFloor(model.rotation.y,100) + "," + model.rotation.z;
			}else if(button ==2 || button==1){            	   
			}
			var msg_pos = model.position.x + "," + model.position.y + "," + model.position.z;
			var msg_rot = $.orgFloor(model.rotation.x,100) + "," + $.orgFloor(model.rotation.y,100) + "," + $.orgFloor(model.rotation.z,100);
			var msg_scale = $.orgFloor(model.scale.x,100) + "," + $.orgFloor(model.scale.y,100) + "," + $.orgFloor(model.scale.z,100);
			//pmを更新する
			var _pm = model_obj["pm"];
			_pm["pos"] = msg_pos;
			_pm["rot"] = msg_rot;
			_pm["scale"] = msg_scale;
			model_obj["pm"] = _pm;
			var msg = 'pos="'+msg_pos+'" rot="'+msg_rot+'" scale="'+msg_scale+'" ';
			j_debug_msg.find("input").val(msg);
			mousedown = false;
		}
		if(pm.overlap=="true"){
			j_canvas.css("z-index",9999999);
			target_layer.css("z-index",9999999);
		}
		//デバッグ用のレイヤ
		var j_three_debug_layer = $("<div style='width:100%;height:100%;position:absolute;z-index:9999999;'></div>");
		$(".tyrano_base").append(j_three_debug_layer);
		var three_debug_layer = j_three_debug_layer.get(0);
		///マウスホイール
		three_debug_layer.addEventListener("mousewheel",evt_mousewheel,false);
		three_debug_layer.addEventListener('mousedown',evt_mousedown,false);
		three_debug_layer.addEventListener('mouseup', evt_mouseup,false);
		three_debug_layer.addEventListener('mousemove', evt_mousemove,false);
		//デバッグ終了ボタンを押すと、nextOrderする。
		//リロードボタンの配置
		//メッセージエリア非表示。
		var j_close_button = $("<div class='area_three_debug' style='position:absolute;z-index:9999999999;padding:10px;opacity:0.8;background-color:white;left:0px;top:0px'><button style='cursor:pointer'><span style=''>"+pm.button_text+"</span></button></div>");
		j_close_button.draggable({
			scroll : false,
			//containment:".tyrano_base",
			stop : (e, ui) => {
			}
		});
		var j_debug_msg = $("<div style='padding:5px'><input type='text' style='width:320px' /></div>");
		var j_copy_button = $("<input type='button' value='コピー' />");
		j_copy_button.on("click",(e)=>{
			evt_mouseup();
			j_debug_msg.find("input").select();
			// コピー
			document.execCommand("copy");
		});
		var j_reset_button = $("<input type='button' value='リセット' />");
		j_reset_button.on("click",(e)=>{
			//モデルを最初の位置に戻す
			//document.execCommand("copy");
			model.position.set(original_v.pos.x, original_v.pos.y, original_v.pos.z ); 
			model.rotation.set(original_v.rot.x, original_v.rot.y, original_v.rot.z ); 
			model.scale.set(original_v.scale.x, original_v.scale.y, original_v.scale.z ); 
		});
		j_close_button.find("button").on("click",(e)=>{ 
			j_three_debug_layer.remove();
			if(pm.reset=="true"){
				j_reset_button.trigger("click");
			}
			j_close_button.remove();
			j_canvas.css("z-index",old_canvas_zindex);
			target_layer.css("z-index",old_target_layer_zindex);
			three_debug_layer.removeEventListener("mousedown",evt_mousedown);
			three_debug_layer.removeEventListener("mouseup",evt_mouseup);
			three_debug_layer.removeEventListener("mousemove",evt_mousemove);
			three_debug_layer.removeEventListener("mousewheel",evt_mousewheel);
			this.kag.ftag.nextOrder();
		});
		if(pm.menu=="true"){ 
			j_close_button.append("<span>|</span>");
			j_close_button.append(j_copy_button);
			j_close_button.append(j_reset_button);
			j_close_button.append(j_debug_msg);
		}        
		$("body").append(j_close_button);
		//初期値を設定する。
		evt_mouseup();
	},
};
TYRANO.kag.ftag.master_tag["3d_debug_legacy"] = TYRANO.kag.tag["3d_debug_legacy"];
TYRANO.kag.ftag.master_tag["3d_debug_legacy"].kag = TYRANO.kag;

仕様は、左ボタンを押したままのドラッグで、モデルのx,y面上の軸での回転、右ボタンを押したままのドラッグで、モデルのx,y面上の移動で、中央ボタンを押したままのx方向へのドラッグをz軸回転、マウスのホイール回転がスケール変更です。ただ、パラメータの scale"false" に指定すると、ホイール回転で、軸移動になります。

[3d_debug_camera]

このタグ自体は、終われない問題だけでしたが、それは、j_close_button.find(….
内での、removeEventListenerの大本のオブジェクトが window でなかったのが原因でした。修正は基本そこだけです。

TYRANO.kag.tag["3d_debug_camera"] = {
	vital: [],
	pm: {
	  name: "camera",
	  button_text: "カメラインスペクタを閉じる",
	  menu: "true",
	  menu_close: "true",
	  rotate: "true",
	  move: "true",
	},
	start: function (pm) {
		//debugger;
		var three = this.kag.tmp.three,
		j_canvas = three.j_canvas,
		target_layer = three.target_layer,
		old_target_layer_zindex = target_layer.css("z-index"),
		old_canvas_zindex = j_canvas.css("z-index"),
		model = this.kag.tmp.three.models[pm.name].model,
		renderer = three.renderer,
		mousedown =
		  (three.camera,
		  parseInt(this.kag.config.scWidth),
		  parseInt(this.kag.config.scHeight),
		  !1),
		button = 0,
		original_v =
		  (new THREE.Vector3(),
		  new THREE.Vector3(),
		  new THREE.Vector3(),
		  $.setVector(model)),
		first_client_x = 0,
		first_client_y = 0,
		spot_client_x = 0,
		spot_client_y = 0,
		first_model_x = 0,
		first_model_y = 0;
	  function evt_mousewheel(e) {
		mousedown = !1;
	  }
	  function evt_mousedown(e) {
		if (0 == e.button && "true" == pm.rotate) {
		  button = 0;
		  first_client_x = e.clientX;
		  first_client_y = e.clientY;
		  first_model_x = model.rotation.x;
		  first_model_y = model.rotation.y;
		  $(".panel_chat").css("pointer-events", "none");
		} else if (1 == e.button && "true" == pm.move) {
		  button = 1;
		  first_client_y = e.clientY;
		  model.position.z;
		} else {
		  if (2 != e.button || "true" != pm.move) {
			mousedown = !1;
			return;
		  }
		  button = 2;
		  first_client_x = e.clientX;
		  first_client_y = e.clientY;
		  first_model_x = model.position.x;
		  first_model_y = model.position.y;
		}
		mousedown = !0;
	  }
	  function evt_mousemove(e) {
		if (1 != three.stat.fps.move_trans_control && mousedown) {
		  three.stat.start_event = !1;
		  let bs = e.buttons;
		  if ( (bs & 1 ) == 1 ) {
			// 左ボタン
			var hen_x = first_client_x - e.clientX;
			model.rotation.y = first_model_y + 0.005 * hen_x;
			var hen_y = first_client_y - e.clientY;
			model.rotation.x = first_model_x + 0.005 * hen_y;
		  } else if ((bs & 4) == 4 ) {
			// 中央ボタン
			0 != spot_client_y &&
			  model.translateZ(-1 * (spot_client_y - e.clientY));
			spot_client_y = e.clientY;
		  } else if ((bs & 2 ) == 2 ) {
			// 右ボタン
			0 != spot_client_x && model.translateX(spot_client_x - e.clientX);
			spot_client_x = e.clientX;
			0 != spot_client_y &&
			  model.translateY(-1 * (spot_client_y - e.clientY));
			spot_client_y = e.clientY;
		  }
		  else{
			evt_mouseup(e);
		  }
		}
	  }
	  function evt_mouseup(e) {
		first_client_x = 0;
		first_client_y = 0;
		if (0 == button) {
		  $.orgFloor(model.rotation.x, 100),
			$.orgFloor(model.rotation.y, 100),
			model.rotation.z;
		  $(".panel_chat").css("pointer-events", "");
		} else if (2 == button || 1 == button) {
		  spot_client_x = 0;
		  spot_client_y = 0;
		}
		var msg =
		  'pos="' +
		  (model.position.x + "," + model.position.y + "," + model.position.z) +
		  '" rot="' +
		  ($.orgFloor(model.rotation.x, 100) +
			"," +
			$.orgFloor(model.rotation.y, 100) +
			"," +
			$.orgFloor(model.rotation.z, 100)) +
		  '" scale="' +
		  ($.orgFloor(model.scale.x, 100) +
			"," +
			$.orgFloor(model.scale.y, 100) +
			"," +
			$.orgFloor(model.scale.z, 100)) +
		  '" ';
		j_debug_msg.find("input").val(msg);
		mousedown = !1;
		1 == three.stat.fps.is_fps_studio && (three.stat.start_event = !0);
		setTimeout((e) => {
		  three.stat.start_event = !0;
		}, 500);
	  }
	  if ("ontouchstart" in document.documentElement) {
		renderer.domElement.addEventListener(
		  "touchstart",
		  function (e) {
			evt_mouseup();
			for (let key in e.touches) {
			  let touche = e.touches[key];
			  if ("three" == touche.target.id) {
				touche.button = 0;
				evt_mousedown(touche);
				break;
			  }
			}
		  },
		  !1
		);
		renderer.domElement.addEventListener(
		  "touchend",
		  function (e) {
			evt_mouseup();
		  },
		  !1
		);
		renderer.domElement.addEventListener(
		  "touchmove",
		  function (e) {
			for (let key in e.touches) {
			  let touche = e.touches[key];
			  if ("three" == touche.target.id) {
				touche.button = 0;
				evt_mousemove(touche);
				break;
			  }
			}
		  },
		  !1
		);
	  } else {
		window.addEventListener("mousewheel", evt_mousewheel);
		window.addEventListener("mousedown", evt_mousedown,true);
		window.addEventListener("mouseup", evt_mouseup);
		window.addEventListener("mousemove", evt_mousemove);
	  }
	  var j_close_button = $(
		"<div class='area_three_debug' style='position:absolute;z-index:9999999999;padding:10px;opacity:0.8;background-color:white;left:0px;top:0px'><button style='cursor:pointer'><span style=''>" +
		  pm.button_text +
		  "</span></button></div>"
	  );
	  j_close_button.draggable({ scroll: !1, stop: (e, ui) => {} });
	  var j_debug_msg = $(
		  "<div style='padding:5px'><input type='text' style='width:320px' /></div>"
		),
		j_copy_button = $("<input type='button' value='コピー' />");
	  j_copy_button.on("click", (e) => {
		evt_mouseup();
		j_debug_msg.find("input").select();
		document.execCommand("copy");
	  });
	  var j_reset_button = $("<input type='button' value='リセット' />");
	  j_reset_button.on("click", (e) => {
		model.position.set(
		  original_v.pos.x,
		  original_v.pos.y,
		  original_v.pos.z
		);
		model.rotation.set(
		  original_v.rot.x,
		  original_v.rot.y,
		  original_v.rot.z
		);
		model.scale.set(
		  original_v.scale.x,
		  original_v.scale.y,
		  original_v.scale.z
		);
	  });
	  j_close_button.find("button").on("click", (e) => {
		j_close_button.remove();
		j_canvas.css("z-index", old_canvas_zindex);
		target_layer.css("z-index", old_target_layer_zindex);
		window.removeEventListener("mousedown", evt_mousedown,true);
		window.removeEventListener("mouseup", evt_mouseup);
		window.removeEventListener("mousemove", evt_mousemove);
		window.removeEventListener("mousewheel", evt_mousewheel);
		this.kag.ftag.nextOrder();
	  });
	  if ("true" == pm.menu) {
		j_close_button.append("<span style='font-size:10px'>|</span>");
		j_close_button.append(j_copy_button);
		j_close_button.append(j_reset_button);
		j_close_button.append(j_debug_msg);
	  }
	  if ("false" == pm.menu_close) {
		this.kag.ftag.nextOrder();
		j_close_button.hide();
	  }
	  if (1 == three.stat.fps.active) {
		three.stat.start_event = !0;
		this.kag.stat.is_strong_stop = !0;
	  }
	  $("body").append(j_close_button);
	},
};
TYRANO.kag.ftag.master_tag["3d_debug_camera"] = TYRANO.kag.tag["3d_debug_camera"];
TYRANO.kag.ftag.master_tag["3d_debug_camera"].kag = TYRANO.kag;

終わりに

three.js の OrbitControlsTransformControls のライブラリは、[3d_debug] でのみ使われていますですので、[3d_debug_legacy] を使う範囲内では、ロードする必要はありません。但し、将来利用することを考慮して、init.ks 内でロードするままでも特に支障はないとおもいます。
現時点では、新規タグとしてグループモデルの生成タグ [3d_group_new] 、モデルを他のモデルの子にする [3d_in] 、子から独立させる [3d_out] まではコーディング済みですが、まずは、第一弾は、これまでにして、次回でまとめにしたいと思います。


この記事が気に入ったらサポートをしてみませんか?