@popaya/pgsg-viewer 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-LFICZTG7.js → chunk-Q2W7KVNK.js} +2 -2
- package/dist/core/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{pgsg-three-viewer-5BUDBGSE.js → pgsg-three-viewer-B5AH6DJO.js} +166 -11
- package/dist/pgsg-three-viewer-B5AH6DJO.js.map +1 -0
- package/dist/react/index.js +182 -95
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/pgsg-three-viewer-5BUDBGSE.js.map +0 -1
- /package/dist/{chunk-LFICZTG7.js.map → chunk-Q2W7KVNK.js.map} +0 -0
|
@@ -10,7 +10,7 @@ var PGSGViewer = class {
|
|
|
10
10
|
const { PGSGPlayCanvasViewer } = await import("./pgsg-playcanvas-viewer-4WORM4WU.js");
|
|
11
11
|
this.engine = new PGSGPlayCanvasViewer(this.options);
|
|
12
12
|
} else {
|
|
13
|
-
const { PGSGThreeViewer } = await import("./pgsg-three-viewer-
|
|
13
|
+
const { PGSGThreeViewer } = await import("./pgsg-three-viewer-B5AH6DJO.js");
|
|
14
14
|
this.engine = new PGSGThreeViewer(this.options);
|
|
15
15
|
}
|
|
16
16
|
await this.engine.load();
|
|
@@ -45,4 +45,4 @@ var PGSGViewer = class {
|
|
|
45
45
|
export {
|
|
46
46
|
PGSGViewer
|
|
47
47
|
};
|
|
48
|
-
//# sourceMappingURL=chunk-
|
|
48
|
+
//# sourceMappingURL=chunk-Q2W7KVNK.js.map
|
package/dist/core/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// src/viewers/three/pgsg-three-viewer.ts
|
|
2
2
|
import * as THREE5 from "three";
|
|
3
|
-
import { GLTFLoader } from "three/
|
|
4
|
-
import { TransformControls } from "three/
|
|
3
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
4
|
+
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
|
|
5
|
+
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
|
|
6
|
+
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
|
|
7
|
+
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
|
|
8
|
+
import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
|
|
5
9
|
import * as RAPIER2 from "@dimforge/rapier3d-compat";
|
|
6
10
|
import nipplejs from "nipplejs";
|
|
7
11
|
|
|
@@ -294,6 +298,7 @@ var OrbitCameraController = class {
|
|
|
294
298
|
lastTouchY = 0;
|
|
295
299
|
externalMove = new THREE2.Vector2(0, 0);
|
|
296
300
|
moveSpeed = 5;
|
|
301
|
+
enabled = true;
|
|
297
302
|
constructor(camera, dom, opts) {
|
|
298
303
|
this.camera = camera;
|
|
299
304
|
this.dom = dom;
|
|
@@ -371,6 +376,7 @@ var OrbitCameraController = class {
|
|
|
371
376
|
// Input
|
|
372
377
|
// -----------------------------
|
|
373
378
|
onMouseDown = (e) => {
|
|
379
|
+
if (!this.enabled) return;
|
|
374
380
|
if (e.button === 0) {
|
|
375
381
|
this.dragging = true;
|
|
376
382
|
} else if (e.button === 2 || e.button === 1) {
|
|
@@ -384,6 +390,7 @@ var OrbitCameraController = class {
|
|
|
384
390
|
this.panning = false;
|
|
385
391
|
};
|
|
386
392
|
onMouseMove = (e) => {
|
|
393
|
+
if (!this.enabled) return;
|
|
387
394
|
if (!this.dragging && !this.panning) return;
|
|
388
395
|
const dx = e.clientX - this.lastX;
|
|
389
396
|
const dy = e.clientY - this.lastY;
|
|
@@ -412,6 +419,7 @@ var OrbitCameraController = class {
|
|
|
412
419
|
}
|
|
413
420
|
};
|
|
414
421
|
onWheel = (e) => {
|
|
422
|
+
if (!this.enabled) return;
|
|
415
423
|
e.preventDefault();
|
|
416
424
|
const zoomFactor = Math.pow(this.zoomSpeed, e.deltaY / 100);
|
|
417
425
|
this.distance *= zoomFactor;
|
|
@@ -423,11 +431,13 @@ var OrbitCameraController = class {
|
|
|
423
431
|
this.updateCamera();
|
|
424
432
|
};
|
|
425
433
|
onTouchStart = (e) => {
|
|
434
|
+
if (!this.enabled) return;
|
|
426
435
|
const t = e.touches[0];
|
|
427
436
|
this.lastTouchX = t.clientX;
|
|
428
437
|
this.lastTouchY = t.clientY;
|
|
429
438
|
};
|
|
430
439
|
onTouchMove = (e) => {
|
|
440
|
+
if (!this.enabled) return;
|
|
431
441
|
const t = e.touches[0];
|
|
432
442
|
const deltaX = t.clientX - this.lastTouchX;
|
|
433
443
|
const deltaY = t.clientY - this.lastTouchY;
|
|
@@ -1006,6 +1016,14 @@ var PGSGThreeViewer = class {
|
|
|
1006
1016
|
placementRotation = 0;
|
|
1007
1017
|
transformControls;
|
|
1008
1018
|
inputEnabled = true;
|
|
1019
|
+
placementMouseMoved = false;
|
|
1020
|
+
placedObjects = [];
|
|
1021
|
+
ghostYOffset = 0;
|
|
1022
|
+
composer;
|
|
1023
|
+
hoverOutline;
|
|
1024
|
+
selectOutline;
|
|
1025
|
+
selectedObject;
|
|
1026
|
+
hoveredObject;
|
|
1009
1027
|
container;
|
|
1010
1028
|
resizeObserver = null;
|
|
1011
1029
|
controls;
|
|
@@ -1032,21 +1050,28 @@ var PGSGThreeViewer = class {
|
|
|
1032
1050
|
this.initRenderer();
|
|
1033
1051
|
this.initCamera();
|
|
1034
1052
|
this.initScene();
|
|
1053
|
+
this.initPostProcessing();
|
|
1035
1054
|
this.bindResize();
|
|
1036
1055
|
this.resize();
|
|
1037
1056
|
this.transformControls = new TransformControls(
|
|
1038
1057
|
this.camera,
|
|
1039
1058
|
this.renderer.domElement
|
|
1040
1059
|
);
|
|
1041
|
-
this.scene.add(this.transformControls);
|
|
1042
|
-
console.log(this.transformControls instanceof THREE5.Object3D);
|
|
1060
|
+
this.scene.add(this.transformControls.getHelper());
|
|
1061
|
+
console.log(this.transformControls.getHelper() instanceof THREE5.Object3D);
|
|
1043
1062
|
this.transformControls.addEventListener("dragging-changed", (event) => {
|
|
1044
1063
|
if (!this.controls) return;
|
|
1045
1064
|
this.controls.enabled = !event.value;
|
|
1046
1065
|
});
|
|
1047
1066
|
this.transformControls.addEventListener("mouseDown", () => {
|
|
1048
1067
|
document.exitPointerLock?.();
|
|
1068
|
+
this.controls.enabled = false;
|
|
1049
1069
|
});
|
|
1070
|
+
this.transformControls.addEventListener("mouseUp", () => {
|
|
1071
|
+
this.controls.enabled = true;
|
|
1072
|
+
});
|
|
1073
|
+
this.transformControls.setSize(0.8);
|
|
1074
|
+
this.transformControls.setSpace("world");
|
|
1050
1075
|
await RAPIER2.init();
|
|
1051
1076
|
this.world = new RAPIER2.World({
|
|
1052
1077
|
x: 0,
|
|
@@ -1080,7 +1105,20 @@ var PGSGThreeViewer = class {
|
|
|
1080
1105
|
if (e.key === "t") this.transformControls.setMode("translate");
|
|
1081
1106
|
if (e.key === "s") this.transformControls.setMode("scale");
|
|
1082
1107
|
});
|
|
1083
|
-
this.renderer.domElement.addEventListener("
|
|
1108
|
+
this.renderer.domElement.addEventListener("mousedown", () => {
|
|
1109
|
+
this.placementMouseMoved = false;
|
|
1110
|
+
});
|
|
1111
|
+
this.renderer.domElement.addEventListener("mousemove", () => {
|
|
1112
|
+
this.placementMouseMoved = true;
|
|
1113
|
+
});
|
|
1114
|
+
this.renderer.domElement.addEventListener("mouseup", (e) => {
|
|
1115
|
+
if (!this.placementMouseMoved) {
|
|
1116
|
+
this.onSceneClick(e);
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
this.renderer.domElement.addEventListener("click", this.onSelectObject);
|
|
1120
|
+
this.renderer.domElement.addEventListener("mousemove", this.onHoverObject);
|
|
1121
|
+
window.addEventListener("keydown", this.onDeleteObject);
|
|
1084
1122
|
}
|
|
1085
1123
|
start() {
|
|
1086
1124
|
if (this.running) return;
|
|
@@ -1096,7 +1134,7 @@ var PGSGThreeViewer = class {
|
|
|
1096
1134
|
this.acc -= this.fixedDt;
|
|
1097
1135
|
}
|
|
1098
1136
|
this.controls?.update?.(delta);
|
|
1099
|
-
this.
|
|
1137
|
+
this.composer.render();
|
|
1100
1138
|
});
|
|
1101
1139
|
}
|
|
1102
1140
|
pause() {
|
|
@@ -1107,6 +1145,9 @@ var PGSGThreeViewer = class {
|
|
|
1107
1145
|
const w = Math.max(1, this.container.clientWidth);
|
|
1108
1146
|
const h = Math.max(1, this.container.clientHeight);
|
|
1109
1147
|
this.renderer.setSize(w, h);
|
|
1148
|
+
this.composer?.setSize(w, h);
|
|
1149
|
+
this.hoverOutline?.setSize(w, h);
|
|
1150
|
+
this.selectOutline?.setSize(w, h);
|
|
1110
1151
|
this.camera.aspect = w / h;
|
|
1111
1152
|
this.camera.updateProjectionMatrix();
|
|
1112
1153
|
}
|
|
@@ -1168,6 +1209,7 @@ var PGSGThreeViewer = class {
|
|
|
1168
1209
|
this.pendingPlacementUrl = url;
|
|
1169
1210
|
this.placementRotation = 0;
|
|
1170
1211
|
console.log("[PGSG Viewer] Placement mode enabled");
|
|
1212
|
+
this.controls.enabled = false;
|
|
1171
1213
|
const gltf = await this.gltfLoader.loadAsync(url);
|
|
1172
1214
|
this.ghostModel = gltf.scene;
|
|
1173
1215
|
const box = new THREE5.Box3().setFromObject(this.ghostModel);
|
|
@@ -1188,8 +1230,17 @@ var PGSGThreeViewer = class {
|
|
|
1188
1230
|
this.onPlacementMove
|
|
1189
1231
|
);
|
|
1190
1232
|
this.renderer.domElement.addEventListener("wheel", this.onPlacementWheel);
|
|
1191
|
-
this.renderer.domElement.addEventListener("click", this.onSceneClick);
|
|
1192
1233
|
window.addEventListener("keydown", this.onPlacementCancel);
|
|
1234
|
+
const rect = this.renderer.domElement.getBoundingClientRect();
|
|
1235
|
+
this.mouse.set(0, 0);
|
|
1236
|
+
this.raycaster.setFromCamera(this.mouse, this.camera);
|
|
1237
|
+
const intersects = this.raycaster.intersectObjects(
|
|
1238
|
+
this.colliderMeshes,
|
|
1239
|
+
true
|
|
1240
|
+
);
|
|
1241
|
+
if (intersects.length) {
|
|
1242
|
+
this.ghostModel.position.copy(intersects[0].point);
|
|
1243
|
+
}
|
|
1193
1244
|
}
|
|
1194
1245
|
async addModelFromUrl(url, position) {
|
|
1195
1246
|
return new Promise((resolve, reject) => {
|
|
@@ -1238,14 +1289,21 @@ var PGSGThreeViewer = class {
|
|
|
1238
1289
|
this.renderer.setPixelRatio(
|
|
1239
1290
|
this.options.renderer?.pixelRatio ?? window.devicePixelRatio
|
|
1240
1291
|
);
|
|
1292
|
+
this.renderer.toneMapping = THREE5.ACESFilmicToneMapping;
|
|
1293
|
+
this.renderer.toneMappingExposure = 1.2;
|
|
1241
1294
|
this.renderer.localClippingEnabled = true;
|
|
1242
1295
|
this.container.appendChild(this.renderer.domElement);
|
|
1243
1296
|
}
|
|
1244
1297
|
initScene() {
|
|
1245
1298
|
this.scene = new THREE5.Scene();
|
|
1246
1299
|
this.scene.background = new THREE5.Color(1118481);
|
|
1247
|
-
const
|
|
1248
|
-
this.scene.add(
|
|
1300
|
+
const hemi = new THREE5.HemisphereLight(16777215, 4473924, 1.2);
|
|
1301
|
+
this.scene.add(hemi);
|
|
1302
|
+
const dir = new THREE5.DirectionalLight(16777215, 2.5);
|
|
1303
|
+
dir.position.set(5, 10, 5);
|
|
1304
|
+
this.scene.add(dir);
|
|
1305
|
+
const amb = new THREE5.AmbientLight(16777215, 0.35);
|
|
1306
|
+
this.scene.add(amb);
|
|
1249
1307
|
}
|
|
1250
1308
|
initCamera() {
|
|
1251
1309
|
this.camera = new THREE5.PerspectiveCamera(
|
|
@@ -1257,6 +1315,31 @@ var PGSGThreeViewer = class {
|
|
|
1257
1315
|
this.camera.position.set(2, 2, 5);
|
|
1258
1316
|
this.camera.lookAt(0, 0, 0);
|
|
1259
1317
|
}
|
|
1318
|
+
initPostProcessing() {
|
|
1319
|
+
this.composer = new EffectComposer(this.renderer);
|
|
1320
|
+
this.composer.addPass(new RenderPass(this.scene, this.camera));
|
|
1321
|
+
const size = new THREE5.Vector2(
|
|
1322
|
+
this.container.clientWidth,
|
|
1323
|
+
this.container.clientHeight
|
|
1324
|
+
);
|
|
1325
|
+
this.hoverOutline = new OutlinePass(size, this.scene, this.camera);
|
|
1326
|
+
this.hoverOutline.edgeStrength = 6;
|
|
1327
|
+
this.hoverOutline.edgeGlow = 1;
|
|
1328
|
+
this.hoverOutline.edgeThickness = 2;
|
|
1329
|
+
this.hoverOutline.pulsePeriod = 0;
|
|
1330
|
+
this.hoverOutline.visibleEdgeColor.set("#00e5ff");
|
|
1331
|
+
this.hoverOutline.hiddenEdgeColor.set("#00e5ff");
|
|
1332
|
+
this.composer.addPass(this.hoverOutline);
|
|
1333
|
+
this.selectOutline = new OutlinePass(size, this.scene, this.camera);
|
|
1334
|
+
this.selectOutline.edgeStrength = 8;
|
|
1335
|
+
this.selectOutline.edgeGlow = 1.2;
|
|
1336
|
+
this.selectOutline.edgeThickness = 2.5;
|
|
1337
|
+
this.selectOutline.pulsePeriod = 0;
|
|
1338
|
+
this.selectOutline.visibleEdgeColor.set("#ffd400");
|
|
1339
|
+
this.selectOutline.hiddenEdgeColor.set("#ffd400");
|
|
1340
|
+
this.composer.addPass(this.selectOutline);
|
|
1341
|
+
this.composer.addPass(new OutputPass());
|
|
1342
|
+
}
|
|
1260
1343
|
bindResize() {
|
|
1261
1344
|
this.resizeObserver?.disconnect();
|
|
1262
1345
|
this.resizeObserver = new ResizeObserver(() => this.resize());
|
|
@@ -1489,16 +1572,21 @@ var PGSGThreeViewer = class {
|
|
|
1489
1572
|
return hits;
|
|
1490
1573
|
}
|
|
1491
1574
|
onSceneClick = async (event) => {
|
|
1575
|
+
if (this.placementMouseMoved) return;
|
|
1492
1576
|
if (!this.pendingPlacementUrl || !this.ghostModel) return;
|
|
1493
1577
|
const position = this.ghostModel.position.clone();
|
|
1494
1578
|
const placed = await this.addModelFromUrl(
|
|
1495
1579
|
this.pendingPlacementUrl,
|
|
1496
1580
|
position
|
|
1497
1581
|
);
|
|
1582
|
+
if (placed) {
|
|
1583
|
+
this.placedObjects.push(placed);
|
|
1584
|
+
}
|
|
1498
1585
|
if (placed && this.transformControls) {
|
|
1499
1586
|
placed.rotation.y = this.placementRotation;
|
|
1500
1587
|
this.transformControls.attach(placed);
|
|
1501
1588
|
}
|
|
1589
|
+
this.controls.enabled = true;
|
|
1502
1590
|
this.scene.remove(this.ghostModel);
|
|
1503
1591
|
this.ghostModel = void 0;
|
|
1504
1592
|
this.pendingPlacementUrl = void 0;
|
|
@@ -1510,7 +1598,6 @@ var PGSGThreeViewer = class {
|
|
|
1510
1598
|
"wheel",
|
|
1511
1599
|
this.onPlacementWheel
|
|
1512
1600
|
);
|
|
1513
|
-
this.renderer.domElement.removeEventListener("click", this.onSceneClick);
|
|
1514
1601
|
window.removeEventListener("keydown", this.onPlacementCancel);
|
|
1515
1602
|
};
|
|
1516
1603
|
onPlacementMove = (event) => {
|
|
@@ -1527,7 +1614,10 @@ var PGSGThreeViewer = class {
|
|
|
1527
1614
|
);
|
|
1528
1615
|
if (!intersects.length) return;
|
|
1529
1616
|
const hit = intersects[0];
|
|
1617
|
+
const box = new THREE5.Box3().setFromObject(this.ghostModel);
|
|
1618
|
+
this.ghostYOffset = -box.min.y;
|
|
1530
1619
|
this.ghostModel.position.copy(hit.point);
|
|
1620
|
+
this.ghostModel.position.y += this.ghostYOffset;
|
|
1531
1621
|
if (hit.face) {
|
|
1532
1622
|
const normal = this.getWorldNormalSafe(hit);
|
|
1533
1623
|
if (normal) {
|
|
@@ -1538,6 +1628,8 @@ var PGSGThreeViewer = class {
|
|
|
1538
1628
|
}
|
|
1539
1629
|
};
|
|
1540
1630
|
onPlacementWheel = (event) => {
|
|
1631
|
+
event.preventDefault();
|
|
1632
|
+
event.stopPropagation();
|
|
1541
1633
|
if (!this.ghostModel) return;
|
|
1542
1634
|
event.preventDefault();
|
|
1543
1635
|
const step = Math.PI / 12;
|
|
@@ -1567,8 +1659,71 @@ var PGSGThreeViewer = class {
|
|
|
1567
1659
|
);
|
|
1568
1660
|
window.removeEventListener("keydown", this.onPlacementCancel);
|
|
1569
1661
|
};
|
|
1662
|
+
onSelectObject = (event) => {
|
|
1663
|
+
if (this.pendingPlacementUrl) return;
|
|
1664
|
+
if (this.transformControls?.dragging) return;
|
|
1665
|
+
const rect = this.renderer.domElement.getBoundingClientRect();
|
|
1666
|
+
this.mouse.set(
|
|
1667
|
+
(event.clientX - rect.left) / rect.width * 2 - 1,
|
|
1668
|
+
-((event.clientY - rect.top) / rect.height) * 2 + 1
|
|
1669
|
+
);
|
|
1670
|
+
this.raycaster.setFromCamera(this.mouse, this.camera);
|
|
1671
|
+
const hits = this.raycaster.intersectObjects(this.placedObjects, true);
|
|
1672
|
+
if (!hits.length) {
|
|
1673
|
+
this.selectedObject = void 0;
|
|
1674
|
+
this.transformControls?.detach();
|
|
1675
|
+
this.selectOutline.selectedObjects = [];
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
let root = hits[0].object;
|
|
1679
|
+
while (root && !this.placedObjects.includes(root)) root = root.parent;
|
|
1680
|
+
if (!root) return;
|
|
1681
|
+
this.selectedObject = root;
|
|
1682
|
+
this.transformControls?.attach(root);
|
|
1683
|
+
this.selectOutline.selectedObjects = [root];
|
|
1684
|
+
};
|
|
1685
|
+
onHoverObject = (event) => {
|
|
1686
|
+
if (this.pendingPlacementUrl) return;
|
|
1687
|
+
if (this.transformControls?.dragging) return;
|
|
1688
|
+
const rect = this.renderer.domElement.getBoundingClientRect();
|
|
1689
|
+
this.mouse.set(
|
|
1690
|
+
(event.clientX - rect.left) / rect.width * 2 - 1,
|
|
1691
|
+
-((event.clientY - rect.top) / rect.height) * 2 + 1
|
|
1692
|
+
);
|
|
1693
|
+
this.raycaster.setFromCamera(this.mouse, this.camera);
|
|
1694
|
+
const hits = this.raycaster.intersectObjects(this.placedObjects, true);
|
|
1695
|
+
if (!hits.length) {
|
|
1696
|
+
this.hoveredObject = void 0;
|
|
1697
|
+
this.hoverOutline.selectedObjects = [];
|
|
1698
|
+
this.renderer.domElement.style.cursor = "default";
|
|
1699
|
+
return;
|
|
1700
|
+
}
|
|
1701
|
+
let root = hits[0].object;
|
|
1702
|
+
while (root && !this.placedObjects.includes(root)) root = root.parent;
|
|
1703
|
+
if (!root) return;
|
|
1704
|
+
if (root !== this.hoveredObject) {
|
|
1705
|
+
this.hoveredObject = root;
|
|
1706
|
+
this.hoverOutline.selectedObjects = [root];
|
|
1707
|
+
this.renderer.domElement.style.cursor = "pointer";
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
1710
|
+
onDeleteObject = (event) => {
|
|
1711
|
+
const tag = event.target?.tagName?.toLowerCase();
|
|
1712
|
+
if (tag === "input" || tag === "textarea") return;
|
|
1713
|
+
if (event.key !== "Delete" && event.key !== "Backspace") return;
|
|
1714
|
+
if (!this.selectedObject) return;
|
|
1715
|
+
event.preventDefault();
|
|
1716
|
+
this.selectedObject.parent?.remove(this.selectedObject);
|
|
1717
|
+
this.placedObjects = this.placedObjects.filter(
|
|
1718
|
+
(o) => o !== this.selectedObject
|
|
1719
|
+
);
|
|
1720
|
+
this.transformControls?.detach();
|
|
1721
|
+
this.selectOutline.selectedObjects = [];
|
|
1722
|
+
this.hoverOutline.selectedObjects = [];
|
|
1723
|
+
this.selectedObject = void 0;
|
|
1724
|
+
};
|
|
1570
1725
|
};
|
|
1571
1726
|
export {
|
|
1572
1727
|
PGSGThreeViewer
|
|
1573
1728
|
};
|
|
1574
|
-
//# sourceMappingURL=pgsg-three-viewer-
|
|
1729
|
+
//# sourceMappingURL=pgsg-three-viewer-B5AH6DJO.js.map
|