Spaces:
Running
Running
Update tooltips.js
Browse files- tooltips.js +28 -40
tooltips.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
| 3 |
/**
|
| 4 |
* initializeTooltips(options)
|
| 5 |
*
|
| 6 |
-
* - options.app: the PlayCanvas
|
| 7 |
-
* - options.cameraEntity:
|
| 8 |
-
* - options.modelEntity: the main model entity (for
|
| 9 |
* - options.tooltipsUrl: URL to fetch JSON array of tooltip definitions
|
| 10 |
* - options.defaultVisible: boolean: whether tooltips are visible initially
|
| 11 |
* - options.moveDuration: number (seconds) for smooth camera move to selected tooltip
|
|
@@ -20,29 +20,23 @@ export async function initializeTooltips(options) {
|
|
| 20 |
moveDuration = 0.6
|
| 21 |
} = options;
|
| 22 |
|
| 23 |
-
if (!app || !cameraEntity || !tooltipsUrl)
|
| 24 |
-
return;
|
| 25 |
-
}
|
| 26 |
|
| 27 |
let tooltipsData;
|
| 28 |
try {
|
| 29 |
const resp = await fetch(tooltipsUrl);
|
| 30 |
tooltipsData = await resp.json();
|
| 31 |
-
} catch (e) {
|
| 32 |
-
|
| 33 |
-
}
|
| 34 |
-
if (!Array.isArray(tooltipsData)) {
|
| 35 |
-
return;
|
| 36 |
-
}
|
| 37 |
|
| 38 |
const tooltipEntities = [];
|
| 39 |
|
| 40 |
-
// Create a material for tooltip spheres
|
| 41 |
const mat = new pc.StandardMaterial();
|
| 42 |
mat.diffuse = new pc.Color(1, 0.8, 0);
|
| 43 |
mat.specular = new pc.Color(1, 1, 1);
|
| 44 |
mat.shininess = 20;
|
| 45 |
-
mat.emissive = new pc.Color(0.85, 0.85, 0.85);
|
| 46 |
mat.emissiveIntensity = 1;
|
| 47 |
mat.useLighting = false;
|
| 48 |
mat.update();
|
|
@@ -64,9 +58,7 @@ export async function initializeTooltips(options) {
|
|
| 64 |
}
|
| 65 |
|
| 66 |
function setTooltipsVisibility(visible) {
|
| 67 |
-
tooltipEntities.forEach(ent => {
|
| 68 |
-
ent.enabled = visible;
|
| 69 |
-
});
|
| 70 |
}
|
| 71 |
setTooltipsVisibility(!!defaultVisible);
|
| 72 |
|
|
@@ -83,10 +75,8 @@ export async function initializeTooltips(options) {
|
|
| 83 |
currentTween = null;
|
| 84 |
}
|
| 85 |
|
| 86 |
-
const x = event.x;
|
| 87 |
-
const
|
| 88 |
-
const from = new pc.Vec3();
|
| 89 |
-
const to = new pc.Vec3();
|
| 90 |
const camera = cameraEntity.camera;
|
| 91 |
|
| 92 |
camera.screenToWorld(x, y, camera.nearClip, from);
|
|
@@ -127,9 +117,7 @@ export async function initializeTooltips(options) {
|
|
| 127 |
}
|
| 128 |
});
|
| 129 |
|
| 130 |
-
//
|
| 131 |
-
|
| 132 |
-
// Helper to normalize angle difference into [-180, +180]
|
| 133 |
function shortestAngleDiff(target, current) {
|
| 134 |
let delta = target - current;
|
| 135 |
delta = ((delta + 180) % 360 + 360) % 360 - 180;
|
|
@@ -141,12 +129,12 @@ export async function initializeTooltips(options) {
|
|
| 141 |
if (!orbitCam) return;
|
| 142 |
|
| 143 |
const targetPos = tooltipEnt.getPosition().clone();
|
| 144 |
-
const startPivot
|
| 145 |
-
const startYaw
|
| 146 |
-
const startPitch
|
| 147 |
-
const startDist
|
| 148 |
|
| 149 |
-
const worldRadius
|
| 150 |
const minZoom = orbitCam.distanceMin;
|
| 151 |
const desiredDistance = Math.max(minZoom * 1.2, worldRadius * 4);
|
| 152 |
|
|
@@ -171,14 +159,14 @@ export async function initializeTooltips(options) {
|
|
| 171 |
|
| 172 |
tempEnt.destroy();
|
| 173 |
|
| 174 |
-
const endPivot
|
| 175 |
-
const endDist
|
| 176 |
|
| 177 |
let elapsed = 0;
|
| 178 |
const orgPivot = startPivot.clone();
|
| 179 |
-
const orgYaw
|
| 180 |
const orgPitch = startPitch;
|
| 181 |
-
const orgDist
|
| 182 |
|
| 183 |
if (currentTween) {
|
| 184 |
app.off("update", currentTween);
|
|
@@ -192,16 +180,16 @@ export async function initializeTooltips(options) {
|
|
| 192 |
const newPivot = new pc.Vec3().lerp(orgPivot, endPivot, t);
|
| 193 |
orbitCam.pivotPoint.copy(newPivot);
|
| 194 |
|
| 195 |
-
const newYaw
|
| 196 |
const newPitch = pc.math.lerp(orgPitch, endPitch, t);
|
| 197 |
-
const newDist
|
| 198 |
|
| 199 |
-
orbitCam._targetYaw
|
| 200 |
-
orbitCam._yaw
|
| 201 |
-
orbitCam._targetPitch
|
| 202 |
-
orbitCam._pitch
|
| 203 |
orbitCam._targetDistance = newDist;
|
| 204 |
-
orbitCam._distance
|
| 205 |
|
| 206 |
orbitCam._updatePosition();
|
| 207 |
|
|
|
|
| 3 |
/**
|
| 4 |
* initializeTooltips(options)
|
| 5 |
*
|
| 6 |
+
* - options.app: the PlayCanvas AppBase instance
|
| 7 |
+
* - options.cameraEntity: PlayCanvas camera Entity
|
| 8 |
+
* - options.modelEntity: the main model entity (for relative positioning, optional)
|
| 9 |
* - options.tooltipsUrl: URL to fetch JSON array of tooltip definitions
|
| 10 |
* - options.defaultVisible: boolean: whether tooltips are visible initially
|
| 11 |
* - options.moveDuration: number (seconds) for smooth camera move to selected tooltip
|
|
|
|
| 20 |
moveDuration = 0.6
|
| 21 |
} = options;
|
| 22 |
|
| 23 |
+
if (!app || !cameraEntity || !tooltipsUrl) return;
|
|
|
|
|
|
|
| 24 |
|
| 25 |
let tooltipsData;
|
| 26 |
try {
|
| 27 |
const resp = await fetch(tooltipsUrl);
|
| 28 |
tooltipsData = await resp.json();
|
| 29 |
+
} catch (e) { return; }
|
| 30 |
+
if (!Array.isArray(tooltipsData)) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
const tooltipEntities = [];
|
| 33 |
|
| 34 |
+
// Create a material for tooltip spheres (still use StandardMaterial, works fine)
|
| 35 |
const mat = new pc.StandardMaterial();
|
| 36 |
mat.diffuse = new pc.Color(1, 0.8, 0);
|
| 37 |
mat.specular = new pc.Color(1, 1, 1);
|
| 38 |
mat.shininess = 20;
|
| 39 |
+
mat.emissive = new pc.Color(0.85, 0.85, 0.85);
|
| 40 |
mat.emissiveIntensity = 1;
|
| 41 |
mat.useLighting = false;
|
| 42 |
mat.update();
|
|
|
|
| 58 |
}
|
| 59 |
|
| 60 |
function setTooltipsVisibility(visible) {
|
| 61 |
+
tooltipEntities.forEach(ent => { ent.enabled = visible; });
|
|
|
|
|
|
|
| 62 |
}
|
| 63 |
setTooltipsVisibility(!!defaultVisible);
|
| 64 |
|
|
|
|
| 75 |
currentTween = null;
|
| 76 |
}
|
| 77 |
|
| 78 |
+
const x = event.x, y = event.y;
|
| 79 |
+
const from = new pc.Vec3(), to = new pc.Vec3();
|
|
|
|
|
|
|
| 80 |
const camera = cameraEntity.camera;
|
| 81 |
|
| 82 |
camera.screenToWorld(x, y, camera.nearClip, from);
|
|
|
|
| 117 |
}
|
| 118 |
});
|
| 119 |
|
| 120 |
+
// Camera animation
|
|
|
|
|
|
|
| 121 |
function shortestAngleDiff(target, current) {
|
| 122 |
let delta = target - current;
|
| 123 |
delta = ((delta + 180) % 360 + 360) % 360 - 180;
|
|
|
|
| 129 |
if (!orbitCam) return;
|
| 130 |
|
| 131 |
const targetPos = tooltipEnt.getPosition().clone();
|
| 132 |
+
const startPivot = orbitCam.pivotPoint.clone();
|
| 133 |
+
const startYaw = orbitCam._yaw;
|
| 134 |
+
const startPitch = orbitCam._pitch;
|
| 135 |
+
const startDist = orbitCam._distance;
|
| 136 |
|
| 137 |
+
const worldRadius = 0.5 * tooltipEnt.getLocalScale().x;
|
| 138 |
const minZoom = orbitCam.distanceMin;
|
| 139 |
const desiredDistance = Math.max(minZoom * 1.2, worldRadius * 4);
|
| 140 |
|
|
|
|
| 159 |
|
| 160 |
tempEnt.destroy();
|
| 161 |
|
| 162 |
+
const endPivot = targetPos.clone();
|
| 163 |
+
const endDist = desiredDistance;
|
| 164 |
|
| 165 |
let elapsed = 0;
|
| 166 |
const orgPivot = startPivot.clone();
|
| 167 |
+
const orgYaw = startYaw;
|
| 168 |
const orgPitch = startPitch;
|
| 169 |
+
const orgDist = startDist;
|
| 170 |
|
| 171 |
if (currentTween) {
|
| 172 |
app.off("update", currentTween);
|
|
|
|
| 180 |
const newPivot = new pc.Vec3().lerp(orgPivot, endPivot, t);
|
| 181 |
orbitCam.pivotPoint.copy(newPivot);
|
| 182 |
|
| 183 |
+
const newYaw = pc.math.lerp(orgYaw, endYaw, t);
|
| 184 |
const newPitch = pc.math.lerp(orgPitch, endPitch, t);
|
| 185 |
+
const newDist = pc.math.lerp(orgDist, endDist, t);
|
| 186 |
|
| 187 |
+
orbitCam._targetYaw = newYaw;
|
| 188 |
+
orbitCam._yaw = newYaw;
|
| 189 |
+
orbitCam._targetPitch = newPitch;
|
| 190 |
+
orbitCam._pitch = newPitch;
|
| 191 |
orbitCam._targetDistance = newDist;
|
| 192 |
+
orbitCam._distance = newDist;
|
| 193 |
|
| 194 |
orbitCam._updatePosition();
|
| 195 |
|