@almadar/ui 5.140.0 → 5.142.0
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/avl/index.cjs +1380 -1226
- package/dist/avl/index.js +409 -255
- package/dist/{avl-schema-parser-B8Onmfsu.d.cts → avl-schema-parser-DAs12kxP.d.ts} +229 -2
- package/dist/{avl-schema-parser-B8Onmfsu.d.ts → avl-schema-parser-wOkfbwAh.d.cts} +229 -2
- package/dist/{cn-Do5Ra3l3.d.ts → cn-BDwC4QpH.d.ts} +1 -1
- package/dist/{cn-DkGYzPOg.d.cts → cn-rwc3svaX.d.cts} +1 -1
- package/dist/components/index.cjs +1364 -1210
- package/dist/components/index.d.cts +13 -6
- package/dist/components/index.d.ts +13 -6
- package/dist/components/index.js +400 -246
- package/dist/lib/drawable/three/index.cjs +542 -154
- package/dist/lib/drawable/three/index.d.cts +14 -171
- package/dist/lib/drawable/three/index.d.ts +14 -171
- package/dist/lib/drawable/three/index.js +518 -130
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/{paintDispatch-B5pPeSEp.d.cts → paintDispatch-BQn5Lyx1.d.cts} +160 -3
- package/dist/{paintDispatch-B5pPeSEp.d.ts → paintDispatch-BQn5Lyx1.d.ts} +160 -3
- package/dist/providers/index.cjs +1263 -1109
- package/dist/providers/index.js +384 -230
- package/dist/runtime/index.cjs +1241 -1087
- package/dist/runtime/index.js +389 -235
- package/package.json +4 -4
|
@@ -4,9 +4,11 @@ var React3 = require('react');
|
|
|
4
4
|
var providers = require('@almadar/ui/providers');
|
|
5
5
|
var logger = require('@almadar/logger');
|
|
6
6
|
var fiber = require('@react-three/fiber');
|
|
7
|
-
var
|
|
7
|
+
var THREE10 = require('three');
|
|
8
|
+
var RoomEnvironment_js = require('three/examples/jsm/environments/RoomEnvironment.js');
|
|
8
9
|
var drei = require('@react-three/drei');
|
|
9
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
var postprocessing = require('@react-three/postprocessing');
|
|
10
12
|
var GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader');
|
|
11
13
|
var SkeletonUtils = require('three/examples/jsm/utils/SkeletonUtils');
|
|
12
14
|
var clsx = require('clsx');
|
|
@@ -14,7 +16,6 @@ var tailwindMerge = require('tailwind-merge');
|
|
|
14
16
|
var OrbitControls_js = require('three/examples/jsm/controls/OrbitControls.js');
|
|
15
17
|
var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
|
|
16
18
|
var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
17
|
-
var postprocessing = require('@react-three/postprocessing');
|
|
18
19
|
var hooks = require('@almadar/ui/hooks');
|
|
19
20
|
|
|
20
21
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -38,7 +39,7 @@ function _interopNamespace(e) {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
var React3__default = /*#__PURE__*/_interopDefault(React3);
|
|
41
|
-
var
|
|
42
|
+
var THREE10__namespace = /*#__PURE__*/_interopNamespace(THREE10);
|
|
42
43
|
|
|
43
44
|
var __defProp = Object.defineProperty;
|
|
44
45
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -189,6 +190,7 @@ function collectDrawnItems(nodes) {
|
|
|
189
190
|
case "draw-shape":
|
|
190
191
|
case "draw-text":
|
|
191
192
|
case "draw-group":
|
|
193
|
+
case "draw-mesh":
|
|
192
194
|
if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
|
|
193
195
|
break;
|
|
194
196
|
case "draw-sprite-layer":
|
|
@@ -473,6 +475,10 @@ function Lighting3D({
|
|
|
473
475
|
directionalIntensity = 0.8,
|
|
474
476
|
directionalColor = "#ffffff",
|
|
475
477
|
directionalPosition = [10, 20, 10],
|
|
478
|
+
hemisphereIntensity = 0.3,
|
|
479
|
+
hemisphereColor = "#87ceeb",
|
|
480
|
+
hemisphereGroundColor = "#362d1d",
|
|
481
|
+
points,
|
|
476
482
|
shadows = true,
|
|
477
483
|
shadowMapSize = 2048,
|
|
478
484
|
shadowCameraSize = 20,
|
|
@@ -505,22 +511,63 @@ function Lighting3D({
|
|
|
505
511
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
506
512
|
"hemisphereLight",
|
|
507
513
|
{
|
|
508
|
-
intensity:
|
|
509
|
-
color:
|
|
510
|
-
groundColor:
|
|
514
|
+
intensity: hemisphereIntensity,
|
|
515
|
+
color: hemisphereColor,
|
|
516
|
+
groundColor: hemisphereGroundColor
|
|
511
517
|
}
|
|
512
518
|
),
|
|
519
|
+
points?.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
520
|
+
"pointLight",
|
|
521
|
+
{
|
|
522
|
+
position: p.position,
|
|
523
|
+
intensity: p.intensity,
|
|
524
|
+
color: p.color,
|
|
525
|
+
distance: p.distance,
|
|
526
|
+
decay: p.decay
|
|
527
|
+
},
|
|
528
|
+
i
|
|
529
|
+
)),
|
|
513
530
|
showHelpers && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
514
531
|
"directionalLightHelper",
|
|
515
532
|
{
|
|
516
533
|
args: [
|
|
517
|
-
new
|
|
534
|
+
new THREE10__namespace.DirectionalLight(directionalColor, directionalIntensity),
|
|
518
535
|
5
|
|
519
536
|
]
|
|
520
537
|
}
|
|
521
538
|
) })
|
|
522
539
|
] });
|
|
523
540
|
}
|
|
541
|
+
function Effects3D({ post }) {
|
|
542
|
+
if (!post || !post.bloom && !post.vignette) return null;
|
|
543
|
+
const passes = [];
|
|
544
|
+
if (post.bloom) {
|
|
545
|
+
passes.push(
|
|
546
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
547
|
+
postprocessing.Bloom,
|
|
548
|
+
{
|
|
549
|
+
intensity: post.bloom.intensity ?? 1,
|
|
550
|
+
luminanceThreshold: post.bloom.threshold ?? 0.9,
|
|
551
|
+
luminanceSmoothing: post.bloom.smoothing ?? 0.3
|
|
552
|
+
},
|
|
553
|
+
"bloom"
|
|
554
|
+
)
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
if (post.vignette) {
|
|
558
|
+
passes.push(
|
|
559
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
560
|
+
postprocessing.Vignette,
|
|
561
|
+
{
|
|
562
|
+
offset: post.vignette.offset ?? 0.3,
|
|
563
|
+
darkness: post.vignette.darkness ?? 0.6
|
|
564
|
+
},
|
|
565
|
+
"vignette"
|
|
566
|
+
)
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
return /* @__PURE__ */ jsxRuntime.jsx(postprocessing.EffectComposer, { children: passes });
|
|
570
|
+
}
|
|
524
571
|
function CameraController3D({
|
|
525
572
|
onCameraChange
|
|
526
573
|
}) {
|
|
@@ -541,8 +588,8 @@ function FollowCamera3D({
|
|
|
541
588
|
offset
|
|
542
589
|
}) {
|
|
543
590
|
const { camera } = fiber.useThree();
|
|
544
|
-
const look = React3.useRef(new
|
|
545
|
-
const goal = React3.useRef(new
|
|
591
|
+
const look = React3.useRef(new THREE10__namespace.Vector3(target[0], target[1], target[2]));
|
|
592
|
+
const goal = React3.useRef(new THREE10__namespace.Vector3());
|
|
546
593
|
fiber.useFrame((_, delta) => {
|
|
547
594
|
const t = Math.min(1, delta * 5);
|
|
548
595
|
goal.current.set(target[0] + offset[0], target[1] + offset[1], target[2] + offset[2]);
|
|
@@ -553,6 +600,88 @@ function FollowCamera3D({
|
|
|
553
600
|
return null;
|
|
554
601
|
}
|
|
555
602
|
|
|
603
|
+
// lib/drawable/projector3d.ts
|
|
604
|
+
function create3DProjector(opts = {}) {
|
|
605
|
+
const cellSize = opts.cellSize ?? 1;
|
|
606
|
+
const offsetX = opts.offsetX ?? 0;
|
|
607
|
+
const offsetZ = opts.offsetZ ?? 0;
|
|
608
|
+
return {
|
|
609
|
+
cellSize,
|
|
610
|
+
toWorld: (pos) => [pos.x * cellSize + offsetX, pos.z ?? 0, pos.y * cellSize + offsetZ]
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
var NUMERIC_TRACKS = [
|
|
614
|
+
"offsetX",
|
|
615
|
+
"offsetY",
|
|
616
|
+
"rotate",
|
|
617
|
+
"opacity",
|
|
618
|
+
"radiusX",
|
|
619
|
+
"radiusY",
|
|
620
|
+
"width",
|
|
621
|
+
"height",
|
|
622
|
+
"strokeWidth",
|
|
623
|
+
"strokeDashOffset",
|
|
624
|
+
"blur"
|
|
625
|
+
];
|
|
626
|
+
function isAnimatedShape(node) {
|
|
627
|
+
return Boolean(node.animation && node.animation.durationMs > 0 && node.animation.keyframes.length > 0);
|
|
628
|
+
}
|
|
629
|
+
var lerp = (a, b, k) => a + (b - a) * k;
|
|
630
|
+
function applyShapeAnimation(node, timeMs) {
|
|
631
|
+
const anim = node.animation;
|
|
632
|
+
if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return node;
|
|
633
|
+
const frames = [...anim.keyframes].sort((a, b) => a.at - b.at);
|
|
634
|
+
const cycle = timeMs / anim.durationMs;
|
|
635
|
+
const t = anim.loop === false ? Math.min(cycle, 1) : cycle - Math.floor(cycle);
|
|
636
|
+
const out = { ...node };
|
|
637
|
+
const trackValue = (key) => {
|
|
638
|
+
const defined = frames.filter((f) => f[key] !== void 0);
|
|
639
|
+
if (defined.length === 0) return void 0;
|
|
640
|
+
let prev;
|
|
641
|
+
let next;
|
|
642
|
+
for (const f of defined) {
|
|
643
|
+
if (f.at <= t) prev = f;
|
|
644
|
+
else if (!next) next = f;
|
|
645
|
+
}
|
|
646
|
+
if (!prev) return defined[0][key];
|
|
647
|
+
if (!next) return prev[key];
|
|
648
|
+
const span = next.at - prev.at;
|
|
649
|
+
const k = span > 0 ? (t - prev.at) / span : 1;
|
|
650
|
+
const a = prev[key];
|
|
651
|
+
const b = next[key];
|
|
652
|
+
if (typeof a === "number" && typeof b === "number") return lerp(a, b, k);
|
|
653
|
+
return a;
|
|
654
|
+
};
|
|
655
|
+
for (const key of NUMERIC_TRACKS) {
|
|
656
|
+
const v = trackValue(key);
|
|
657
|
+
if (v !== void 0) out[key] = v;
|
|
658
|
+
}
|
|
659
|
+
const fill = trackValue("fill");
|
|
660
|
+
if (fill !== void 0) out.fill = fill;
|
|
661
|
+
const stroke = trackValue("stroke");
|
|
662
|
+
if (stroke !== void 0) out.stroke = stroke;
|
|
663
|
+
const shadowFrames = frames.filter((f) => f.shadow !== void 0);
|
|
664
|
+
if (shadowFrames.length > 0) {
|
|
665
|
+
const sh = trackValue("shadow");
|
|
666
|
+
if (sh !== void 0) {
|
|
667
|
+
let prevSh;
|
|
668
|
+
let nextSh;
|
|
669
|
+
for (const f of shadowFrames) {
|
|
670
|
+
if (f.at <= t) prevSh = f;
|
|
671
|
+
else if (!nextSh) nextSh = f;
|
|
672
|
+
}
|
|
673
|
+
if (prevSh?.shadow && nextSh?.shadow) {
|
|
674
|
+
const span = nextSh.at - prevSh.at;
|
|
675
|
+
const k = span > 0 ? (t - prevSh.at) / span : 1;
|
|
676
|
+
out.shadow = { color: prevSh.shadow.color, blur: lerp(prevSh.shadow.blur, nextSh.shadow.blur, k) };
|
|
677
|
+
} else {
|
|
678
|
+
out.shadow = sh;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return out;
|
|
683
|
+
}
|
|
684
|
+
|
|
556
685
|
// lib/atlasSlice.ts
|
|
557
686
|
var atlasCache = /* @__PURE__ */ new Map();
|
|
558
687
|
function isTilesheet(a) {
|
|
@@ -687,12 +816,12 @@ function ModelLoader({
|
|
|
687
816
|
if (!loadedModel) return null;
|
|
688
817
|
const cloned = SkeletonUtils.clone(loadedModel);
|
|
689
818
|
cloned.updateMatrixWorld(true);
|
|
690
|
-
const tintColor = tint ? new
|
|
819
|
+
const tintColor = tint ? new THREE10__namespace.Color(tint) : null;
|
|
691
820
|
cloned.traverse((child) => {
|
|
692
|
-
if (child instanceof
|
|
821
|
+
if (child instanceof THREE10__namespace.Mesh) {
|
|
693
822
|
child.castShadow = castShadow;
|
|
694
823
|
child.receiveShadow = receiveShadow;
|
|
695
|
-
if (tintColor && child.material instanceof
|
|
824
|
+
if (tintColor && child.material instanceof THREE10__namespace.MeshStandardMaterial) {
|
|
696
825
|
const mat = child.material.clone();
|
|
697
826
|
mat.color.multiply(tintColor);
|
|
698
827
|
child.material = mat;
|
|
@@ -701,7 +830,7 @@ function ModelLoader({
|
|
|
701
830
|
});
|
|
702
831
|
return cloned;
|
|
703
832
|
}, [loadedModel, castShadow, receiveShadow, tint]);
|
|
704
|
-
const mixer = React3.useMemo(() => model ? new
|
|
833
|
+
const mixer = React3.useMemo(() => model ? new THREE10__namespace.AnimationMixer(model) : null, [model]);
|
|
705
834
|
React3.useEffect(() => {
|
|
706
835
|
if (!mixer || !animation || clips.length === 0) return;
|
|
707
836
|
const wanted = animation.toLowerCase();
|
|
@@ -718,8 +847,8 @@ function ModelLoader({
|
|
|
718
847
|
});
|
|
719
848
|
const normFactor = React3.useMemo(() => {
|
|
720
849
|
if (!model) return 1;
|
|
721
|
-
const box = new
|
|
722
|
-
const size = new
|
|
850
|
+
const box = new THREE10__namespace.Box3().setFromObject(model);
|
|
851
|
+
const size = new THREE10__namespace.Vector3();
|
|
723
852
|
box.getSize(size);
|
|
724
853
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
725
854
|
if (!Number.isFinite(maxDim) || maxDim < 0.05) return 1;
|
|
@@ -809,7 +938,7 @@ var warnUnsupported3d = (kind) => {
|
|
|
809
938
|
warnedUnsupported.add(kind);
|
|
810
939
|
mesh3dLog.warn("unsupported drawable kind on the 3D backend \u2014 skipped", { kind });
|
|
811
940
|
};
|
|
812
|
-
var CrossOriginTextureLoader = class extends
|
|
941
|
+
var CrossOriginTextureLoader = class extends THREE10__namespace.TextureLoader {
|
|
813
942
|
constructor() {
|
|
814
943
|
super();
|
|
815
944
|
this.crossOrigin = "anonymous";
|
|
@@ -827,7 +956,7 @@ function useBillboardTexture(url) {
|
|
|
827
956
|
url,
|
|
828
957
|
(texture) => {
|
|
829
958
|
if (!active) return;
|
|
830
|
-
texture.colorSpace =
|
|
959
|
+
texture.colorSpace = THREE10__namespace.SRGBColorSpace;
|
|
831
960
|
setState({ texture, error: false });
|
|
832
961
|
},
|
|
833
962
|
void 0,
|
|
@@ -859,7 +988,7 @@ function useAtlasFrame(asset) {
|
|
|
859
988
|
return { frame: { x: r.sx, y: r.sy, w: r.sw, h: r.sh }, ready: true };
|
|
860
989
|
}, [asset, tick]);
|
|
861
990
|
}
|
|
862
|
-
function SpriteBillboard({ node, world, cellSize = 1 }) {
|
|
991
|
+
function SpriteBillboard({ node, world, cellSize = 1, groupOpacity = 1 }) {
|
|
863
992
|
const { texture, error: textureError } = useBillboardTexture(node.asset.url);
|
|
864
993
|
const { frame: atlasFrame, ready: atlasReady } = useAtlasFrame(node.asset);
|
|
865
994
|
const frame = node.frame ?? atlasFrame;
|
|
@@ -880,7 +1009,7 @@ function SpriteBillboard({ node, world, cellSize = 1 }) {
|
|
|
880
1009
|
}, [texture, frame, node.height, node.width, anchor, cellSize]);
|
|
881
1010
|
const groundGeometry = React3__default.default.useMemo(() => {
|
|
882
1011
|
if (anchor !== "top-left" || !texture || !atlasReady) return null;
|
|
883
|
-
const g = new
|
|
1012
|
+
const g = new THREE10__namespace.PlaneGeometry(size.width, size.height);
|
|
884
1013
|
g.rotateX(-Math.PI / 2);
|
|
885
1014
|
return g;
|
|
886
1015
|
}, [anchor, texture, atlasReady, size.width, size.height]);
|
|
@@ -888,15 +1017,15 @@ function SpriteBillboard({ node, world, cellSize = 1 }) {
|
|
|
888
1017
|
if (anchor === "top-left") {
|
|
889
1018
|
return /* @__PURE__ */ jsxRuntime.jsx("group", { position: [world[0] + size.width / 2, 0.02, world[2] + size.height / 2], children: /* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
890
1019
|
/* @__PURE__ */ jsxRuntime.jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
891
|
-
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side:
|
|
1020
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE10__namespace.DoubleSide })
|
|
892
1021
|
] }) });
|
|
893
1022
|
}
|
|
894
1023
|
return /* @__PURE__ */ jsxRuntime.jsx("group", { position: [world[0], world[1] + size.height / 2, world[2]], children: /* @__PURE__ */ jsxRuntime.jsxs("mesh", { children: [
|
|
895
1024
|
/* @__PURE__ */ jsxRuntime.jsx("planeGeometry", { args: [size.width, size.height] }),
|
|
896
|
-
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side:
|
|
1025
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color: textureError ? 16729156 : 8947848, transparent: true, opacity: 0.6, side: THREE10__namespace.DoubleSide })
|
|
897
1026
|
] }) });
|
|
898
1027
|
}
|
|
899
|
-
texture.magFilter = texture.minFilter =
|
|
1028
|
+
texture.magFilter = texture.minFilter = THREE10__namespace.NearestFilter;
|
|
900
1029
|
texture.needsUpdate = true;
|
|
901
1030
|
if (frame) {
|
|
902
1031
|
texture.repeat.set(frame.w / size.imgW, frame.h / size.imgH);
|
|
@@ -909,8 +1038,8 @@ function SpriteBillboard({ node, world, cellSize = 1 }) {
|
|
|
909
1038
|
map: texture,
|
|
910
1039
|
transparent: true,
|
|
911
1040
|
alphaTest: 0.1,
|
|
912
|
-
side:
|
|
913
|
-
opacity: node.opacity ?? 1
|
|
1041
|
+
side: THREE10__namespace.DoubleSide,
|
|
1042
|
+
opacity: (node.opacity ?? 1) * groupOpacity
|
|
914
1043
|
}
|
|
915
1044
|
) }) });
|
|
916
1045
|
}
|
|
@@ -922,13 +1051,13 @@ function SpriteBillboard({ node, world, cellSize = 1 }) {
|
|
|
922
1051
|
map: texture,
|
|
923
1052
|
transparent: true,
|
|
924
1053
|
alphaTest: 0.1,
|
|
925
|
-
side:
|
|
1054
|
+
side: THREE10__namespace.DoubleSide,
|
|
926
1055
|
opacity: node.opacity ?? 1
|
|
927
1056
|
}
|
|
928
1057
|
)
|
|
929
1058
|
] }) });
|
|
930
1059
|
}
|
|
931
|
-
function Sprite3D({ node, projector }) {
|
|
1060
|
+
function Sprite3D({ node, projector, groupOpacity = 1 }) {
|
|
932
1061
|
const asset = node.asset;
|
|
933
1062
|
if (!asset?.url || !isValidScenePos(node.position)) return null;
|
|
934
1063
|
if (asset.dimension === "3d") {
|
|
@@ -942,7 +1071,7 @@ function Sprite3D({ node, projector }) {
|
|
|
942
1071
|
{
|
|
943
1072
|
url: asset.url,
|
|
944
1073
|
scale,
|
|
945
|
-
rotation: [0, node.rotation ?? 0, 0],
|
|
1074
|
+
rotation: [0, (node.rotation ?? 0) * 180 / Math.PI, 0],
|
|
946
1075
|
animation: node.animation,
|
|
947
1076
|
fallbackGeometry: "box",
|
|
948
1077
|
castShadow: true,
|
|
@@ -950,11 +1079,30 @@ function Sprite3D({ node, projector }) {
|
|
|
950
1079
|
}
|
|
951
1080
|
) });
|
|
952
1081
|
}
|
|
953
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SpriteBillboard, { node, world: projector.toWorld(node.position), cellSize: projector.cellSize });
|
|
1082
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SpriteBillboard, { node, world: projector.toWorld(node.position), cellSize: projector.cellSize, groupOpacity });
|
|
954
1083
|
}
|
|
955
|
-
function Shape3D({ node, projector }) {
|
|
956
|
-
|
|
957
|
-
const
|
|
1084
|
+
function Shape3D({ node, projector, groupOpacity = 1 }) {
|
|
1085
|
+
const groupRef = React3__default.default.useRef(null);
|
|
1086
|
+
const materialRef = React3__default.default.useRef(null);
|
|
1087
|
+
const animated = isAnimatedShape(node);
|
|
1088
|
+
const validPos = isValidScenePos(node.position);
|
|
1089
|
+
const world = validPos ? projector.toWorld(node.position) : [0, 0, 0];
|
|
1090
|
+
fiber.useFrame(({ clock }) => {
|
|
1091
|
+
if (!animated || !groupRef.current) return;
|
|
1092
|
+
const view = applyShapeAnimation(node, clock.elapsedTime * 1e3);
|
|
1093
|
+
groupRef.current.position.set(
|
|
1094
|
+
world[0] + (view.offsetX ?? 0) * projector.cellSize,
|
|
1095
|
+
world[1] + 0.02,
|
|
1096
|
+
world[2] + (view.offsetY ?? 0) * projector.cellSize
|
|
1097
|
+
);
|
|
1098
|
+
groupRef.current.rotation.y = -(view.rotate ?? 0);
|
|
1099
|
+
const mat = materialRef.current;
|
|
1100
|
+
if (mat) {
|
|
1101
|
+
mat.opacity = (view.opacity ?? node.opacity ?? 1) * groupOpacity;
|
|
1102
|
+
if (view.fill) mat.color.set(view.fill);
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
if (!validPos) return null;
|
|
958
1106
|
const color = node.fill ?? node.stroke ?? "#ffffff";
|
|
959
1107
|
let geometry;
|
|
960
1108
|
switch (node.shape) {
|
|
@@ -972,7 +1120,7 @@ function Shape3D({ node, projector }) {
|
|
|
972
1120
|
}
|
|
973
1121
|
case "poly": {
|
|
974
1122
|
if (!node.points || node.points.length === 0) return null;
|
|
975
|
-
const s = new
|
|
1123
|
+
const s = new THREE10__namespace.Shape();
|
|
976
1124
|
node.points.forEach((p, i) => {
|
|
977
1125
|
if (i === 0) s.moveTo(p.x, p.y);
|
|
978
1126
|
else s.lineTo(p.x, p.y);
|
|
@@ -988,12 +1136,12 @@ function Shape3D({ node, projector }) {
|
|
|
988
1136
|
default:
|
|
989
1137
|
return null;
|
|
990
1138
|
}
|
|
991
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1139
|
+
return /* @__PURE__ */ jsxRuntime.jsx("group", { ref: groupRef, position: [world[0], world[1] + 0.02, world[2]], children: /* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
992
1140
|
geometry,
|
|
993
|
-
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { color, transparent: true, opacity: node.opacity ?? 1, side:
|
|
994
|
-
] });
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { ref: materialRef, color, transparent: true, opacity: (node.opacity ?? 1) * groupOpacity, side: THREE10__namespace.DoubleSide })
|
|
1142
|
+
] }) });
|
|
995
1143
|
}
|
|
996
|
-
function Text3D({ node, projector }) {
|
|
1144
|
+
function Text3D({ node, projector, groupOpacity = 1 }) {
|
|
997
1145
|
if (!isValidScenePos(node.position)) return null;
|
|
998
1146
|
const world = projector.toWorld(node.position);
|
|
999
1147
|
return /* @__PURE__ */ jsxRuntime.jsx(drei.Billboard, { position: [world[0], world[1] + 1.2, world[2]], children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1005,41 +1153,252 @@ function Text3D({ node, projector }) {
|
|
|
1005
1153
|
anchorY: "middle",
|
|
1006
1154
|
outlineWidth: 0.02,
|
|
1007
1155
|
outlineColor: "#000000",
|
|
1156
|
+
fillOpacity: groupOpacity,
|
|
1157
|
+
outlineOpacity: groupOpacity,
|
|
1008
1158
|
children: node.text
|
|
1009
1159
|
}
|
|
1010
1160
|
) });
|
|
1011
1161
|
}
|
|
1012
|
-
|
|
1162
|
+
var MESH_SEGMENTS_DEFAULT = 24;
|
|
1163
|
+
function clampSegments(segments) {
|
|
1164
|
+
const s = segments ?? MESH_SEGMENTS_DEFAULT;
|
|
1165
|
+
return Math.min(64, Math.max(3, Math.round(s)));
|
|
1166
|
+
}
|
|
1167
|
+
function isAnimatedMesh(node) {
|
|
1168
|
+
return Boolean(node.animation && node.animation.durationMs > 0 && node.animation.keyframes.length > 0);
|
|
1169
|
+
}
|
|
1170
|
+
var lerp2 = (a, b, k) => a + (b - a) * k;
|
|
1171
|
+
var NUMERIC_TRACKS2 = [
|
|
1172
|
+
"offsetX",
|
|
1173
|
+
"offsetY",
|
|
1174
|
+
"offsetZ",
|
|
1175
|
+
"rotateX",
|
|
1176
|
+
"rotateY",
|
|
1177
|
+
"rotateZ",
|
|
1178
|
+
"scale",
|
|
1179
|
+
"opacity",
|
|
1180
|
+
"emissiveIntensity"
|
|
1181
|
+
];
|
|
1182
|
+
function applyMeshAnimation(node, timeMs) {
|
|
1183
|
+
const anim = node.animation;
|
|
1184
|
+
if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return null;
|
|
1185
|
+
const frames = [...anim.keyframes].sort((a, b) => a.at - b.at);
|
|
1186
|
+
const cycle = timeMs / anim.durationMs;
|
|
1187
|
+
const t = anim.loop === false ? Math.min(cycle, 1) : cycle - Math.floor(cycle);
|
|
1188
|
+
const trackValue = (key) => {
|
|
1189
|
+
const defined = frames.filter((f) => f[key] !== void 0);
|
|
1190
|
+
if (defined.length === 0) return void 0;
|
|
1191
|
+
let prev;
|
|
1192
|
+
let next;
|
|
1193
|
+
for (const f of defined) {
|
|
1194
|
+
if (f.at <= t) prev = f;
|
|
1195
|
+
else if (!next) next = f;
|
|
1196
|
+
}
|
|
1197
|
+
if (!prev) return defined[0][key];
|
|
1198
|
+
if (!next) return prev[key];
|
|
1199
|
+
const span = next.at - prev.at;
|
|
1200
|
+
const k = span > 0 ? (t - prev.at) / span : 1;
|
|
1201
|
+
const a = prev[key];
|
|
1202
|
+
const b = next[key];
|
|
1203
|
+
if (typeof a === "number" && typeof b === "number") return lerp2(a, b, k);
|
|
1204
|
+
return a;
|
|
1205
|
+
};
|
|
1206
|
+
const num = {};
|
|
1207
|
+
for (const key of NUMERIC_TRACKS2) {
|
|
1208
|
+
const v = trackValue(key);
|
|
1209
|
+
if (v !== void 0) num[key] = v;
|
|
1210
|
+
}
|
|
1211
|
+
return {
|
|
1212
|
+
offset: [num.offsetX ?? 0, num.offsetY ?? 0, num.offsetZ ?? 0],
|
|
1213
|
+
rotate: [num.rotateX ?? 0, num.rotateY ?? 0, num.rotateZ ?? 0],
|
|
1214
|
+
scale: num.scale ?? 1,
|
|
1215
|
+
opacity: num.opacity,
|
|
1216
|
+
emissiveIntensity: num.emissiveIntensity,
|
|
1217
|
+
color: trackValue("color"),
|
|
1218
|
+
emissive: trackValue("emissive")
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
function meshGeometry(node, cellSize) {
|
|
1222
|
+
const seg = clampSegments(node.segments);
|
|
1223
|
+
const r = (node.radius ?? 0.4) * cellSize;
|
|
1224
|
+
const w = (node.width ?? 1) * cellSize;
|
|
1225
|
+
const h = (node.height ?? 1) * cellSize;
|
|
1226
|
+
const d = (node.depth ?? node.width ?? 1) * cellSize;
|
|
1227
|
+
switch (node.shape) {
|
|
1228
|
+
case "box":
|
|
1229
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [w, h, d] }), lift: h / 2, size: Math.max(w, h, d) };
|
|
1230
|
+
case "sphere":
|
|
1231
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [r, seg, seg] }), lift: r, size: r * 2 };
|
|
1232
|
+
case "capsule":
|
|
1233
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("capsuleGeometry", { args: [r, h, Math.max(2, Math.round(seg / 2)), seg] }), lift: h / 2 + r, size: h + r * 2 };
|
|
1234
|
+
case "cylinder":
|
|
1235
|
+
return {
|
|
1236
|
+
element: /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [(node.radiusTop ?? node.radius ?? 0.4) * cellSize, (node.radiusBottom ?? node.radius ?? 0.4) * cellSize, h, seg] }),
|
|
1237
|
+
lift: h / 2,
|
|
1238
|
+
size: Math.max(h, r * 2)
|
|
1239
|
+
};
|
|
1240
|
+
case "cone":
|
|
1241
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("coneGeometry", { args: [r, h, seg] }), lift: h / 2, size: Math.max(h, r * 2) };
|
|
1242
|
+
case "torus": {
|
|
1243
|
+
const tube = (node.tube ?? (node.radius ?? 0.4) / 3) * cellSize;
|
|
1244
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [r, tube, Math.max(3, Math.round(seg / 2)), seg] }), lift: r + tube, size: (r + tube) * 2 };
|
|
1245
|
+
}
|
|
1246
|
+
case "plane":
|
|
1247
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("planeGeometry", { args: [w, d] }), lift: 0, size: Math.max(w, d) };
|
|
1248
|
+
case "circle":
|
|
1249
|
+
return { element: /* @__PURE__ */ jsxRuntime.jsx("circleGeometry", { args: [r, seg] }), lift: 0, size: r * 2 };
|
|
1250
|
+
default:
|
|
1251
|
+
return null;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
var SIDE_MAP = {
|
|
1255
|
+
front: THREE10__namespace.FrontSide,
|
|
1256
|
+
back: THREE10__namespace.BackSide,
|
|
1257
|
+
double: THREE10__namespace.DoubleSide
|
|
1258
|
+
};
|
|
1259
|
+
function meshMaterial(mat, opacity, ref) {
|
|
1260
|
+
const m = mat ?? {};
|
|
1261
|
+
const common = {
|
|
1262
|
+
ref,
|
|
1263
|
+
color: m.color ?? "#ffffff",
|
|
1264
|
+
transparent: opacity < 1,
|
|
1265
|
+
opacity,
|
|
1266
|
+
side: SIDE_MAP[m.side ?? "front"]
|
|
1267
|
+
};
|
|
1268
|
+
const emissive = m.emissive ? { emissive: m.emissive, emissiveIntensity: m.emissiveIntensity ?? 1 } : {};
|
|
1269
|
+
switch (m.kind ?? "standard") {
|
|
1270
|
+
case "basic":
|
|
1271
|
+
return /* @__PURE__ */ jsxRuntime.jsx("meshBasicMaterial", { ...common });
|
|
1272
|
+
case "toon":
|
|
1273
|
+
return /* @__PURE__ */ jsxRuntime.jsx("meshToonMaterial", { ...common, ...emissive });
|
|
1274
|
+
case "physical":
|
|
1275
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1276
|
+
"meshPhysicalMaterial",
|
|
1277
|
+
{
|
|
1278
|
+
...common,
|
|
1279
|
+
...emissive,
|
|
1280
|
+
metalness: m.metalness ?? 0,
|
|
1281
|
+
roughness: m.roughness ?? 0.5,
|
|
1282
|
+
transmission: m.transmission ?? 0,
|
|
1283
|
+
ior: m.ior ?? 1.5,
|
|
1284
|
+
flatShading: m.flatShading ?? false
|
|
1285
|
+
}
|
|
1286
|
+
);
|
|
1287
|
+
case "standard":
|
|
1288
|
+
default:
|
|
1289
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1290
|
+
"meshStandardMaterial",
|
|
1291
|
+
{
|
|
1292
|
+
...common,
|
|
1293
|
+
...emissive,
|
|
1294
|
+
metalness: m.metalness ?? 0,
|
|
1295
|
+
roughness: m.roughness ?? 0.5,
|
|
1296
|
+
flatShading: m.flatShading ?? false
|
|
1297
|
+
}
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function Mesh3D({
|
|
1302
|
+
node,
|
|
1303
|
+
projector,
|
|
1304
|
+
groupOpacity = 1
|
|
1305
|
+
}) {
|
|
1306
|
+
const groupRef = React3.useRef(null);
|
|
1307
|
+
const meshRef = React3.useRef(null);
|
|
1308
|
+
const materialRef = React3.useRef(null);
|
|
1309
|
+
const animated = isAnimatedMesh(node);
|
|
1310
|
+
const validPos = isValidScenePos(node.position);
|
|
1311
|
+
const baseWorld = validPos ? projector.toWorld(node.position) : [0, 0, 0];
|
|
1312
|
+
const geo = React3.useMemo(() => meshGeometry(node, projector.cellSize), [node, projector.cellSize]);
|
|
1313
|
+
fiber.useFrame(({ clock }) => {
|
|
1314
|
+
if (!animated || !groupRef.current) return;
|
|
1315
|
+
const state = applyMeshAnimation(node, clock.elapsedTime * 1e3);
|
|
1316
|
+
if (!state) return;
|
|
1317
|
+
const [wx, wy, wz] = baseWorld;
|
|
1318
|
+
groupRef.current.position.set(
|
|
1319
|
+
wx + state.offset[0] * projector.cellSize,
|
|
1320
|
+
wy + state.offset[2] * projector.cellSize,
|
|
1321
|
+
wz + state.offset[1] * projector.cellSize
|
|
1322
|
+
);
|
|
1323
|
+
groupRef.current.scale.setScalar(state.scale);
|
|
1324
|
+
if (meshRef.current) {
|
|
1325
|
+
const base = node.rotation ?? [0, 0, 0];
|
|
1326
|
+
meshRef.current.rotation.set(base[0] + state.rotate[0], base[1] + state.rotate[1], base[2] + state.rotate[2]);
|
|
1327
|
+
}
|
|
1328
|
+
const mat = materialRef.current;
|
|
1329
|
+
if (mat) {
|
|
1330
|
+
const effective = (state.opacity ?? node.opacity ?? 1) * (node.material?.opacity ?? 1) * groupOpacity;
|
|
1331
|
+
mat.opacity = effective;
|
|
1332
|
+
mat.transparent = effective < 1;
|
|
1333
|
+
if (state.color && mat.color) mat.color.set(state.color);
|
|
1334
|
+
if (state.emissive && mat.emissive) mat.emissive.set(state.emissive);
|
|
1335
|
+
if (state.emissiveIntensity !== void 0 && mat.emissiveIntensity !== void 0) {
|
|
1336
|
+
mat.emissiveIntensity = state.emissiveIntensity;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
if (!validPos || !geo) return null;
|
|
1341
|
+
const lift = (node.pivot ?? "bottom") === "bottom" ? geo.lift : 0;
|
|
1342
|
+
const opacity = (node.opacity ?? 1) * (node.material?.opacity ?? 1) * groupOpacity;
|
|
1343
|
+
const rotation = node.rotation ?? [0, 0, 0];
|
|
1344
|
+
const outlineScale = geo.size > 0 ? 1 + (node.outline?.width ?? 0.05) * projector.cellSize / geo.size : 1;
|
|
1345
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { ref: groupRef, position: baseWorld, children: [
|
|
1346
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1347
|
+
"mesh",
|
|
1348
|
+
{
|
|
1349
|
+
ref: meshRef,
|
|
1350
|
+
position: [0, lift, 0],
|
|
1351
|
+
rotation,
|
|
1352
|
+
castShadow: node.castShadow ?? true,
|
|
1353
|
+
receiveShadow: node.receiveShadow ?? true,
|
|
1354
|
+
children: [
|
|
1355
|
+
geo.element,
|
|
1356
|
+
meshMaterial(node.material, opacity, materialRef)
|
|
1357
|
+
]
|
|
1358
|
+
}
|
|
1359
|
+
),
|
|
1360
|
+
node.outline && /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, lift, 0], rotation, scale: outlineScale, children: [
|
|
1361
|
+
geo.element,
|
|
1362
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1363
|
+
"meshBasicMaterial",
|
|
1364
|
+
{
|
|
1365
|
+
color: node.outline.color ?? "#101014",
|
|
1366
|
+
side: THREE10__namespace.BackSide,
|
|
1367
|
+
transparent: opacity < 1,
|
|
1368
|
+
opacity
|
|
1369
|
+
}
|
|
1370
|
+
)
|
|
1371
|
+
] })
|
|
1372
|
+
] });
|
|
1373
|
+
}
|
|
1374
|
+
function Drawable3D({ node, projector, groupOpacity = 1 }) {
|
|
1013
1375
|
switch (node.type) {
|
|
1014
1376
|
case "draw-sprite":
|
|
1015
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Sprite3D, { node, projector });
|
|
1377
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Sprite3D, { node, projector, groupOpacity });
|
|
1016
1378
|
case "draw-shape":
|
|
1017
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node, projector });
|
|
1379
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node, projector, groupOpacity });
|
|
1018
1380
|
case "draw-text":
|
|
1019
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node, projector });
|
|
1381
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node, projector, groupOpacity });
|
|
1382
|
+
case "draw-mesh":
|
|
1383
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Mesh3D, { node, projector, groupOpacity });
|
|
1020
1384
|
case "draw-sprite-layer":
|
|
1021
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Sprite3D, { node: item, projector }, i)) });
|
|
1385
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Sprite3D, { node: item, projector, groupOpacity }, i)) });
|
|
1022
1386
|
case "draw-shape-layer":
|
|
1023
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node: item, projector }, i)) });
|
|
1387
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Shape3D, { node: item, projector, groupOpacity }, i)) });
|
|
1024
1388
|
case "draw-text-layer":
|
|
1025
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node: item, projector }, i)) });
|
|
1026
|
-
case "draw-group":
|
|
1027
|
-
|
|
1028
|
-
|
|
1389
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Text3D, { node: item, projector, groupOpacity }, i)) });
|
|
1390
|
+
case "draw-group": {
|
|
1391
|
+
if (!isValidScenePos(node.position) || !Array.isArray(node.items)) return null;
|
|
1392
|
+
if (node.clip) warnUnsupported3d("draw-group:clip");
|
|
1393
|
+
const world = projector.toWorld(node.position);
|
|
1394
|
+
const inner = create3DProjector({ cellSize: projector.cellSize });
|
|
1395
|
+
const opacity = (node.opacity ?? 1) * groupOpacity;
|
|
1396
|
+
const s = node.scale ?? 1;
|
|
1397
|
+
return /* @__PURE__ */ jsxRuntime.jsx("group", { position: world, rotation: [0, -(node.rotate ?? 0), 0], scale: [s, s, s], children: node.items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(Drawable3D, { node: item, projector: inner, groupOpacity: opacity }, i)) });
|
|
1398
|
+
}
|
|
1029
1399
|
}
|
|
1030
1400
|
}
|
|
1031
1401
|
|
|
1032
|
-
// lib/drawable/projector3d.ts
|
|
1033
|
-
function create3DProjector(opts = {}) {
|
|
1034
|
-
const cellSize = opts.cellSize ?? 1;
|
|
1035
|
-
const offsetX = opts.offsetX ?? 0;
|
|
1036
|
-
const offsetZ = opts.offsetZ ?? 0;
|
|
1037
|
-
return {
|
|
1038
|
-
cellSize,
|
|
1039
|
-
toWorld: (pos) => [pos.x * cellSize + offsetX, pos.z ?? 0, pos.y * cellSize + offsetZ]
|
|
1040
|
-
};
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
1402
|
// lib/drawable/three/game3dTheme.ts
|
|
1044
1403
|
var GRID_COLORS_3D = {
|
|
1045
1404
|
cell: "#444444",
|
|
@@ -1051,6 +1410,20 @@ function cn(...inputs) {
|
|
|
1051
1410
|
}
|
|
1052
1411
|
var DEFAULT_GRID_CONFIG = {
|
|
1053
1412
|
cellSize: 1};
|
|
1413
|
+
function RoomEnvironment3D() {
|
|
1414
|
+
const { gl, scene } = fiber.useThree(({ gl: gl2, scene: scene2 }) => ({ gl: gl2, scene: scene2 }));
|
|
1415
|
+
React3.useEffect(() => {
|
|
1416
|
+
const pmremGenerator = new THREE10__namespace.PMREMGenerator(gl);
|
|
1417
|
+
const envTexture = pmremGenerator.fromScene(new RoomEnvironment_js.RoomEnvironment(), 0.04).texture;
|
|
1418
|
+
scene.environment = envTexture;
|
|
1419
|
+
return () => {
|
|
1420
|
+
scene.environment = null;
|
|
1421
|
+
envTexture.dispose();
|
|
1422
|
+
pmremGenerator.dispose();
|
|
1423
|
+
};
|
|
1424
|
+
}, [gl, scene]);
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1054
1427
|
var Canvas3DHost = React3.forwardRef(
|
|
1055
1428
|
({
|
|
1056
1429
|
cameraMode = "isometric",
|
|
@@ -1075,6 +1448,9 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1075
1448
|
keyMap,
|
|
1076
1449
|
keyUpMap,
|
|
1077
1450
|
pixelsPerUnit,
|
|
1451
|
+
fov,
|
|
1452
|
+
lighting,
|
|
1453
|
+
post,
|
|
1078
1454
|
children,
|
|
1079
1455
|
drawables
|
|
1080
1456
|
}, ref) => {
|
|
@@ -1083,6 +1459,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1083
1459
|
const [internalError, setInternalError] = React3.useState(null);
|
|
1084
1460
|
const eventBus = useEventBus();
|
|
1085
1461
|
const keysRef = React3.useRef(/* @__PURE__ */ new Set());
|
|
1462
|
+
const allDrawables = React3.useMemo(() => drawables ?? [], [drawables]);
|
|
1086
1463
|
React3.useEffect(() => {
|
|
1087
1464
|
if (!keyMap && !keyUpMap) return;
|
|
1088
1465
|
const down = (e) => {
|
|
@@ -1116,7 +1493,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1116
1493
|
unitAnimationEvent,
|
|
1117
1494
|
cameraChangeEvent
|
|
1118
1495
|
});
|
|
1119
|
-
const drawnItems = React3.useMemo(() => collectDrawnItems(
|
|
1496
|
+
const drawnItems = React3.useMemo(() => collectDrawnItems(allDrawables), [allDrawables]);
|
|
1120
1497
|
const scenePositions = React3.useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
|
|
1121
1498
|
const hitIndex = React3.useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
|
|
1122
1499
|
const gridBounds = React3.useMemo(() => {
|
|
@@ -1164,7 +1541,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1164
1541
|
getCameraPosition: () => {
|
|
1165
1542
|
if (controlsRef.current) {
|
|
1166
1543
|
const pos = controlsRef.current.object.position;
|
|
1167
|
-
return new
|
|
1544
|
+
return new THREE10__namespace.Vector3(pos.x, pos.y, pos.z);
|
|
1168
1545
|
}
|
|
1169
1546
|
return null;
|
|
1170
1547
|
},
|
|
@@ -1203,18 +1580,19 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1203
1580
|
const cx = cameraTarget[0];
|
|
1204
1581
|
const cz = cameraTarget[2];
|
|
1205
1582
|
const d = size * 1;
|
|
1583
|
+
const fovDeg = fov ?? 45;
|
|
1206
1584
|
switch (cameraMode) {
|
|
1207
1585
|
case "isometric":
|
|
1208
|
-
return { position: [cx + d, d * 0.8, cz + d], fov:
|
|
1586
|
+
return { position: [cx + d, d * 0.8, cz + d], fov: fovDeg };
|
|
1209
1587
|
case "top-down":
|
|
1210
|
-
return { position: [cx, d * 2, cz + d * 0.35], fov:
|
|
1588
|
+
return { position: [cx, d * 2, cz + d * 0.35], fov: fovDeg };
|
|
1211
1589
|
case "follow":
|
|
1212
|
-
return { position: [cx, d * 0.5, cz + d], fov:
|
|
1590
|
+
return { position: [cx, d * 0.5, cz + d], fov: fovDeg };
|
|
1213
1591
|
case "perspective":
|
|
1214
1592
|
default:
|
|
1215
|
-
return { position: [cx + d, d, cz + d], fov:
|
|
1593
|
+
return { position: [cx + d, d, cz + d], fov: fovDeg };
|
|
1216
1594
|
}
|
|
1217
|
-
}, [cameraMode, gridBounds, cellSize, cameraTarget]);
|
|
1595
|
+
}, [cameraMode, gridBounds, cellSize, cameraTarget, fov]);
|
|
1218
1596
|
const followWorld = React3.useMemo(() => {
|
|
1219
1597
|
if (followTarget) return drawableProjector.toWorld(followTarget);
|
|
1220
1598
|
return cameraTarget;
|
|
@@ -1297,9 +1675,19 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1297
1675
|
shadowNormalBias: 0.04,
|
|
1298
1676
|
shadowCameraSize: 5,
|
|
1299
1677
|
shadowCameraNear: 0.5,
|
|
1300
|
-
shadowCameraFar: 500
|
|
1678
|
+
shadowCameraFar: 500,
|
|
1679
|
+
ambientIntensity: lighting?.ambient?.intensity,
|
|
1680
|
+
ambientColor: lighting?.ambient?.color,
|
|
1681
|
+
directionalIntensity: lighting?.directional?.intensity,
|
|
1682
|
+
directionalColor: lighting?.directional?.color,
|
|
1683
|
+
directionalPosition: lighting?.directional?.position,
|
|
1684
|
+
hemisphereIntensity: lighting?.hemisphere?.intensity,
|
|
1685
|
+
hemisphereColor: lighting?.hemisphere?.color,
|
|
1686
|
+
hemisphereGroundColor: lighting?.hemisphere?.groundColor,
|
|
1687
|
+
points: lighting?.points
|
|
1301
1688
|
}
|
|
1302
1689
|
),
|
|
1690
|
+
lighting?.environment === "room" && /* @__PURE__ */ jsxRuntime.jsx(RoomEnvironment3D, {}),
|
|
1303
1691
|
showGrid && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1304
1692
|
drei.Grid,
|
|
1305
1693
|
{
|
|
@@ -1322,7 +1710,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1322
1710
|
fadeStrength: 1
|
|
1323
1711
|
}
|
|
1324
1712
|
),
|
|
1325
|
-
|
|
1713
|
+
allDrawables.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("group", { children: allDrawables.map((node, i) => /* @__PURE__ */ jsxRuntime.jsx(Drawable3D, { node, projector: drawableProjector }, i)) }),
|
|
1326
1714
|
(tileClickEvent || unitClickEvent) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1327
1715
|
"mesh",
|
|
1328
1716
|
{
|
|
@@ -1347,7 +1735,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1347
1735
|
]
|
|
1348
1736
|
}
|
|
1349
1737
|
),
|
|
1350
|
-
|
|
1738
|
+
post && (post.bloom || post.vignette) ? /* @__PURE__ */ jsxRuntime.jsx(Effects3D, { post }) : null,
|
|
1351
1739
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1352
1740
|
drei.OrbitControls,
|
|
1353
1741
|
{
|
|
@@ -1358,7 +1746,7 @@ var Canvas3DHost = React3.forwardRef(
|
|
|
1358
1746
|
dampingFactor: 0.05,
|
|
1359
1747
|
enableZoom: true,
|
|
1360
1748
|
enablePan: true,
|
|
1361
|
-
touches: { ONE:
|
|
1749
|
+
touches: { ONE: THREE10__namespace.TOUCH.ROTATE, TWO: THREE10__namespace.TOUCH.DOLLY_PAN },
|
|
1362
1750
|
minDistance: 2,
|
|
1363
1751
|
maxDistance: 100,
|
|
1364
1752
|
maxPolarAngle: Math.PI / 2 - 0.1
|
|
@@ -1381,15 +1769,15 @@ function Scene3D({ background = "#1a1a2e", fog, children }) {
|
|
|
1381
1769
|
if (initializedRef.current) return;
|
|
1382
1770
|
initializedRef.current = true;
|
|
1383
1771
|
if (background.startsWith("#") || background.startsWith("rgb")) {
|
|
1384
|
-
scene.background = new
|
|
1772
|
+
scene.background = new THREE10__namespace.Color(background);
|
|
1385
1773
|
} else {
|
|
1386
|
-
const loader = new
|
|
1774
|
+
const loader = new THREE10__namespace.TextureLoader();
|
|
1387
1775
|
loader.load(background, (texture) => {
|
|
1388
1776
|
scene.background = texture;
|
|
1389
1777
|
});
|
|
1390
1778
|
}
|
|
1391
1779
|
if (fog) {
|
|
1392
|
-
scene.fog = new
|
|
1780
|
+
scene.fog = new THREE10__namespace.Fog(fog.color, fog.near, fog.far);
|
|
1393
1781
|
}
|
|
1394
1782
|
return () => {
|
|
1395
1783
|
scene.background = null;
|
|
@@ -1412,14 +1800,14 @@ var Camera3D = React3.forwardRef(
|
|
|
1412
1800
|
}, ref) => {
|
|
1413
1801
|
const { camera, set, viewport } = fiber.useThree();
|
|
1414
1802
|
const controlsRef = React3.useRef(null);
|
|
1415
|
-
const initialPosition = React3.useRef(new
|
|
1416
|
-
const initialTarget = React3.useRef(new
|
|
1803
|
+
const initialPosition = React3.useRef(new THREE10__namespace.Vector3(...position));
|
|
1804
|
+
const initialTarget = React3.useRef(new THREE10__namespace.Vector3(...target));
|
|
1417
1805
|
React3.useEffect(() => {
|
|
1418
1806
|
let newCamera;
|
|
1419
1807
|
if (mode === "isometric") {
|
|
1420
1808
|
const aspect = viewport.aspect;
|
|
1421
1809
|
const size = 10 / zoom;
|
|
1422
|
-
newCamera = new
|
|
1810
|
+
newCamera = new THREE10__namespace.OrthographicCamera(
|
|
1423
1811
|
-size * aspect,
|
|
1424
1812
|
size * aspect,
|
|
1425
1813
|
size,
|
|
@@ -1428,7 +1816,7 @@ var Camera3D = React3.forwardRef(
|
|
|
1428
1816
|
1e3
|
|
1429
1817
|
);
|
|
1430
1818
|
} else {
|
|
1431
|
-
newCamera = new
|
|
1819
|
+
newCamera = new THREE10__namespace.PerspectiveCamera(fov, viewport.aspect, 0.1, 1e3);
|
|
1432
1820
|
}
|
|
1433
1821
|
newCamera.position.copy(initialPosition.current);
|
|
1434
1822
|
newCamera.lookAt(initialTarget.current.x, initialTarget.current.y, initialTarget.current.z);
|
|
@@ -1469,8 +1857,8 @@ var Camera3D = React3.forwardRef(
|
|
|
1469
1857
|
}
|
|
1470
1858
|
},
|
|
1471
1859
|
getViewBounds: () => {
|
|
1472
|
-
const min = new
|
|
1473
|
-
const max = new
|
|
1860
|
+
const min = new THREE10__namespace.Vector3(-10, -10, -10);
|
|
1861
|
+
const max = new THREE10__namespace.Vector3(10, 10, 10);
|
|
1474
1862
|
return { min, max };
|
|
1475
1863
|
}
|
|
1476
1864
|
}));
|
|
@@ -1512,7 +1900,7 @@ var AssetLoader = class {
|
|
|
1512
1900
|
__publicField(this, "textureCache");
|
|
1513
1901
|
__publicField(this, "loadingPromises");
|
|
1514
1902
|
this.objLoader = new OBJLoader_js.OBJLoader();
|
|
1515
|
-
this.textureLoader = new
|
|
1903
|
+
this.textureLoader = new THREE10__namespace.TextureLoader();
|
|
1516
1904
|
this.modelCache = /* @__PURE__ */ new Map();
|
|
1517
1905
|
this.textureCache = /* @__PURE__ */ new Map();
|
|
1518
1906
|
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
@@ -1586,7 +1974,7 @@ var AssetLoader = class {
|
|
|
1586
1974
|
return this.loadingPromises.get(`texture:${url}`);
|
|
1587
1975
|
}
|
|
1588
1976
|
const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
|
|
1589
|
-
texture.colorSpace =
|
|
1977
|
+
texture.colorSpace = THREE10__namespace.SRGBColorSpace;
|
|
1590
1978
|
this.textureCache.set(url, texture);
|
|
1591
1979
|
this.loadingPromises.delete(`texture:${url}`);
|
|
1592
1980
|
return texture;
|
|
@@ -1660,7 +2048,7 @@ var AssetLoader = class {
|
|
|
1660
2048
|
});
|
|
1661
2049
|
this.modelCache.forEach((model) => {
|
|
1662
2050
|
model.scene.traverse((child) => {
|
|
1663
|
-
if (child instanceof
|
|
2051
|
+
if (child instanceof THREE10__namespace.Mesh) {
|
|
1664
2052
|
child.geometry.dispose();
|
|
1665
2053
|
if (Array.isArray(child.material)) {
|
|
1666
2054
|
child.material.forEach((m) => m.dispose());
|
|
@@ -1697,7 +2085,7 @@ var DEFAULT_OPTIONS = {
|
|
|
1697
2085
|
gridSize: 20,
|
|
1698
2086
|
assetLoader: new AssetLoader()
|
|
1699
2087
|
};
|
|
1700
|
-
function
|
|
2088
|
+
function useThree5(options = {}) {
|
|
1701
2089
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1702
2090
|
const containerRef = React3.useRef(null);
|
|
1703
2091
|
const canvasRef = React3.useRef(null);
|
|
@@ -1710,21 +2098,21 @@ function useThree4(options = {}) {
|
|
|
1710
2098
|
const [isReady, setIsReady] = React3.useState(false);
|
|
1711
2099
|
const [dimensions, setDimensions] = React3.useState({ width: 0, height: 0 });
|
|
1712
2100
|
const initialCameraPosition = React3.useMemo(
|
|
1713
|
-
() => new
|
|
2101
|
+
() => new THREE10__namespace.Vector3(...opts.cameraPosition),
|
|
1714
2102
|
[]
|
|
1715
2103
|
);
|
|
1716
2104
|
React3.useEffect(() => {
|
|
1717
2105
|
if (!containerRef.current) return;
|
|
1718
2106
|
const container = containerRef.current;
|
|
1719
2107
|
const { clientWidth, clientHeight } = container;
|
|
1720
|
-
const scene = new
|
|
1721
|
-
scene.background = new
|
|
2108
|
+
const scene = new THREE10__namespace.Scene();
|
|
2109
|
+
scene.background = new THREE10__namespace.Color(opts.backgroundColor);
|
|
1722
2110
|
sceneRef.current = scene;
|
|
1723
2111
|
let camera;
|
|
1724
2112
|
const aspect = clientWidth / clientHeight;
|
|
1725
2113
|
if (opts.cameraMode === "isometric") {
|
|
1726
2114
|
const size = 10;
|
|
1727
|
-
camera = new
|
|
2115
|
+
camera = new THREE10__namespace.OrthographicCamera(
|
|
1728
2116
|
-size * aspect,
|
|
1729
2117
|
size * aspect,
|
|
1730
2118
|
size,
|
|
@@ -1733,11 +2121,11 @@ function useThree4(options = {}) {
|
|
|
1733
2121
|
1e3
|
|
1734
2122
|
);
|
|
1735
2123
|
} else {
|
|
1736
|
-
camera = new
|
|
2124
|
+
camera = new THREE10__namespace.PerspectiveCamera(45, aspect, 0.1, 1e3);
|
|
1737
2125
|
}
|
|
1738
2126
|
camera.position.copy(initialCameraPosition);
|
|
1739
2127
|
cameraRef.current = camera;
|
|
1740
|
-
const renderer = new
|
|
2128
|
+
const renderer = new THREE10__namespace.WebGLRenderer({
|
|
1741
2129
|
antialias: true,
|
|
1742
2130
|
alpha: true,
|
|
1743
2131
|
canvas: canvasRef.current || void 0
|
|
@@ -1745,7 +2133,7 @@ function useThree4(options = {}) {
|
|
|
1745
2133
|
renderer.setSize(clientWidth, clientHeight);
|
|
1746
2134
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
1747
2135
|
renderer.shadowMap.enabled = opts.shadows;
|
|
1748
|
-
renderer.shadowMap.type =
|
|
2136
|
+
renderer.shadowMap.type = THREE10__namespace.PCFSoftShadowMap;
|
|
1749
2137
|
rendererRef.current = renderer;
|
|
1750
2138
|
const controls = new OrbitControls_js.OrbitControls(camera, renderer.domElement);
|
|
1751
2139
|
controls.enableDamping = true;
|
|
@@ -1754,16 +2142,16 @@ function useThree4(options = {}) {
|
|
|
1754
2142
|
controls.maxDistance = 100;
|
|
1755
2143
|
controls.maxPolarAngle = Math.PI / 2 - 0.1;
|
|
1756
2144
|
controlsRef.current = controls;
|
|
1757
|
-
const ambientLight = new
|
|
2145
|
+
const ambientLight = new THREE10__namespace.AmbientLight(16777215, 0.6);
|
|
1758
2146
|
scene.add(ambientLight);
|
|
1759
|
-
const directionalLight = new
|
|
2147
|
+
const directionalLight = new THREE10__namespace.DirectionalLight(16777215, 0.8);
|
|
1760
2148
|
directionalLight.position.set(10, 20, 10);
|
|
1761
2149
|
directionalLight.castShadow = opts.shadows;
|
|
1762
2150
|
directionalLight.shadow.mapSize.width = 2048;
|
|
1763
2151
|
directionalLight.shadow.mapSize.height = 2048;
|
|
1764
2152
|
scene.add(directionalLight);
|
|
1765
2153
|
if (opts.showGrid) {
|
|
1766
|
-
const gridHelper = new
|
|
2154
|
+
const gridHelper = new THREE10__namespace.GridHelper(
|
|
1767
2155
|
opts.gridSize,
|
|
1768
2156
|
opts.gridSize,
|
|
1769
2157
|
4473924,
|
|
@@ -1781,10 +2169,10 @@ function useThree4(options = {}) {
|
|
|
1781
2169
|
const handleResize = () => {
|
|
1782
2170
|
const { clientWidth: width, clientHeight: height } = container;
|
|
1783
2171
|
setDimensions({ width, height });
|
|
1784
|
-
if (camera instanceof
|
|
2172
|
+
if (camera instanceof THREE10__namespace.PerspectiveCamera) {
|
|
1785
2173
|
camera.aspect = width / height;
|
|
1786
2174
|
camera.updateProjectionMatrix();
|
|
1787
|
-
} else if (camera instanceof
|
|
2175
|
+
} else if (camera instanceof THREE10__namespace.OrthographicCamera) {
|
|
1788
2176
|
const aspect2 = width / height;
|
|
1789
2177
|
const size = 10;
|
|
1790
2178
|
camera.left = -size * aspect2;
|
|
@@ -1815,7 +2203,7 @@ function useThree4(options = {}) {
|
|
|
1815
2203
|
let newCamera;
|
|
1816
2204
|
if (opts.cameraMode === "isometric") {
|
|
1817
2205
|
const size = 10;
|
|
1818
|
-
newCamera = new
|
|
2206
|
+
newCamera = new THREE10__namespace.OrthographicCamera(
|
|
1819
2207
|
-size * aspect,
|
|
1820
2208
|
size * aspect,
|
|
1821
2209
|
size,
|
|
@@ -1824,7 +2212,7 @@ function useThree4(options = {}) {
|
|
|
1824
2212
|
1e3
|
|
1825
2213
|
);
|
|
1826
2214
|
} else {
|
|
1827
|
-
newCamera = new
|
|
2215
|
+
newCamera = new THREE10__namespace.PerspectiveCamera(45, aspect, 0.1, 1e3);
|
|
1828
2216
|
}
|
|
1829
2217
|
newCamera.position.copy(currentPos);
|
|
1830
2218
|
cameraRef.current = newCamera;
|
|
@@ -2154,8 +2542,8 @@ function useSceneGraph() {
|
|
|
2154
2542
|
}
|
|
2155
2543
|
function useRaycaster(options) {
|
|
2156
2544
|
const { camera, canvas, cellSize = 1, offsetX = 0, offsetZ = 0 } = options;
|
|
2157
|
-
const raycaster = React3.useRef(new
|
|
2158
|
-
const mouse = React3.useRef(new
|
|
2545
|
+
const raycaster = React3.useRef(new THREE10__namespace.Raycaster());
|
|
2546
|
+
const mouse = React3.useRef(new THREE10__namespace.Vector2());
|
|
2159
2547
|
const clientToNDC = React3.useCallback(
|
|
2160
2548
|
(clientX, clientY) => {
|
|
2161
2549
|
if (!canvas) {
|
|
@@ -2225,8 +2613,8 @@ function useRaycaster(options) {
|
|
|
2225
2613
|
const ndc = clientToNDC(clientX, clientY);
|
|
2226
2614
|
mouse.current.set(ndc.x, ndc.y);
|
|
2227
2615
|
raycaster.current.setFromCamera(mouse.current, camera);
|
|
2228
|
-
const plane = new
|
|
2229
|
-
const target = new
|
|
2616
|
+
const plane = new THREE10__namespace.Plane(new THREE10__namespace.Vector3(0, 1, 0), 0);
|
|
2617
|
+
const target = new THREE10__namespace.Vector3();
|
|
2230
2618
|
const intersection = raycaster.current.ray.intersectPlane(plane, target);
|
|
2231
2619
|
if (intersection) {
|
|
2232
2620
|
const gridX = Math.round((target.x - offsetX) / cellSize);
|
|
@@ -2264,7 +2652,7 @@ function useRaycaster(options) {
|
|
|
2264
2652
|
return {
|
|
2265
2653
|
gridX: gridCoords.x,
|
|
2266
2654
|
gridZ: gridCoords.z,
|
|
2267
|
-
worldPosition: new
|
|
2655
|
+
worldPosition: new THREE10__namespace.Vector3(
|
|
2268
2656
|
gridCoords.x * cellSize + offsetX,
|
|
2269
2657
|
0,
|
|
2270
2658
|
gridCoords.z * cellSize + offsetZ
|
|
@@ -2294,7 +2682,7 @@ var DEFAULT_CONFIG = {
|
|
|
2294
2682
|
};
|
|
2295
2683
|
function gridToWorld(gridX, gridZ, config = DEFAULT_CONFIG) {
|
|
2296
2684
|
const opts = { ...DEFAULT_CONFIG, ...config };
|
|
2297
|
-
return new
|
|
2685
|
+
return new THREE10__namespace.Vector3(
|
|
2298
2686
|
gridX * opts.cellSize + opts.offsetX,
|
|
2299
2687
|
opts.elevation,
|
|
2300
2688
|
gridZ * opts.cellSize + opts.offsetZ
|
|
@@ -2308,17 +2696,17 @@ function worldToGrid(worldX, worldZ, config = DEFAULT_CONFIG) {
|
|
|
2308
2696
|
};
|
|
2309
2697
|
}
|
|
2310
2698
|
function raycastToPlane(camera, mouseX, mouseY, planeY = 0) {
|
|
2311
|
-
const raycaster = new
|
|
2312
|
-
const mouse = new
|
|
2699
|
+
const raycaster = new THREE10__namespace.Raycaster();
|
|
2700
|
+
const mouse = new THREE10__namespace.Vector2(mouseX, mouseY);
|
|
2313
2701
|
raycaster.setFromCamera(mouse, camera);
|
|
2314
|
-
const plane = new
|
|
2315
|
-
const target = new
|
|
2702
|
+
const plane = new THREE10__namespace.Plane(new THREE10__namespace.Vector3(0, 1, 0), -planeY);
|
|
2703
|
+
const target = new THREE10__namespace.Vector3();
|
|
2316
2704
|
const intersection = raycaster.ray.intersectPlane(plane, target);
|
|
2317
2705
|
return intersection ? target : null;
|
|
2318
2706
|
}
|
|
2319
2707
|
function raycastToObjects(camera, mouseX, mouseY, objects) {
|
|
2320
|
-
const raycaster = new
|
|
2321
|
-
const mouse = new
|
|
2708
|
+
const raycaster = new THREE10__namespace.Raycaster();
|
|
2709
|
+
const mouse = new THREE10__namespace.Vector2(mouseX, mouseY);
|
|
2322
2710
|
raycaster.setFromCamera(mouse, camera);
|
|
2323
2711
|
const intersects = raycaster.intersectObjects(objects, true);
|
|
2324
2712
|
return intersects.length > 0 ? intersects[0] : null;
|
|
@@ -2370,14 +2758,14 @@ function getCellsInRadius(centerX, centerZ, radius) {
|
|
|
2370
2758
|
return cells;
|
|
2371
2759
|
}
|
|
2372
2760
|
function createGridHighlight(color = 16776960, opacity = 0.3) {
|
|
2373
|
-
const geometry = new
|
|
2374
|
-
const material = new
|
|
2761
|
+
const geometry = new THREE10__namespace.PlaneGeometry(0.95, 0.95);
|
|
2762
|
+
const material = new THREE10__namespace.MeshBasicMaterial({
|
|
2375
2763
|
color,
|
|
2376
2764
|
transparent: true,
|
|
2377
2765
|
opacity,
|
|
2378
|
-
side:
|
|
2766
|
+
side: THREE10__namespace.DoubleSide
|
|
2379
2767
|
});
|
|
2380
|
-
const mesh = new
|
|
2768
|
+
const mesh = new THREE10__namespace.Mesh(geometry, material);
|
|
2381
2769
|
mesh.rotation.x = -Math.PI / 2;
|
|
2382
2770
|
mesh.position.y = 0.01;
|
|
2383
2771
|
return mesh;
|
|
@@ -2390,31 +2778,31 @@ function normalizeMouseCoordinates(clientX, clientY, element) {
|
|
|
2390
2778
|
};
|
|
2391
2779
|
}
|
|
2392
2780
|
function isInFrustum(position, camera, padding = 0) {
|
|
2393
|
-
const frustum = new
|
|
2394
|
-
const projScreenMatrix = new
|
|
2781
|
+
const frustum = new THREE10__namespace.Frustum();
|
|
2782
|
+
const projScreenMatrix = new THREE10__namespace.Matrix4();
|
|
2395
2783
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2396
2784
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2397
|
-
const sphere = new
|
|
2785
|
+
const sphere = new THREE10__namespace.Sphere(position, padding);
|
|
2398
2786
|
return frustum.intersectsSphere(sphere);
|
|
2399
2787
|
}
|
|
2400
2788
|
function filterByFrustum(positions, camera, padding = 0) {
|
|
2401
|
-
const frustum = new
|
|
2402
|
-
const projScreenMatrix = new
|
|
2789
|
+
const frustum = new THREE10__namespace.Frustum();
|
|
2790
|
+
const projScreenMatrix = new THREE10__namespace.Matrix4();
|
|
2403
2791
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2404
2792
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2405
2793
|
return positions.filter((position) => {
|
|
2406
|
-
const sphere = new
|
|
2794
|
+
const sphere = new THREE10__namespace.Sphere(position, padding);
|
|
2407
2795
|
return frustum.intersectsSphere(sphere);
|
|
2408
2796
|
});
|
|
2409
2797
|
}
|
|
2410
2798
|
function getVisibleIndices(positions, camera, padding = 0) {
|
|
2411
|
-
const frustum = new
|
|
2412
|
-
const projScreenMatrix = new
|
|
2799
|
+
const frustum = new THREE10__namespace.Frustum();
|
|
2800
|
+
const projScreenMatrix = new THREE10__namespace.Matrix4();
|
|
2413
2801
|
const visible = /* @__PURE__ */ new Set();
|
|
2414
2802
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
2415
2803
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
2416
2804
|
positions.forEach((position, index) => {
|
|
2417
|
-
const sphere = new
|
|
2805
|
+
const sphere = new THREE10__namespace.Sphere(position, padding);
|
|
2418
2806
|
if (frustum.intersectsSphere(sphere)) {
|
|
2419
2807
|
visible.add(index);
|
|
2420
2808
|
}
|
|
@@ -2438,7 +2826,7 @@ function updateInstanceLOD(instancedMesh, positions, camera, lodDistances) {
|
|
|
2438
2826
|
return lodIndices;
|
|
2439
2827
|
}
|
|
2440
2828
|
function cullInstancedMesh(instancedMesh, positions, visibleIndices) {
|
|
2441
|
-
const dummy = new
|
|
2829
|
+
const dummy = new THREE10__namespace.Object3D();
|
|
2442
2830
|
let visibleCount = 0;
|
|
2443
2831
|
positions.forEach((position, index) => {
|
|
2444
2832
|
if (visibleIndices.has(index)) {
|
|
@@ -3605,25 +3993,25 @@ function orbitRingPositions(count, radius, tilt) {
|
|
|
3605
3993
|
return positions;
|
|
3606
3994
|
}
|
|
3607
3995
|
function arcCurve3D(from, to, offset) {
|
|
3608
|
-
const start = new
|
|
3609
|
-
const end = new
|
|
3610
|
-
const mid = new
|
|
3611
|
-
const dir = new
|
|
3612
|
-
const up = new
|
|
3613
|
-
const perp = new
|
|
3996
|
+
const start = new THREE10.Vector3(...from);
|
|
3997
|
+
const end = new THREE10.Vector3(...to);
|
|
3998
|
+
const mid = new THREE10.Vector3().addVectors(start, end).multiplyScalar(0.5);
|
|
3999
|
+
const dir = new THREE10.Vector3().subVectors(end, start).normalize();
|
|
4000
|
+
const up = new THREE10.Vector3(0, 1, 0);
|
|
4001
|
+
const perp = new THREE10.Vector3().crossVectors(dir, up).normalize();
|
|
3614
4002
|
if (perp.length() < 1e-3) {
|
|
3615
|
-
perp.crossVectors(dir, new
|
|
4003
|
+
perp.crossVectors(dir, new THREE10.Vector3(1, 0, 0)).normalize();
|
|
3616
4004
|
}
|
|
3617
4005
|
const control = mid.clone().add(perp.multiplyScalar(offset));
|
|
3618
4006
|
control.y += Math.abs(offset) * 0.3;
|
|
3619
|
-
return new
|
|
4007
|
+
return new THREE10.QuadraticBezierCurve3(start, control, end);
|
|
3620
4008
|
}
|
|
3621
4009
|
function selfLoopCurve3D(position, loopRadius) {
|
|
3622
|
-
const base = new
|
|
3623
|
-
const start = base.clone().add(new
|
|
3624
|
-
const end = base.clone().add(new
|
|
3625
|
-
const control = base.clone().add(new
|
|
3626
|
-
return new
|
|
4010
|
+
const base = new THREE10.Vector3(...position);
|
|
4011
|
+
const start = base.clone().add(new THREE10.Vector3(-loopRadius * 0.3, 0, 0));
|
|
4012
|
+
const end = base.clone().add(new THREE10.Vector3(loopRadius * 0.3, 0, 0));
|
|
4013
|
+
const control = base.clone().add(new THREE10.Vector3(0, loopRadius, 0));
|
|
4014
|
+
return new THREE10.QuadraticBezierCurve3(start, control, end);
|
|
3627
4015
|
}
|
|
3628
4016
|
function treeLayout3D(node, origin, horizontalSpacing, verticalSpacing = 2) {
|
|
3629
4017
|
const results = [];
|
|
@@ -3790,7 +4178,7 @@ var Avl3DOrbitalNode = ({
|
|
|
3790
4178
|
if (!groupRef.current) return;
|
|
3791
4179
|
groupRef.current.rotation.y += delta * (hovered ? 0.4 : 0.2);
|
|
3792
4180
|
groupRef.current.rotation.x += delta * 0.05;
|
|
3793
|
-
currentScale.current =
|
|
4181
|
+
currentScale.current = THREE10.MathUtils.damp(currentScale.current, targetScale, 6, delta);
|
|
3794
4182
|
});
|
|
3795
4183
|
const baseBrightness = 0.3 + Math.min(pageCount, 5) * 0.05;
|
|
3796
4184
|
const emissiveIntensity = hovered ? 0.8 : baseBrightness;
|
|
@@ -4432,7 +4820,7 @@ var Avl3DStateNode = ({
|
|
|
4432
4820
|
const targetScale = hovered ? 1.08 : 1;
|
|
4433
4821
|
const currentScale = React3.useRef(1);
|
|
4434
4822
|
fiber.useFrame((_, delta) => {
|
|
4435
|
-
currentScale.current =
|
|
4823
|
+
currentScale.current = THREE10.MathUtils.damp(currentScale.current, targetScale, 6, delta);
|
|
4436
4824
|
});
|
|
4437
4825
|
const scale = currentScale.current;
|
|
4438
4826
|
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position, children: [
|
|
@@ -4612,9 +5000,9 @@ var Avl3DTransitionArc = ({
|
|
|
4612
5000
|
const guardPt = curve.getPoint(0.3);
|
|
4613
5001
|
const arrowPt = curve.getPoint(0.9);
|
|
4614
5002
|
const arrowTangent = curve.getTangent(0.9);
|
|
4615
|
-
const upVec = new
|
|
4616
|
-
const tangentVec = new
|
|
4617
|
-
const quat = new
|
|
5003
|
+
const upVec = new THREE10.Vector3(0, 1, 0);
|
|
5004
|
+
const tangentVec = new THREE10.Vector3(arrowTangent.x, arrowTangent.y, arrowTangent.z).normalize();
|
|
5005
|
+
const quat = new THREE10.Quaternion().setFromUnitVectors(upVec, tangentVec);
|
|
4618
5006
|
const effectPositions2 = [];
|
|
4619
5007
|
for (let ei = 0; ei < 4; ei++) {
|
|
4620
5008
|
const t = 0.7 + ei * 0.05;
|
|
@@ -4838,14 +5226,14 @@ function operatorColor(label) {
|
|
|
4838
5226
|
return "#4A90D9";
|
|
4839
5227
|
}
|
|
4840
5228
|
function edgeGeometry(parent, child) {
|
|
4841
|
-
const p = new
|
|
4842
|
-
const c = new
|
|
4843
|
-
const mid = new
|
|
4844
|
-
const dir = new
|
|
5229
|
+
const p = new THREE10.Vector3(parent.x, parent.y, parent.z);
|
|
5230
|
+
const c = new THREE10.Vector3(child.x, child.y, child.z);
|
|
5231
|
+
const mid = new THREE10.Vector3().addVectors(p, c).multiplyScalar(0.5);
|
|
5232
|
+
const dir = new THREE10.Vector3().subVectors(c, p);
|
|
4845
5233
|
const length = dir.length();
|
|
4846
|
-
const yAxis = new
|
|
5234
|
+
const yAxis = new THREE10.Vector3(0, 1, 0);
|
|
4847
5235
|
const angle = yAxis.angleTo(dir.normalize());
|
|
4848
|
-
const axis = new
|
|
5236
|
+
const axis = new THREE10.Vector3().crossVectors(yAxis, dir).normalize();
|
|
4849
5237
|
if (axis.length() < 1e-3) {
|
|
4850
5238
|
return {
|
|
4851
5239
|
position: [mid.x, mid.y, mid.z],
|
|
@@ -5221,12 +5609,12 @@ function useAvl3DConfig() {
|
|
|
5221
5609
|
}
|
|
5222
5610
|
function CameraController({ targetPosition, targetLookAt, animated }) {
|
|
5223
5611
|
const { camera } = fiber.useThree();
|
|
5224
|
-
const targetPosVec = React3.useRef(new
|
|
5225
|
-
const targetLookVec = React3.useRef(new
|
|
5612
|
+
const targetPosVec = React3.useRef(new THREE10__namespace.Vector3(...targetPosition));
|
|
5613
|
+
const targetLookVec = React3.useRef(new THREE10__namespace.Vector3(...targetLookAt));
|
|
5226
5614
|
const isAnimating = React3.useRef(false);
|
|
5227
5615
|
React3.useEffect(() => {
|
|
5228
|
-
const newTarget = new
|
|
5229
|
-
const newLookAt = new
|
|
5616
|
+
const newTarget = new THREE10__namespace.Vector3(...targetPosition);
|
|
5617
|
+
const newLookAt = new THREE10__namespace.Vector3(...targetLookAt);
|
|
5230
5618
|
if (!newTarget.equals(targetPosVec.current) || !newLookAt.equals(targetLookVec.current)) {
|
|
5231
5619
|
targetPosVec.current.copy(newTarget);
|
|
5232
5620
|
targetLookVec.current.copy(newLookAt);
|
|
@@ -5241,9 +5629,9 @@ function CameraController({ targetPosition, targetLookAt, animated }) {
|
|
|
5241
5629
|
fiber.useFrame((_, delta) => {
|
|
5242
5630
|
if (!isAnimating.current) return;
|
|
5243
5631
|
const speed = 3;
|
|
5244
|
-
camera.position.x =
|
|
5245
|
-
camera.position.y =
|
|
5246
|
-
camera.position.z =
|
|
5632
|
+
camera.position.x = THREE10__namespace.MathUtils.damp(camera.position.x, targetPosVec.current.x, speed, delta);
|
|
5633
|
+
camera.position.y = THREE10__namespace.MathUtils.damp(camera.position.y, targetPosVec.current.y, speed, delta);
|
|
5634
|
+
camera.position.z = THREE10__namespace.MathUtils.damp(camera.position.z, targetPosVec.current.z, speed, delta);
|
|
5247
5635
|
camera.lookAt(targetLookVec.current);
|
|
5248
5636
|
const dist = camera.position.distanceTo(targetPosVec.current);
|
|
5249
5637
|
if (dist < 0.05) {
|
|
@@ -5258,7 +5646,7 @@ function SceneFade({ animating, children }) {
|
|
|
5258
5646
|
fiber.useFrame((_, delta) => {
|
|
5259
5647
|
if (!groupRef.current) return;
|
|
5260
5648
|
const target = animating ? 0 : 1;
|
|
5261
|
-
opacityRef.current =
|
|
5649
|
+
opacityRef.current = THREE10__namespace.MathUtils.damp(opacityRef.current, target, 5, delta);
|
|
5262
5650
|
groupRef.current.visible = opacityRef.current > 0.05;
|
|
5263
5651
|
const s = 0.9 + opacityRef.current * 0.1;
|
|
5264
5652
|
groupRef.current.scale.setScalar(s);
|
|
@@ -5558,5 +5946,5 @@ exports.useAvl3DConfig = useAvl3DConfig;
|
|
|
5558
5946
|
exports.useGameCanvas3DEvents = useGameCanvas3DEvents;
|
|
5559
5947
|
exports.useRaycaster = useRaycaster;
|
|
5560
5948
|
exports.useSceneGraph = useSceneGraph;
|
|
5561
|
-
exports.useThree =
|
|
5949
|
+
exports.useThree = useThree5;
|
|
5562
5950
|
exports.worldToGrid = worldToGrid;
|