From 6b02daa6e2ea69e5fe0b493cff501484cf7dd2a8 Mon Sep 17 00:00:00 2001
From: Lucio Zambon <lucio.zambon@elettra.eu>
Date: Fri, 13 Sep 2024 00:27:50 +0000
Subject: [PATCH] Update panther.js

---
 panther.js | 107 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 92 insertions(+), 15 deletions(-)

diff --git a/panther.js b/panther.js
index ee40ff4..5734e16 100644
--- a/panther.js
+++ b/panther.js
@@ -7,6 +7,7 @@
 	import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js';
 	import {RenderPass} from 'three/addons/postprocessing/RenderPass.js';
 	import {OutlinePass} from 'three/addons/postprocessing/OutlinePass.js';
+	import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
 
 	import {ellipticaltubeGeometry} from 'components/ellipticaltube.js';
 	import {chamber} from 'components/chamber.js';
@@ -78,8 +79,11 @@
 	const bpmSkip = {};
 	const bpmIndex = {};
 	const bpmData = {};
+	const compBuffer = {};
+	const loader = new GLTFLoader();
 	let fast = document.location.search.indexOf('fast')>-1? document.location.search.split('fast')[1].split('&')[0].split(','): false;
 	let premium = document.location.search.indexOf('premium')>-1? document.location.search.split('premium')[1].split('&')[0].split(','): false;
+	const real = document.location.search.indexOf('real')>-1;
 	const blm = {oldIndex: null, reader: false, acqTime: null};
 	let latticenodes = 0;
 	const Ydefault = 100;
@@ -314,7 +318,7 @@
 			fetch(conf.stateSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
 				const statSrc = data.toUpperCase().split(',');
 				for (let j=0; j<statSrc.length; j++) {
-					statSrc[j] = statSrc[j].split('/')[3].replace('PS', '');
+					if (typeof statSrc[j].split('/')[3] != 'undefined') statSrc[j] = statSrc[j].split('/')[3].replace('PS', '');
 					// if (statSrc[j].split('/')[1]=='POWER_SUPPLY') statSrc[j] = statSrc[j].split('/')[2].replace('PS', '');
 				}
 				for (let i=0; i<status.length; i++) { 
@@ -324,25 +328,37 @@
 				}
 				console.log('statSrc', statSrc, status);
 			})
-			.catch(error => {console.log("Fetch error", error);});
+			.catch(error => {console.log('stateSrcUrl: '+conf.stateSrcUrl, "Fetch error", error);});
 			setInterval(updateStatus, 1000);
 		}
 	})
 	.catch(error => {console.log("Fetch error", error);});
 	function showStatus(i, stat) {
-		if (stat == 0 || stat == 'null' || stat == '' || stat == 'ON' || stat == 'RUNNING' || (!fel1 && status[i].facility=='fel1') || (!fel2 && status[i].facility=='fel2')) {status[i].visible = false;}
+			status[i].scale.x = 1;
+			status[i].scale.y = 1;
+			status[i].scale.z = 1;
+		if (stat == 'null' || stat == '' || stat == 0 || (!fel1 && status[i].facility=='fel1') || (!fel2 && status[i].facility=='fel2')) {status[i].visible = false;}
+		else if (stat == 'ON' || stat == 'RUNNING') {
+			status[i].visible = true; 
+			status[i].material.color.set(conf.stateLabelColor[stat]);
+			status[i].scale.x = statScale;
+			status[i].scale.y = statScale;
+			status[i].scale.z = statScale;
+		}
 		else {status[i].visible = true; status[i].material.color.set(conf.stateLabelColor[stat]);}
-		// console.log(i, status[i], stat);
+		// if (i==40) console.log(i, status[i], stat);
 	}
 	function clearStatus() {
 		for (let i=0; i<status.length; i++) {
-			if (status[i].statsrc==ps) showStatus(i, 0);
+			if (status[i].statsrc==ps && statVal[status[i].statindex]!=='ON' && statVal[status[i].statindex]!=='RUNNING') showStatus(i, 0);
 		}
 	}
+	let statVal;
+	const statScale = 0.3; 
 	function updateStatus() {
 		fetch(conf.stateUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
 			// console.log('updateStatus()', fel1, fel2, status);
-			const statVal = data.split(';');
+			statVal = data.split(';');
 			for (let i=0; i<status.length; i++) {
 				if (status[i].statsrc==ps) {
 					if (status[i].statindex) showStatus(i, statVal[status[i].statindex]);
@@ -430,11 +446,69 @@
 	// status
 	const normalMaterial = new THREE.MeshBasicMaterial({ color: 0xffff66});
 	const sphereGeometry = new THREE.SphereGeometry(300, 10, 10);
+	const rot = {x: $('#rotx').val(), y: $('#roty').val(), z: $('#rotz').val()};
+	let gltfscene;
 
+	function pushComponent(facility, i, m, tang, direction, y=Ydefault) {
+		let magnet = lattice[facility].sections[i].components[m].type;
+		if (typeof compBuffer[magnet] == 'undefined') compBuffer[magnet] = [];
+		compBuffer[magnet].push({facility: facility, i: i, m: m, tang: tang, direction: direction, y: y});
+	}
+	function placemagnet(magnet, gs) {
+		const gltfscene = new THREE.Object3D();
+		gs.scale.set(900, 900, 900);
+		gs.rotateX(conf.real[magnet].rot.x);
+		gs.rotateY(conf.real[magnet].rot.y);
+		gs.rotateZ(conf.real[magnet].rot.z);
+		gs.position.set(conf.real[magnet].pos.x, conf.real[magnet].pos.y, conf.real[magnet].pos.z);
+		gltfscene.add(gs);
+		console.log('placemagnet', gltfscene, gltfscene.rotation, gltfscene.rotation.x);
+		for (let l=0; l<compBuffer[magnet].length; l++) {
+			const mycomp = gltfscene.clone();
+			const facility = compBuffer[magnet][l].facility;
+			const i = compBuffer[magnet][l].i;
+			const m = compBuffer[magnet][l].m;
+			const tang = compBuffer[magnet][l].tang;
+			const direction = compBuffer[magnet][l].direction;
+			const y = compBuffer[magnet][l].y;
+			const myname = lattice[facility].sections[i].components[m].name;
+			console.log(facility, i, m, lattice[facility].sections[i].components[m]);
+			const id = extractId(myname);
+			const d = lattice[facility].sections[i].components[m].position;
+			const den = Math.sqrt(tang*tang+1) * direction;
+			const offset = lattice[facility].sections[i].components[m].offset3d? lattice[facility].sections[i].components[m].offset3d: [0, 0, 0];
+			mycomp.position.set(params.highlightScale*(lattice[facility].sections[i].start.x + tang*d / den) + offset[0], y + offset[1], params.highlightScale*(lattice[facility].sections[i].start.z + d / den + offset[2]));
+			if (mycomp.rotatedX) {mycomp.rotateZ(Math.atan(-tang));} else mycomp.rotateY(Math.atan(tang));
+			window.names.push(lattice[facility].sections[i].components[m].name);
+			if (lattice[facility].sections[i].components[m].embedded) {
+				// console.log('mycomp.embedded',lattice[facility].sections[i].components[m].embedded);
+				for (let j=0; j<lattice[facility].sections[i].components[m].embedded.length; j++)  {names.push(lattice[facility].sections[i].components[m].embedded[j]); alias.push([myname,lattice[facility].sections[i].components[m].embedded[j]]);}
+			}
+			if (id[1]) {window.names.push(id[1]); alias.push(id);}
+			mycomp.magnetType = magnet;
+			mycomp.name = lattice[facility].sections[i].components[m].name;
+			compBuffer[magnet][l].name = mycomp.name;
+			if (lattice[facility].sections[i].components[m].href) mycomp.href = lattice[facility].sections[i].components[m].href;
+			if (highlight.length && !highlight.find(element => element == magnet)) {mycomp.scale.set(params.highlightShrink, params.highlightShrink, params.highlightShrink);}
+			facilities[facility].add(mycomp);
+			compBuffer[magnet][l].mycomp = mycomp;
+			scene.add(mycomp);
+		}
+	}
+	function loadreal(magnet) {
+		loader.load( './components/'+magnet+'.glb', function ( gltf ) {
+			placemagnet(magnet, gltf.scene);
+		}, undefined, function ( error ) {
+			console.error( error );
+		});
+	}
 	function appendComponent(facility, i, m, tang, direction, y=Ydefault) {
 		if (tang==-Infinity) tang = -1e12;
 		if (tang==Infinity) tang = 1e12;
 		let magnet = lattice[facility].sections[i].components[m].type;
+		// if (magnet=='quadrupole') return;
+		// if (glb.indexOf(magnet)>-1) return;
+		if (real && typeof conf.real[magnet] !== 'undefined') return;
 		if (componentCreator[magnet+'fast'] && (fast==false || fast.indexOf(magnet)>-1)) magnet = magnet+'fast';
 		if (componentCreator[magnet+'premium'] && (premium==false || premium.indexOf(magnet)>-1)) magnet = magnet+'premium';
 		if (componentCreator[magnet]) {
@@ -544,6 +618,7 @@
 			if (document.location.search.indexOf('components=hide')==-1) if (flattice[i].components) for (let m=0; m<flattice[i].components.length; m++) {
 				// if (facility=='servicearea') console.log(facility, i, m, tang, direction);
 				const position = appendComponent(facility, i, m, tang, direction, y);
+				pushComponent(facility, i, m, tang, direction, y);
 				if (flattice[i].components[m].type=='bpm' && (document.location.search.indexOf('&bpm')>-1 || document.location.search.indexOf('?bpm')>-1) && lattice[facility].bpm) {
 					if (lattice[facility].bpm.skip && (lattice[facility].bpm.skip.indexOf(flattice[i].components[m].name)>-1)) {bpmSkip[facility].push(bpmPoints[facility].length);}
 					else bpmPoints[facility].push([position.clone(), tang, direction]);
@@ -551,6 +626,8 @@
 			}
 			envelopeAdd(flattice, i, j, facility, direction);
 		}
+		console.log('compBuffer', compBuffer);
+		if (real) for (let i in conf.real) {loadreal(i);}
 
 		// console.log('vlvs', vlvs); console.log('facilities', facilities, 'names', window.names.join(';'));
 		bpmAdd(facility);
@@ -608,7 +685,7 @@
 		outlinePass.selectedObjects = [];
 		for (let facility in scene.children) {
 			for (let comp in scene.children[facility].children) {
-				if (scene.children[facility].children[comp].name==name) {
+				if (scene.children[facility].children[magnet].name==name) {
 					const dist = scene.children[facility].name=='servicearea'? 7000: 1000;
 					facilities[scene.children[facility].name].visible = true; // make facility visible
 					// transverse lil menu and check facility checkbox
@@ -627,23 +704,23 @@
 						}
 					}
 					found = true;
-					const selectedObject = scene.children[facility].children[comp];
+					const selectedObject = scene.children[facility].children[magnet];
 					if (outline) {outlinePass.selectedObjects = [selectedObject]; addSelectedObject(selectedObject);}
 					renderer.render(scene, camera);
 					x1 = camera.position.x;
 					y1 = camera.position.y;
 					z1 = camera.position.z;
-					x2 = scene.children[facility].children[comp].position.x+dist*Math.sign(scene.children[facility].children[comp].position.x);
-					y2 = scene.children[facility].children[comp].position.y+dist*Math.sign(scene.children[facility].children[comp].position.y);
-					z2 = scene.children[facility].children[comp].position.z+dist*Math.sign(scene.children[facility].children[comp].position.z);
-					console.log("findComponent()", name, selectedObject, x1, x2, scene.children[facility].children[comp].position, scene.children[facility]);
+					x2 = scene.children[facility].children[magnet].position.x+dist*Math.sign(scene.children[facility].children[magnet].position.x);
+					y2 = scene.children[facility].children[magnet].position.y+dist*Math.sign(scene.children[facility].children[magnet].position.y);
+					z2 = scene.children[facility].children[magnet].position.z+dist*Math.sign(scene.children[facility].children[magnet].position.z);
+					console.log("findComponent()", name, selectedObject, x1, x2, scene.children[facility].children[magnet].position, scene.children[facility]);
 					const lookat = (new THREE.Vector3(0, 0, -20000)).applyQuaternion(camera.quaternion).add(camera.position); // https://stackoverflow.com/questions/27957645/three-js-find-the-current-lookat-of-a-camera
 					rx1 = lookat.x;
 					ry1 = lookat.y;
 					rz1 = lookat.z;
-					rx2 = scene.children[facility].children[comp].position.x;
-					ry2 = scene.children[facility].children[comp].position.y;
-					rz2 = scene.children[facility].children[comp].position.z;
+					rx2 = scene.children[facility].children[magnet].position.x;
+					ry2 = scene.children[facility].children[magnet].position.y;
+					rz2 = scene.children[facility].children[magnet].position.z;
 					if (debugcamera) {$('#x').val(x1); $('#y').val(y1); $('#z').val(z1); $('#cx').val(rx1); $('#cy').val(ry1); $('#cz').val(rz1);}
 					cameraStep = numSteps;
 					updateCamera();
-- 
GitLab