@almadar/ui 2.20.1 → 2.20.7
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/LICENSE +72 -21
- package/dist/avl/index.cjs +1345 -1323
- package/dist/avl/index.d.cts +47 -47
- package/dist/avl/index.js +1321 -1299
- package/dist/components/atoms/avl/Avl3DLabel.d.ts +23 -0
- package/dist/components/atoms/avl/Avl3DTooltip.d.ts +25 -0
- package/dist/components/atoms/avl/index.d.ts +2 -0
- package/dist/components/index.cjs +3 -1
- package/dist/components/index.js +3 -1
- package/dist/components/molecules/avl/Avl3DCrossWire.d.ts +22 -0
- package/dist/components/molecules/avl/Avl3DEntityCore.d.ts +26 -0
- package/dist/components/molecules/avl/Avl3DExprTree.d.ts +21 -0
- package/dist/components/molecules/avl/Avl3DOrbitalNode.d.ts +29 -0
- package/dist/components/molecules/avl/Avl3DStateNode.d.ts +34 -0
- package/dist/components/molecules/avl/Avl3DTransitionArc.d.ts +38 -0
- package/dist/components/molecules/avl/index.d.ts +6 -0
- package/dist/components/organisms/avl/Avl3DApplicationScene.d.ts +19 -0
- package/dist/components/organisms/avl/Avl3DEffects.d.ts +18 -0
- package/dist/components/organisms/avl/Avl3DOrbitalScene.d.ts +23 -0
- package/dist/components/organisms/avl/Avl3DTraitScene.d.ts +19 -0
- package/dist/components/organisms/avl/Avl3DTransitionScene.d.ts +17 -0
- package/dist/components/organisms/avl/Avl3DViewer.d.ts +40 -0
- package/dist/components/organisms/avl/avl-3d-context.d.ts +32 -0
- package/dist/components/organisms/avl/avl-3d-layout.d.ts +116 -0
- package/dist/components/organisms/game/three/index.cjs +2549 -120
- package/dist/components/organisms/game/three/index.d.ts +8 -0
- package/dist/components/organisms/game/three/index.js +2419 -5
- package/dist/illustrations/index.cjs +2880 -109
- package/dist/illustrations/index.js +2879 -108
- package/dist/providers/OrbitalProvider.d.ts +4 -2
- package/dist/providers/index.cjs +263 -284
- package/dist/providers/index.js +189 -210
- package/dist/runtime/OrbPreview.d.ts +9 -6
- package/dist/runtime/ServerBridge.d.ts +23 -0
- package/dist/runtime/enrichFromResponse.d.ts +21 -0
- package/dist/runtime/index.cjs +31754 -2587
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +31735 -2571
- package/index.css +156 -0
- package/package.json +9 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React21 = require('react');
|
|
4
4
|
var fiber = require('@react-three/fiber');
|
|
5
5
|
var THREE6 = require('three');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -12,6 +12,7 @@ var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
|
12
12
|
var providers = require('@almadar/ui/providers');
|
|
13
13
|
var clsx = require('clsx');
|
|
14
14
|
var tailwindMerge = require('tailwind-merge');
|
|
15
|
+
var postprocessing = require('@react-three/postprocessing');
|
|
15
16
|
|
|
16
17
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
18
|
|
|
@@ -33,7 +34,7 @@ function _interopNamespace(e) {
|
|
|
33
34
|
return Object.freeze(n);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
var
|
|
37
|
+
var React21__default = /*#__PURE__*/_interopDefault(React21);
|
|
37
38
|
var THREE6__namespace = /*#__PURE__*/_interopNamespace(THREE6);
|
|
38
39
|
|
|
39
40
|
var __defProp = Object.defineProperty;
|
|
@@ -41,8 +42,8 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
41
42
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
42
43
|
function Scene3D({ background = "#1a1a2e", fog, children }) {
|
|
43
44
|
const { scene } = fiber.useThree();
|
|
44
|
-
const initializedRef =
|
|
45
|
-
|
|
45
|
+
const initializedRef = React21.useRef(false);
|
|
46
|
+
React21.useEffect(() => {
|
|
46
47
|
if (initializedRef.current) return;
|
|
47
48
|
initializedRef.current = true;
|
|
48
49
|
if (background.startsWith("#") || background.startsWith("rgb")) {
|
|
@@ -63,7 +64,7 @@ function Scene3D({ background = "#1a1a2e", fog, children }) {
|
|
|
63
64
|
}, [scene, background, fog]);
|
|
64
65
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
65
66
|
}
|
|
66
|
-
var Camera3D =
|
|
67
|
+
var Camera3D = React21.forwardRef(
|
|
67
68
|
({
|
|
68
69
|
mode = "isometric",
|
|
69
70
|
position = [10, 10, 10],
|
|
@@ -76,10 +77,10 @@ var Camera3D = React7.forwardRef(
|
|
|
76
77
|
onChange
|
|
77
78
|
}, ref) => {
|
|
78
79
|
const { camera, set, viewport } = fiber.useThree();
|
|
79
|
-
const controlsRef =
|
|
80
|
-
const initialPosition =
|
|
81
|
-
const initialTarget =
|
|
82
|
-
|
|
80
|
+
const controlsRef = React21.useRef(null);
|
|
81
|
+
const initialPosition = React21.useRef(new THREE6__namespace.Vector3(...position));
|
|
82
|
+
const initialTarget = React21.useRef(new THREE6__namespace.Vector3(...target));
|
|
83
|
+
React21.useEffect(() => {
|
|
83
84
|
let newCamera;
|
|
84
85
|
if (mode === "isometric") {
|
|
85
86
|
const aspect = viewport.aspect;
|
|
@@ -110,7 +111,7 @@ var Camera3D = React7.forwardRef(
|
|
|
110
111
|
onChange(camera);
|
|
111
112
|
}
|
|
112
113
|
});
|
|
113
|
-
|
|
114
|
+
React21.useImperativeHandle(ref, () => ({
|
|
114
115
|
getCamera: () => camera,
|
|
115
116
|
setPosition: (x, y, z) => {
|
|
116
117
|
camera.position.set(x, y, z);
|
|
@@ -251,7 +252,7 @@ function Canvas3DLoadingState({
|
|
|
251
252
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "canvas-3d-loading__background", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg__grid" }) })
|
|
252
253
|
] });
|
|
253
254
|
}
|
|
254
|
-
var Canvas3DErrorBoundary = class extends
|
|
255
|
+
var Canvas3DErrorBoundary = class extends React21.Component {
|
|
255
256
|
constructor(props) {
|
|
256
257
|
super(props);
|
|
257
258
|
__publicField(this, "handleReset", () => {
|
|
@@ -330,12 +331,12 @@ function detectAssetRoot(modelUrl) {
|
|
|
330
331
|
return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
|
|
331
332
|
}
|
|
332
333
|
function useGLTFModel(url, resourceBasePath) {
|
|
333
|
-
const [state, setState] =
|
|
334
|
+
const [state, setState] = React21.useState({
|
|
334
335
|
model: null,
|
|
335
336
|
isLoading: false,
|
|
336
337
|
error: null
|
|
337
338
|
});
|
|
338
|
-
|
|
339
|
+
React21.useEffect(() => {
|
|
339
340
|
if (!url) {
|
|
340
341
|
setState({ model: null, isLoading: false, error: null });
|
|
341
342
|
return;
|
|
@@ -384,7 +385,7 @@ function ModelLoader({
|
|
|
384
385
|
resourceBasePath
|
|
385
386
|
}) {
|
|
386
387
|
const { model: loadedModel, isLoading, error } = useGLTFModel(url, resourceBasePath);
|
|
387
|
-
const model =
|
|
388
|
+
const model = React21.useMemo(() => {
|
|
388
389
|
if (!loadedModel) return null;
|
|
389
390
|
const cloned = loadedModel.clone();
|
|
390
391
|
cloned.traverse((child) => {
|
|
@@ -395,13 +396,13 @@ function ModelLoader({
|
|
|
395
396
|
});
|
|
396
397
|
return cloned;
|
|
397
398
|
}, [loadedModel, castShadow, receiveShadow]);
|
|
398
|
-
const scaleArray =
|
|
399
|
+
const scaleArray = React21.useMemo(() => {
|
|
399
400
|
if (typeof scale === "number") {
|
|
400
401
|
return [scale, scale, scale];
|
|
401
402
|
}
|
|
402
403
|
return scale;
|
|
403
404
|
}, [scale]);
|
|
404
|
-
const rotationRad =
|
|
405
|
+
const rotationRad = React21.useMemo(() => {
|
|
405
406
|
return [
|
|
406
407
|
rotation[0] * Math.PI / 180,
|
|
407
408
|
rotation[1] * Math.PI / 180,
|
|
@@ -487,8 +488,8 @@ function PhysicsObject3D({
|
|
|
487
488
|
onGroundHit,
|
|
488
489
|
onCollision
|
|
489
490
|
}) {
|
|
490
|
-
const groupRef =
|
|
491
|
-
const physicsStateRef =
|
|
491
|
+
const groupRef = React21.useRef(null);
|
|
492
|
+
const physicsStateRef = React21.useRef({
|
|
492
493
|
id: entityId,
|
|
493
494
|
x: initialPosition[0],
|
|
494
495
|
y: initialPosition[1],
|
|
@@ -505,8 +506,8 @@ function PhysicsObject3D({
|
|
|
505
506
|
mass,
|
|
506
507
|
state: "Active"
|
|
507
508
|
});
|
|
508
|
-
const groundHitRef =
|
|
509
|
-
|
|
509
|
+
const groundHitRef = React21.useRef(false);
|
|
510
|
+
React21.useEffect(() => {
|
|
510
511
|
if (groupRef.current) {
|
|
511
512
|
groupRef.current.position.set(
|
|
512
513
|
initialPosition[0],
|
|
@@ -787,21 +788,21 @@ var DEFAULT_OPTIONS = {
|
|
|
787
788
|
};
|
|
788
789
|
function useThree3(options = {}) {
|
|
789
790
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
790
|
-
const containerRef =
|
|
791
|
-
const canvasRef =
|
|
792
|
-
const rendererRef =
|
|
793
|
-
const sceneRef =
|
|
794
|
-
const cameraRef =
|
|
795
|
-
const controlsRef =
|
|
796
|
-
const gridHelperRef =
|
|
797
|
-
const rafRef =
|
|
798
|
-
const [isReady, setIsReady] =
|
|
799
|
-
const [dimensions, setDimensions] =
|
|
800
|
-
const initialCameraPosition =
|
|
791
|
+
const containerRef = React21.useRef(null);
|
|
792
|
+
const canvasRef = React21.useRef(null);
|
|
793
|
+
const rendererRef = React21.useRef(null);
|
|
794
|
+
const sceneRef = React21.useRef(null);
|
|
795
|
+
const cameraRef = React21.useRef(null);
|
|
796
|
+
const controlsRef = React21.useRef(null);
|
|
797
|
+
const gridHelperRef = React21.useRef(null);
|
|
798
|
+
const rafRef = React21.useRef(0);
|
|
799
|
+
const [isReady, setIsReady] = React21.useState(false);
|
|
800
|
+
const [dimensions, setDimensions] = React21.useState({ width: 0, height: 0 });
|
|
801
|
+
const initialCameraPosition = React21.useMemo(
|
|
801
802
|
() => new THREE6__namespace.Vector3(...opts.cameraPosition),
|
|
802
803
|
[]
|
|
803
804
|
);
|
|
804
|
-
|
|
805
|
+
React21.useEffect(() => {
|
|
805
806
|
if (!containerRef.current) return;
|
|
806
807
|
const container = containerRef.current;
|
|
807
808
|
const { clientWidth, clientHeight } = container;
|
|
@@ -894,7 +895,7 @@ function useThree3(options = {}) {
|
|
|
894
895
|
scene.clear();
|
|
895
896
|
};
|
|
896
897
|
}, []);
|
|
897
|
-
|
|
898
|
+
React21.useEffect(() => {
|
|
898
899
|
if (!cameraRef.current || !containerRef.current) return;
|
|
899
900
|
const container = containerRef.current;
|
|
900
901
|
const { clientWidth, clientHeight } = container;
|
|
@@ -929,20 +930,20 @@ function useThree3(options = {}) {
|
|
|
929
930
|
animate();
|
|
930
931
|
}
|
|
931
932
|
}, [opts.cameraMode]);
|
|
932
|
-
const setCameraPosition =
|
|
933
|
+
const setCameraPosition = React21.useCallback((x, y, z) => {
|
|
933
934
|
if (cameraRef.current) {
|
|
934
935
|
cameraRef.current.position.set(x, y, z);
|
|
935
936
|
controlsRef.current?.update();
|
|
936
937
|
}
|
|
937
938
|
}, []);
|
|
938
|
-
const lookAt =
|
|
939
|
+
const lookAt = React21.useCallback((x, y, z) => {
|
|
939
940
|
if (cameraRef.current) {
|
|
940
941
|
cameraRef.current.lookAt(x, y, z);
|
|
941
942
|
controlsRef.current?.target.set(x, y, z);
|
|
942
943
|
controlsRef.current?.update();
|
|
943
944
|
}
|
|
944
945
|
}, []);
|
|
945
|
-
const resetCamera =
|
|
946
|
+
const resetCamera = React21.useCallback(() => {
|
|
946
947
|
if (cameraRef.current) {
|
|
947
948
|
cameraRef.current.position.copy(initialCameraPosition);
|
|
948
949
|
cameraRef.current.lookAt(0, 0, 0);
|
|
@@ -952,7 +953,7 @@ function useThree3(options = {}) {
|
|
|
952
953
|
}
|
|
953
954
|
}
|
|
954
955
|
}, [initialCameraPosition]);
|
|
955
|
-
const fitView =
|
|
956
|
+
const fitView = React21.useCallback(
|
|
956
957
|
(bounds) => {
|
|
957
958
|
if (!cameraRef.current) return;
|
|
958
959
|
const centerX = (bounds.minX + bounds.maxX) / 2;
|
|
@@ -983,20 +984,20 @@ function useThree3(options = {}) {
|
|
|
983
984
|
}
|
|
984
985
|
function useAssetLoader(options = {}) {
|
|
985
986
|
const { preloadUrls = [], loader: customLoader } = options;
|
|
986
|
-
const loaderRef =
|
|
987
|
-
const [state, setState] =
|
|
987
|
+
const loaderRef = React21.useRef(customLoader || new AssetLoader());
|
|
988
|
+
const [state, setState] = React21.useState({
|
|
988
989
|
isLoading: false,
|
|
989
990
|
progress: 0,
|
|
990
991
|
loaded: 0,
|
|
991
992
|
total: 0,
|
|
992
993
|
errors: []
|
|
993
994
|
});
|
|
994
|
-
|
|
995
|
+
React21.useEffect(() => {
|
|
995
996
|
if (preloadUrls.length > 0) {
|
|
996
997
|
preload(preloadUrls);
|
|
997
998
|
}
|
|
998
999
|
}, []);
|
|
999
|
-
const updateProgress =
|
|
1000
|
+
const updateProgress = React21.useCallback((loaded, total) => {
|
|
1000
1001
|
setState((prev) => ({
|
|
1001
1002
|
...prev,
|
|
1002
1003
|
loaded,
|
|
@@ -1004,7 +1005,7 @@ function useAssetLoader(options = {}) {
|
|
|
1004
1005
|
progress: total > 0 ? Math.round(loaded / total * 100) : 0
|
|
1005
1006
|
}));
|
|
1006
1007
|
}, []);
|
|
1007
|
-
const loadModel =
|
|
1008
|
+
const loadModel = React21.useCallback(
|
|
1008
1009
|
async (url) => {
|
|
1009
1010
|
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1010
1011
|
try {
|
|
@@ -1027,7 +1028,7 @@ function useAssetLoader(options = {}) {
|
|
|
1027
1028
|
},
|
|
1028
1029
|
[]
|
|
1029
1030
|
);
|
|
1030
|
-
const loadOBJ =
|
|
1031
|
+
const loadOBJ = React21.useCallback(
|
|
1031
1032
|
async (url) => {
|
|
1032
1033
|
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1033
1034
|
try {
|
|
@@ -1050,7 +1051,7 @@ function useAssetLoader(options = {}) {
|
|
|
1050
1051
|
},
|
|
1051
1052
|
[]
|
|
1052
1053
|
);
|
|
1053
|
-
const loadTexture =
|
|
1054
|
+
const loadTexture = React21.useCallback(
|
|
1054
1055
|
async (url) => {
|
|
1055
1056
|
setState((prev) => ({ ...prev, isLoading: true }));
|
|
1056
1057
|
try {
|
|
@@ -1073,7 +1074,7 @@ function useAssetLoader(options = {}) {
|
|
|
1073
1074
|
},
|
|
1074
1075
|
[]
|
|
1075
1076
|
);
|
|
1076
|
-
const preload =
|
|
1077
|
+
const preload = React21.useCallback(
|
|
1077
1078
|
async (urls) => {
|
|
1078
1079
|
setState((prev) => ({
|
|
1079
1080
|
...prev,
|
|
@@ -1112,27 +1113,27 @@ function useAssetLoader(options = {}) {
|
|
|
1112
1113
|
},
|
|
1113
1114
|
[updateProgress]
|
|
1114
1115
|
);
|
|
1115
|
-
const hasModel =
|
|
1116
|
+
const hasModel = React21.useCallback((url) => {
|
|
1116
1117
|
return loaderRef.current.hasModel(url);
|
|
1117
1118
|
}, []);
|
|
1118
|
-
const hasTexture =
|
|
1119
|
+
const hasTexture = React21.useCallback((url) => {
|
|
1119
1120
|
return loaderRef.current.hasTexture(url);
|
|
1120
1121
|
}, []);
|
|
1121
|
-
const getModel =
|
|
1122
|
+
const getModel = React21.useCallback((url) => {
|
|
1122
1123
|
try {
|
|
1123
1124
|
return loaderRef.current.getModel(url);
|
|
1124
1125
|
} catch {
|
|
1125
1126
|
return void 0;
|
|
1126
1127
|
}
|
|
1127
1128
|
}, []);
|
|
1128
|
-
const getTexture =
|
|
1129
|
+
const getTexture = React21.useCallback((url) => {
|
|
1129
1130
|
try {
|
|
1130
1131
|
return loaderRef.current.getTexture(url);
|
|
1131
1132
|
} catch {
|
|
1132
1133
|
return void 0;
|
|
1133
1134
|
}
|
|
1134
1135
|
}, []);
|
|
1135
|
-
const clearCache =
|
|
1136
|
+
const clearCache = React21.useCallback(() => {
|
|
1136
1137
|
loaderRef.current.clearCache();
|
|
1137
1138
|
setState({
|
|
1138
1139
|
isLoading: false,
|
|
@@ -1156,25 +1157,25 @@ function useAssetLoader(options = {}) {
|
|
|
1156
1157
|
};
|
|
1157
1158
|
}
|
|
1158
1159
|
function useSceneGraph() {
|
|
1159
|
-
const nodesRef =
|
|
1160
|
-
const addNode =
|
|
1160
|
+
const nodesRef = React21.useRef(/* @__PURE__ */ new Map());
|
|
1161
|
+
const addNode = React21.useCallback((node) => {
|
|
1161
1162
|
const existing = nodesRef.current.get(node.id);
|
|
1162
1163
|
if (existing) {
|
|
1163
1164
|
existing.mesh.removeFromParent();
|
|
1164
1165
|
}
|
|
1165
1166
|
nodesRef.current.set(node.id, node);
|
|
1166
1167
|
}, []);
|
|
1167
|
-
const removeNode =
|
|
1168
|
+
const removeNode = React21.useCallback((id) => {
|
|
1168
1169
|
const node = nodesRef.current.get(id);
|
|
1169
1170
|
if (node) {
|
|
1170
1171
|
node.mesh.removeFromParent();
|
|
1171
1172
|
nodesRef.current.delete(id);
|
|
1172
1173
|
}
|
|
1173
1174
|
}, []);
|
|
1174
|
-
const getNode =
|
|
1175
|
+
const getNode = React21.useCallback((id) => {
|
|
1175
1176
|
return nodesRef.current.get(id);
|
|
1176
1177
|
}, []);
|
|
1177
|
-
const updateNodePosition =
|
|
1178
|
+
const updateNodePosition = React21.useCallback(
|
|
1178
1179
|
(id, x, y, z) => {
|
|
1179
1180
|
const node = nodesRef.current.get(id);
|
|
1180
1181
|
if (node) {
|
|
@@ -1184,7 +1185,7 @@ function useSceneGraph() {
|
|
|
1184
1185
|
},
|
|
1185
1186
|
[]
|
|
1186
1187
|
);
|
|
1187
|
-
const updateNodeGridPosition =
|
|
1188
|
+
const updateNodeGridPosition = React21.useCallback(
|
|
1188
1189
|
(id, gridX, gridZ) => {
|
|
1189
1190
|
const node = nodesRef.current.get(id);
|
|
1190
1191
|
if (node) {
|
|
@@ -1193,7 +1194,7 @@ function useSceneGraph() {
|
|
|
1193
1194
|
},
|
|
1194
1195
|
[]
|
|
1195
1196
|
);
|
|
1196
|
-
const getNodeAtGrid =
|
|
1197
|
+
const getNodeAtGrid = React21.useCallback(
|
|
1197
1198
|
(x, z, type) => {
|
|
1198
1199
|
return Array.from(nodesRef.current.values()).find((node) => {
|
|
1199
1200
|
const matchesGrid = node.gridPosition.x === x && node.gridPosition.z === z;
|
|
@@ -1202,10 +1203,10 @@ function useSceneGraph() {
|
|
|
1202
1203
|
},
|
|
1203
1204
|
[]
|
|
1204
1205
|
);
|
|
1205
|
-
const getNodesByType =
|
|
1206
|
+
const getNodesByType = React21.useCallback((type) => {
|
|
1206
1207
|
return Array.from(nodesRef.current.values()).filter((node) => node.type === type);
|
|
1207
1208
|
}, []);
|
|
1208
|
-
const getNodesInBounds =
|
|
1209
|
+
const getNodesInBounds = React21.useCallback(
|
|
1209
1210
|
(minX, maxX, minZ, maxZ) => {
|
|
1210
1211
|
return Array.from(nodesRef.current.values()).filter((node) => {
|
|
1211
1212
|
const { x, z } = node.gridPosition;
|
|
@@ -1214,13 +1215,13 @@ function useSceneGraph() {
|
|
|
1214
1215
|
},
|
|
1215
1216
|
[]
|
|
1216
1217
|
);
|
|
1217
|
-
const clearNodes =
|
|
1218
|
+
const clearNodes = React21.useCallback(() => {
|
|
1218
1219
|
nodesRef.current.forEach((node) => {
|
|
1219
1220
|
node.mesh.removeFromParent();
|
|
1220
1221
|
});
|
|
1221
1222
|
nodesRef.current.clear();
|
|
1222
1223
|
}, []);
|
|
1223
|
-
const countNodes =
|
|
1224
|
+
const countNodes = React21.useCallback((type) => {
|
|
1224
1225
|
if (!type) {
|
|
1225
1226
|
return nodesRef.current.size;
|
|
1226
1227
|
}
|
|
@@ -1242,9 +1243,9 @@ function useSceneGraph() {
|
|
|
1242
1243
|
}
|
|
1243
1244
|
function useRaycaster(options) {
|
|
1244
1245
|
const { camera, canvas, cellSize = 1, offsetX = 0, offsetZ = 0 } = options;
|
|
1245
|
-
const raycaster =
|
|
1246
|
-
const mouse =
|
|
1247
|
-
const clientToNDC =
|
|
1246
|
+
const raycaster = React21.useRef(new THREE6__namespace.Raycaster());
|
|
1247
|
+
const mouse = React21.useRef(new THREE6__namespace.Vector2());
|
|
1248
|
+
const clientToNDC = React21.useCallback(
|
|
1248
1249
|
(clientX, clientY) => {
|
|
1249
1250
|
if (!canvas) {
|
|
1250
1251
|
return { x: 0, y: 0 };
|
|
@@ -1257,7 +1258,7 @@ function useRaycaster(options) {
|
|
|
1257
1258
|
},
|
|
1258
1259
|
[canvas]
|
|
1259
1260
|
);
|
|
1260
|
-
const isWithinCanvas =
|
|
1261
|
+
const isWithinCanvas = React21.useCallback(
|
|
1261
1262
|
(clientX, clientY) => {
|
|
1262
1263
|
if (!canvas) return false;
|
|
1263
1264
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -1265,7 +1266,7 @@ function useRaycaster(options) {
|
|
|
1265
1266
|
},
|
|
1266
1267
|
[canvas]
|
|
1267
1268
|
);
|
|
1268
|
-
const getIntersection =
|
|
1269
|
+
const getIntersection = React21.useCallback(
|
|
1269
1270
|
(clientX, clientY, objects) => {
|
|
1270
1271
|
if (!camera || !canvas) return null;
|
|
1271
1272
|
const ndc = clientToNDC(clientX, clientY);
|
|
@@ -1288,7 +1289,7 @@ function useRaycaster(options) {
|
|
|
1288
1289
|
},
|
|
1289
1290
|
[camera, canvas, clientToNDC]
|
|
1290
1291
|
);
|
|
1291
|
-
const getAllIntersections =
|
|
1292
|
+
const getAllIntersections = React21.useCallback(
|
|
1292
1293
|
(clientX, clientY, objects) => {
|
|
1293
1294
|
if (!camera || !canvas) return [];
|
|
1294
1295
|
const ndc = clientToNDC(clientX, clientY);
|
|
@@ -1307,7 +1308,7 @@ function useRaycaster(options) {
|
|
|
1307
1308
|
},
|
|
1308
1309
|
[camera, canvas, clientToNDC]
|
|
1309
1310
|
);
|
|
1310
|
-
const getGridCoordinates =
|
|
1311
|
+
const getGridCoordinates = React21.useCallback(
|
|
1311
1312
|
(clientX, clientY) => {
|
|
1312
1313
|
if (!camera || !canvas) return null;
|
|
1313
1314
|
const ndc = clientToNDC(clientX, clientY);
|
|
@@ -1325,7 +1326,7 @@ function useRaycaster(options) {
|
|
|
1325
1326
|
},
|
|
1326
1327
|
[camera, canvas, cellSize, offsetX, offsetZ, clientToNDC]
|
|
1327
1328
|
);
|
|
1328
|
-
const getTileAtPosition =
|
|
1329
|
+
const getTileAtPosition = React21.useCallback(
|
|
1329
1330
|
(clientX, clientY, scene) => {
|
|
1330
1331
|
if (!camera || !canvas) return null;
|
|
1331
1332
|
const tileMeshes = [];
|
|
@@ -1441,12 +1442,12 @@ var fallbackEventBus = {
|
|
|
1441
1442
|
}
|
|
1442
1443
|
};
|
|
1443
1444
|
function useEventBus() {
|
|
1444
|
-
const context =
|
|
1445
|
+
const context = React21.useContext(providers.EventBusContext);
|
|
1445
1446
|
return context ?? getGlobalEventBus() ?? fallbackEventBus;
|
|
1446
1447
|
}
|
|
1447
1448
|
function useEmitEvent() {
|
|
1448
1449
|
const eventBus = useEventBus();
|
|
1449
|
-
return
|
|
1450
|
+
return React21.useCallback(
|
|
1450
1451
|
(type, payload) => {
|
|
1451
1452
|
eventBus.emit(type, payload);
|
|
1452
1453
|
},
|
|
@@ -1473,9 +1474,9 @@ function useGameCanvas3DEvents(options) {
|
|
|
1473
1474
|
onUnitAnimation
|
|
1474
1475
|
} = options;
|
|
1475
1476
|
const emit = useEmitEvent();
|
|
1476
|
-
const optionsRef =
|
|
1477
|
+
const optionsRef = React21.useRef(options);
|
|
1477
1478
|
optionsRef.current = options;
|
|
1478
|
-
const handleTileClick =
|
|
1479
|
+
const handleTileClick = React21.useCallback(
|
|
1479
1480
|
(tile, event) => {
|
|
1480
1481
|
if (tileClickEvent) {
|
|
1481
1482
|
emit(tileClickEvent, {
|
|
@@ -1491,7 +1492,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1491
1492
|
},
|
|
1492
1493
|
[tileClickEvent, emit]
|
|
1493
1494
|
);
|
|
1494
|
-
const handleUnitClick =
|
|
1495
|
+
const handleUnitClick = React21.useCallback(
|
|
1495
1496
|
(unit, event) => {
|
|
1496
1497
|
if (unitClickEvent) {
|
|
1497
1498
|
emit(unitClickEvent, {
|
|
@@ -1510,7 +1511,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1510
1511
|
},
|
|
1511
1512
|
[unitClickEvent, emit]
|
|
1512
1513
|
);
|
|
1513
|
-
const handleFeatureClick =
|
|
1514
|
+
const handleFeatureClick = React21.useCallback(
|
|
1514
1515
|
(feature, event) => {
|
|
1515
1516
|
if (featureClickEvent) {
|
|
1516
1517
|
emit(featureClickEvent, {
|
|
@@ -1525,7 +1526,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1525
1526
|
},
|
|
1526
1527
|
[featureClickEvent, emit]
|
|
1527
1528
|
);
|
|
1528
|
-
const handleCanvasClick =
|
|
1529
|
+
const handleCanvasClick = React21.useCallback(
|
|
1529
1530
|
(event) => {
|
|
1530
1531
|
if (canvasClickEvent) {
|
|
1531
1532
|
emit(canvasClickEvent, {
|
|
@@ -1538,7 +1539,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1538
1539
|
},
|
|
1539
1540
|
[canvasClickEvent, emit]
|
|
1540
1541
|
);
|
|
1541
|
-
const handleTileHover =
|
|
1542
|
+
const handleTileHover = React21.useCallback(
|
|
1542
1543
|
(tile, event) => {
|
|
1543
1544
|
if (tile) {
|
|
1544
1545
|
if (tileHoverEvent) {
|
|
@@ -1558,7 +1559,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1558
1559
|
},
|
|
1559
1560
|
[tileHoverEvent, tileLeaveEvent, emit]
|
|
1560
1561
|
);
|
|
1561
|
-
const handleUnitAnimation =
|
|
1562
|
+
const handleUnitAnimation = React21.useCallback(
|
|
1562
1563
|
(unitId, state) => {
|
|
1563
1564
|
if (unitAnimationEvent) {
|
|
1564
1565
|
emit(unitAnimationEvent, {
|
|
@@ -1571,7 +1572,7 @@ function useGameCanvas3DEvents(options) {
|
|
|
1571
1572
|
},
|
|
1572
1573
|
[unitAnimationEvent, emit]
|
|
1573
1574
|
);
|
|
1574
|
-
const handleCameraChange =
|
|
1575
|
+
const handleCameraChange = React21.useCallback(
|
|
1575
1576
|
(position) => {
|
|
1576
1577
|
if (cameraChangeEvent) {
|
|
1577
1578
|
emit(cameraChangeEvent, {
|
|
@@ -1617,17 +1618,17 @@ function TileRenderer({
|
|
|
1617
1618
|
validMoves = [],
|
|
1618
1619
|
attackTargets = []
|
|
1619
1620
|
}) {
|
|
1620
|
-
const meshRef =
|
|
1621
|
-
const geometry =
|
|
1621
|
+
const meshRef = React21.useRef(null);
|
|
1622
|
+
const geometry = React21.useMemo(() => {
|
|
1622
1623
|
return new THREE6__namespace.BoxGeometry(cellSize * 0.95, 0.2, cellSize * 0.95);
|
|
1623
1624
|
}, [cellSize]);
|
|
1624
|
-
const material =
|
|
1625
|
+
const material = React21.useMemo(() => {
|
|
1625
1626
|
return new THREE6__namespace.MeshStandardMaterial({
|
|
1626
1627
|
roughness: 0.8,
|
|
1627
1628
|
metalness: 0.1
|
|
1628
1629
|
});
|
|
1629
1630
|
}, []);
|
|
1630
|
-
const { positions, colors, tileMap } =
|
|
1631
|
+
const { positions, colors, tileMap } = React21.useMemo(() => {
|
|
1631
1632
|
const pos = [];
|
|
1632
1633
|
const cols = [];
|
|
1633
1634
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -1657,7 +1658,7 @@ function TileRenderer({
|
|
|
1657
1658
|
});
|
|
1658
1659
|
return { positions: pos, colors: cols, tileMap: map };
|
|
1659
1660
|
}, [tiles, cellSize, offsetX, offsetZ, terrainColors, selectedTileIds, validMoves, attackTargets]);
|
|
1660
|
-
|
|
1661
|
+
React21.useEffect(() => {
|
|
1661
1662
|
if (!meshRef.current || !useInstancing) return;
|
|
1662
1663
|
const mesh = meshRef.current;
|
|
1663
1664
|
mesh.count = positions.length;
|
|
@@ -1761,10 +1762,10 @@ function TileRenderer({
|
|
|
1761
1762
|
return /* @__PURE__ */ jsxRuntime.jsx("group", { children: renderIndividualTiles() });
|
|
1762
1763
|
}
|
|
1763
1764
|
function UnitVisual({ unit, position, isSelected, onClick }) {
|
|
1764
|
-
const groupRef =
|
|
1765
|
-
const [animationState, setAnimationState] =
|
|
1766
|
-
const [isHovered, setIsHovered] =
|
|
1767
|
-
const teamColor =
|
|
1765
|
+
const groupRef = React21.useRef(null);
|
|
1766
|
+
const [animationState, setAnimationState] = React21.useState("idle");
|
|
1767
|
+
const [isHovered, setIsHovered] = React21.useState(false);
|
|
1768
|
+
const teamColor = React21.useMemo(() => {
|
|
1768
1769
|
if (unit.faction === "player" || unit.team === "player") return 4491519;
|
|
1769
1770
|
if (unit.faction === "enemy" || unit.team === "enemy") return 16729156;
|
|
1770
1771
|
if (unit.faction === "neutral" || unit.team === "neutral") return 16777028;
|
|
@@ -1776,11 +1777,11 @@ function UnitVisual({ unit, position, isSelected, onClick }) {
|
|
|
1776
1777
|
groupRef.current.position.y = y;
|
|
1777
1778
|
}
|
|
1778
1779
|
});
|
|
1779
|
-
const healthPercent =
|
|
1780
|
+
const healthPercent = React21.useMemo(() => {
|
|
1780
1781
|
if (unit.health === void 0 || unit.maxHealth === void 0) return 1;
|
|
1781
1782
|
return Math.max(0, Math.min(1, unit.health / unit.maxHealth));
|
|
1782
1783
|
}, [unit.health, unit.maxHealth]);
|
|
1783
|
-
const healthColor =
|
|
1784
|
+
const healthColor = React21.useMemo(() => {
|
|
1784
1785
|
if (healthPercent > 0.5) return "#44aa44";
|
|
1785
1786
|
if (healthPercent > 0.25) return "#aaaa44";
|
|
1786
1787
|
return "#ff4444";
|
|
@@ -1841,7 +1842,7 @@ function UnitRenderer({
|
|
|
1841
1842
|
onAnimationStateChange,
|
|
1842
1843
|
animationSpeed = 1
|
|
1843
1844
|
}) {
|
|
1844
|
-
const handleUnitClick =
|
|
1845
|
+
const handleUnitClick = React21__default.default.useCallback(
|
|
1845
1846
|
(unit) => {
|
|
1846
1847
|
onUnitClick?.(unit);
|
|
1847
1848
|
},
|
|
@@ -2054,10 +2055,10 @@ function detectAssetRoot3(modelUrl) {
|
|
|
2054
2055
|
return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
|
|
2055
2056
|
}
|
|
2056
2057
|
function useGLTFModel2(url) {
|
|
2057
|
-
const [model, setModel] =
|
|
2058
|
-
const [isLoading, setIsLoading] =
|
|
2059
|
-
const [error, setError] =
|
|
2060
|
-
|
|
2058
|
+
const [model, setModel] = React21.useState(null);
|
|
2059
|
+
const [isLoading, setIsLoading] = React21.useState(false);
|
|
2060
|
+
const [error, setError] = React21.useState(null);
|
|
2061
|
+
React21.useEffect(() => {
|
|
2061
2062
|
if (!url) {
|
|
2062
2063
|
setModel(null);
|
|
2063
2064
|
return;
|
|
@@ -2089,9 +2090,9 @@ function FeatureModel({
|
|
|
2089
2090
|
onClick,
|
|
2090
2091
|
onHover
|
|
2091
2092
|
}) {
|
|
2092
|
-
const groupRef =
|
|
2093
|
+
const groupRef = React21.useRef(null);
|
|
2093
2094
|
const { model: loadedModel, isLoading } = useGLTFModel2(feature.assetUrl);
|
|
2094
|
-
const model =
|
|
2095
|
+
const model = React21.useMemo(() => {
|
|
2095
2096
|
if (!loadedModel) return null;
|
|
2096
2097
|
const cloned = loadedModel.clone();
|
|
2097
2098
|
cloned.scale.setScalar(0.3);
|
|
@@ -2209,7 +2210,7 @@ function CameraController({
|
|
|
2209
2210
|
onCameraChange
|
|
2210
2211
|
}) {
|
|
2211
2212
|
const { camera } = fiber.useThree();
|
|
2212
|
-
|
|
2213
|
+
React21.useEffect(() => {
|
|
2213
2214
|
if (onCameraChange) {
|
|
2214
2215
|
onCameraChange({
|
|
2215
2216
|
x: camera.position.x,
|
|
@@ -2220,7 +2221,7 @@ function CameraController({
|
|
|
2220
2221
|
}, [camera.position, onCameraChange]);
|
|
2221
2222
|
return null;
|
|
2222
2223
|
}
|
|
2223
|
-
var GameCanvas3D =
|
|
2224
|
+
var GameCanvas3D = React21.forwardRef(
|
|
2224
2225
|
({
|
|
2225
2226
|
tiles = [],
|
|
2226
2227
|
units = [],
|
|
@@ -2265,10 +2266,10 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2265
2266
|
selectedUnitId = null,
|
|
2266
2267
|
children
|
|
2267
2268
|
}, ref) => {
|
|
2268
|
-
const containerRef =
|
|
2269
|
-
const controlsRef =
|
|
2270
|
-
const [hoveredTile, setHoveredTile] =
|
|
2271
|
-
const [internalError, setInternalError] =
|
|
2269
|
+
const containerRef = React21.useRef(null);
|
|
2270
|
+
const controlsRef = React21.useRef(null);
|
|
2271
|
+
const [hoveredTile, setHoveredTile] = React21.useState(null);
|
|
2272
|
+
const [internalError, setInternalError] = React21.useState(null);
|
|
2272
2273
|
const { isLoading: assetsLoading, progress, loaded, total } = useAssetLoader({
|
|
2273
2274
|
preloadUrls: preloadAssets,
|
|
2274
2275
|
loader: customAssetLoader
|
|
@@ -2289,7 +2290,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2289
2290
|
onTileHover,
|
|
2290
2291
|
onUnitAnimation
|
|
2291
2292
|
});
|
|
2292
|
-
const gridBounds =
|
|
2293
|
+
const gridBounds = React21.useMemo(() => {
|
|
2293
2294
|
if (tiles.length === 0) {
|
|
2294
2295
|
return { minX: 0, maxX: 10, minZ: 0, maxZ: 10 };
|
|
2295
2296
|
}
|
|
@@ -2302,14 +2303,14 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2302
2303
|
maxZ: Math.max(...zs)
|
|
2303
2304
|
};
|
|
2304
2305
|
}, [tiles]);
|
|
2305
|
-
const cameraTarget =
|
|
2306
|
+
const cameraTarget = React21.useMemo(() => {
|
|
2306
2307
|
return [
|
|
2307
2308
|
(gridBounds.minX + gridBounds.maxX) / 2,
|
|
2308
2309
|
0,
|
|
2309
2310
|
(gridBounds.minZ + gridBounds.maxZ) / 2
|
|
2310
2311
|
];
|
|
2311
2312
|
}, [gridBounds]);
|
|
2312
|
-
const gridConfig =
|
|
2313
|
+
const gridConfig = React21.useMemo(
|
|
2313
2314
|
() => ({
|
|
2314
2315
|
...DEFAULT_GRID_CONFIG,
|
|
2315
2316
|
offsetX: -(gridBounds.maxX - gridBounds.minX) / 2,
|
|
@@ -2317,7 +2318,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2317
2318
|
}),
|
|
2318
2319
|
[gridBounds]
|
|
2319
2320
|
);
|
|
2320
|
-
const gridToWorld2 =
|
|
2321
|
+
const gridToWorld2 = React21.useCallback(
|
|
2321
2322
|
(x, z, y = 0) => {
|
|
2322
2323
|
const worldX = (x - gridBounds.minX) * gridConfig.cellSize;
|
|
2323
2324
|
const worldZ = (z - gridBounds.minZ) * gridConfig.cellSize;
|
|
@@ -2325,7 +2326,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2325
2326
|
},
|
|
2326
2327
|
[gridBounds, gridConfig]
|
|
2327
2328
|
);
|
|
2328
|
-
|
|
2329
|
+
React21.useImperativeHandle(ref, () => ({
|
|
2329
2330
|
getCameraPosition: () => {
|
|
2330
2331
|
if (controlsRef.current) {
|
|
2331
2332
|
const pos = controlsRef.current.object.position;
|
|
@@ -2363,19 +2364,19 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2363
2364
|
features
|
|
2364
2365
|
})
|
|
2365
2366
|
}));
|
|
2366
|
-
const handleTileClick =
|
|
2367
|
+
const handleTileClick = React21.useCallback(
|
|
2367
2368
|
(tile, event) => {
|
|
2368
2369
|
eventHandlers.handleTileClick(tile, event);
|
|
2369
2370
|
},
|
|
2370
2371
|
[eventHandlers]
|
|
2371
2372
|
);
|
|
2372
|
-
const handleUnitClick =
|
|
2373
|
+
const handleUnitClick = React21.useCallback(
|
|
2373
2374
|
(unit, event) => {
|
|
2374
2375
|
eventHandlers.handleUnitClick(unit, event);
|
|
2375
2376
|
},
|
|
2376
2377
|
[eventHandlers]
|
|
2377
2378
|
);
|
|
2378
|
-
const handleFeatureClick =
|
|
2379
|
+
const handleFeatureClick = React21.useCallback(
|
|
2379
2380
|
(feature, event) => {
|
|
2380
2381
|
if (event) {
|
|
2381
2382
|
eventHandlers.handleFeatureClick(feature, event);
|
|
@@ -2383,7 +2384,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2383
2384
|
},
|
|
2384
2385
|
[eventHandlers]
|
|
2385
2386
|
);
|
|
2386
|
-
const handleTileHover =
|
|
2387
|
+
const handleTileHover = React21.useCallback(
|
|
2387
2388
|
(tile, event) => {
|
|
2388
2389
|
setHoveredTile(tile);
|
|
2389
2390
|
if (event) {
|
|
@@ -2392,7 +2393,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2392
2393
|
},
|
|
2393
2394
|
[eventHandlers]
|
|
2394
2395
|
);
|
|
2395
|
-
const cameraConfig =
|
|
2396
|
+
const cameraConfig = React21.useMemo(() => {
|
|
2396
2397
|
const size = Math.max(
|
|
2397
2398
|
gridBounds.maxX - gridBounds.minX,
|
|
2398
2399
|
gridBounds.maxZ - gridBounds.minZ
|
|
@@ -2417,7 +2418,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2417
2418
|
};
|
|
2418
2419
|
}
|
|
2419
2420
|
}, [cameraMode, gridBounds]);
|
|
2420
|
-
const DefaultTileRenderer =
|
|
2421
|
+
const DefaultTileRenderer = React21.useCallback(
|
|
2421
2422
|
({ tile, position }) => {
|
|
2422
2423
|
const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
|
|
2423
2424
|
const isHovered = hoveredTile?.id === tile.id;
|
|
@@ -2455,7 +2456,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2455
2456
|
},
|
|
2456
2457
|
[selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
|
|
2457
2458
|
);
|
|
2458
|
-
const DefaultUnitRenderer =
|
|
2459
|
+
const DefaultUnitRenderer = React21.useCallback(
|
|
2459
2460
|
({ unit, position }) => {
|
|
2460
2461
|
const isSelected = selectedUnitId === unit.id;
|
|
2461
2462
|
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
@@ -2513,7 +2514,7 @@ var GameCanvas3D = React7.forwardRef(
|
|
|
2513
2514
|
},
|
|
2514
2515
|
[selectedUnitId, handleUnitClick]
|
|
2515
2516
|
);
|
|
2516
|
-
const DefaultFeatureRenderer =
|
|
2517
|
+
const DefaultFeatureRenderer = React21.useCallback(
|
|
2517
2518
|
({
|
|
2518
2519
|
feature,
|
|
2519
2520
|
position
|
|
@@ -2820,7 +2821,7 @@ var positionStyles = {
|
|
|
2820
2821
|
fixed: "fixed",
|
|
2821
2822
|
sticky: "sticky"
|
|
2822
2823
|
};
|
|
2823
|
-
var Box =
|
|
2824
|
+
var Box = React21__default.default.forwardRef(
|
|
2824
2825
|
({
|
|
2825
2826
|
padding,
|
|
2826
2827
|
paddingX,
|
|
@@ -2849,20 +2850,20 @@ var Box = React7__default.default.forwardRef(
|
|
|
2849
2850
|
...rest
|
|
2850
2851
|
}, ref) => {
|
|
2851
2852
|
const eventBus = useEventBus();
|
|
2852
|
-
const handleClick =
|
|
2853
|
+
const handleClick = React21.useCallback((e) => {
|
|
2853
2854
|
if (action) {
|
|
2854
2855
|
e.stopPropagation();
|
|
2855
2856
|
eventBus.emit(`UI:${action}`, actionPayload ?? {});
|
|
2856
2857
|
}
|
|
2857
2858
|
onClick?.(e);
|
|
2858
2859
|
}, [action, actionPayload, eventBus, onClick]);
|
|
2859
|
-
const handleMouseEnter =
|
|
2860
|
+
const handleMouseEnter = React21.useCallback((e) => {
|
|
2860
2861
|
if (hoverEvent) {
|
|
2861
2862
|
eventBus.emit(`UI:${hoverEvent}`, { hovered: true });
|
|
2862
2863
|
}
|
|
2863
2864
|
onMouseEnter?.(e);
|
|
2864
2865
|
}, [hoverEvent, eventBus, onMouseEnter]);
|
|
2865
|
-
const handleMouseLeave =
|
|
2866
|
+
const handleMouseLeave = React21.useCallback((e) => {
|
|
2866
2867
|
if (hoverEvent) {
|
|
2867
2868
|
eventBus.emit(`UI:${hoverEvent}`, { hovered: false });
|
|
2868
2869
|
}
|
|
@@ -3364,6 +3365,2418 @@ function normalizeMouseCoordinates(clientX, clientY, element) {
|
|
|
3364
3365
|
y: -((clientY - rect.top) / rect.height) * 2 + 1
|
|
3365
3366
|
};
|
|
3366
3367
|
}
|
|
3368
|
+
|
|
3369
|
+
// components/organisms/avl/avl-schema-parser.ts
|
|
3370
|
+
function getEntity(orbital) {
|
|
3371
|
+
const entity = orbital.entity;
|
|
3372
|
+
if (typeof entity === "string") {
|
|
3373
|
+
return { name: entity, fields: [], persistence: "runtime" };
|
|
3374
|
+
}
|
|
3375
|
+
const e = entity;
|
|
3376
|
+
return {
|
|
3377
|
+
name: e.name ?? orbital.name,
|
|
3378
|
+
fields: e.fields ?? [],
|
|
3379
|
+
persistence: e.persistence ?? "runtime"
|
|
3380
|
+
};
|
|
3381
|
+
}
|
|
3382
|
+
function getTraits(orbital) {
|
|
3383
|
+
if (!orbital.traits) return [];
|
|
3384
|
+
return orbital.traits.map((t) => {
|
|
3385
|
+
if (typeof t === "string") return { name: t };
|
|
3386
|
+
return t;
|
|
3387
|
+
});
|
|
3388
|
+
}
|
|
3389
|
+
function getPages(orbital) {
|
|
3390
|
+
if (!orbital.pages) return [];
|
|
3391
|
+
return orbital.pages.map((p) => {
|
|
3392
|
+
if (typeof p === "string") return { name: p, path: `/${p.toLowerCase()}` };
|
|
3393
|
+
return p;
|
|
3394
|
+
});
|
|
3395
|
+
}
|
|
3396
|
+
function getStateMachine(trait) {
|
|
3397
|
+
return trait.stateMachine ?? null;
|
|
3398
|
+
}
|
|
3399
|
+
function getStates(sm) {
|
|
3400
|
+
return sm.states ?? [];
|
|
3401
|
+
}
|
|
3402
|
+
function getTransitions(sm) {
|
|
3403
|
+
return sm.transitions ?? [];
|
|
3404
|
+
}
|
|
3405
|
+
function getEvents(sm) {
|
|
3406
|
+
return sm.events ?? [];
|
|
3407
|
+
}
|
|
3408
|
+
function getEmits(trait) {
|
|
3409
|
+
const emits = trait.emits;
|
|
3410
|
+
if (!emits) return [];
|
|
3411
|
+
return emits.map((e) => typeof e === "string" ? e : e.event ?? e.name ?? "");
|
|
3412
|
+
}
|
|
3413
|
+
function getListens(trait) {
|
|
3414
|
+
const listens = trait.listens;
|
|
3415
|
+
if (!listens) return [];
|
|
3416
|
+
return listens.map((l) => typeof l === "string" ? l : l.event ?? "");
|
|
3417
|
+
}
|
|
3418
|
+
function parseEffectType(effect) {
|
|
3419
|
+
if (Array.isArray(effect)) {
|
|
3420
|
+
const [type, ...args] = effect;
|
|
3421
|
+
return { type: String(type), args };
|
|
3422
|
+
}
|
|
3423
|
+
return { type: "unknown", args: [] };
|
|
3424
|
+
}
|
|
3425
|
+
function exprToTree(expr) {
|
|
3426
|
+
if (Array.isArray(expr)) {
|
|
3427
|
+
const [op, ...args] = expr;
|
|
3428
|
+
return {
|
|
3429
|
+
label: String(op),
|
|
3430
|
+
type: "operator",
|
|
3431
|
+
children: args.map((a) => exprToTree(a))
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
3434
|
+
if (typeof expr === "string") {
|
|
3435
|
+
if (expr.startsWith("@")) {
|
|
3436
|
+
return { label: expr, type: "binding" };
|
|
3437
|
+
}
|
|
3438
|
+
return { label: expr, type: "literal" };
|
|
3439
|
+
}
|
|
3440
|
+
return { label: String(expr), type: "literal" };
|
|
3441
|
+
}
|
|
3442
|
+
function parseApplicationLevel(schema) {
|
|
3443
|
+
const orbitals = [];
|
|
3444
|
+
const crossLinks = [];
|
|
3445
|
+
const count = schema.orbitals.length;
|
|
3446
|
+
const cols = Math.ceil(Math.sqrt(count));
|
|
3447
|
+
const rows = Math.ceil(count / cols);
|
|
3448
|
+
const spacing = 200;
|
|
3449
|
+
const gridW = cols * spacing;
|
|
3450
|
+
const gridH = rows * spacing;
|
|
3451
|
+
const originX = (600 - gridW) / 2 + spacing / 2;
|
|
3452
|
+
const originY = (400 - gridH) / 2 + spacing / 2;
|
|
3453
|
+
schema.orbitals.forEach((orbital, i) => {
|
|
3454
|
+
const entity = getEntity(orbital);
|
|
3455
|
+
const traits = getTraits(orbital);
|
|
3456
|
+
const pages = getPages(orbital);
|
|
3457
|
+
orbitals.push({
|
|
3458
|
+
name: orbital.name,
|
|
3459
|
+
entityName: entity.name,
|
|
3460
|
+
fieldCount: entity.fields.length,
|
|
3461
|
+
persistence: entity.persistence,
|
|
3462
|
+
traitNames: traits.map((t) => t.name ?? ""),
|
|
3463
|
+
pageNames: pages.map((p) => p.name ?? ""),
|
|
3464
|
+
position: {
|
|
3465
|
+
x: originX + i % cols * spacing,
|
|
3466
|
+
y: originY + Math.floor(i / cols) * spacing
|
|
3467
|
+
}
|
|
3468
|
+
});
|
|
3469
|
+
});
|
|
3470
|
+
const emitMap = [];
|
|
3471
|
+
const listenMap = [];
|
|
3472
|
+
for (const orbital of schema.orbitals) {
|
|
3473
|
+
for (const traitRef of getTraits(orbital)) {
|
|
3474
|
+
const traitName = traitRef.name ?? "";
|
|
3475
|
+
for (const event of getEmits(traitRef)) {
|
|
3476
|
+
emitMap.push({ orbital: orbital.name, trait: traitName, event });
|
|
3477
|
+
}
|
|
3478
|
+
for (const event of getListens(traitRef)) {
|
|
3479
|
+
listenMap.push({ orbital: orbital.name, trait: traitName, event });
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
for (const emit of emitMap) {
|
|
3484
|
+
for (const listen of listenMap) {
|
|
3485
|
+
if (emit.event === listen.event && emit.orbital !== listen.orbital) {
|
|
3486
|
+
crossLinks.push({
|
|
3487
|
+
emitterOrbital: emit.orbital,
|
|
3488
|
+
listenerOrbital: listen.orbital,
|
|
3489
|
+
eventName: emit.event,
|
|
3490
|
+
emitterTrait: emit.trait,
|
|
3491
|
+
listenerTrait: listen.trait
|
|
3492
|
+
});
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
return { orbitals, crossLinks };
|
|
3497
|
+
}
|
|
3498
|
+
function parseOrbitalLevel(schema, orbitalName) {
|
|
3499
|
+
const orbital = schema.orbitals.find((o) => o.name === orbitalName);
|
|
3500
|
+
if (!orbital) return null;
|
|
3501
|
+
const entity = getEntity(orbital);
|
|
3502
|
+
const traits = getTraits(orbital);
|
|
3503
|
+
const pages = getPages(orbital);
|
|
3504
|
+
const fields = entity.fields.map((f) => ({
|
|
3505
|
+
name: f.name ?? "",
|
|
3506
|
+
type: f.type ?? "string",
|
|
3507
|
+
required: f.required ?? false,
|
|
3508
|
+
hasDefault: f.default !== void 0
|
|
3509
|
+
}));
|
|
3510
|
+
const traitInfos = traits.map((t) => {
|
|
3511
|
+
const sm = getStateMachine(t);
|
|
3512
|
+
return {
|
|
3513
|
+
name: t.name ?? "",
|
|
3514
|
+
stateCount: sm ? getStates(sm).length : 0,
|
|
3515
|
+
eventCount: sm ? getEvents(sm).length : 0,
|
|
3516
|
+
transitionCount: sm ? getTransitions(sm).length : 0,
|
|
3517
|
+
emits: getEmits(t),
|
|
3518
|
+
listens: getListens(t)
|
|
3519
|
+
};
|
|
3520
|
+
});
|
|
3521
|
+
const pageInfos = pages.map((p) => ({
|
|
3522
|
+
name: p.name ?? "",
|
|
3523
|
+
route: p.path ?? `/${(p.name ?? "").toLowerCase()}`
|
|
3524
|
+
}));
|
|
3525
|
+
const externalLinks = [];
|
|
3526
|
+
const thisTraitEmits = traits.flatMap((t) => getEmits(t).map((e) => ({ trait: t.name ?? "", event: e })));
|
|
3527
|
+
const thisTraitListens = traits.flatMap((t) => getListens(t).map((e) => ({ trait: t.name ?? "", event: e })));
|
|
3528
|
+
for (const other of schema.orbitals) {
|
|
3529
|
+
if (other.name === orbitalName) continue;
|
|
3530
|
+
const otherTraits = getTraits(other);
|
|
3531
|
+
const otherListens = otherTraits.flatMap((t) => getListens(t));
|
|
3532
|
+
const otherEmits = otherTraits.flatMap((t) => getEmits(t));
|
|
3533
|
+
for (const emit of thisTraitEmits) {
|
|
3534
|
+
if (otherListens.includes(emit.event)) {
|
|
3535
|
+
externalLinks.push({
|
|
3536
|
+
targetOrbital: other.name,
|
|
3537
|
+
eventName: emit.event,
|
|
3538
|
+
direction: "out",
|
|
3539
|
+
traitName: emit.trait
|
|
3540
|
+
});
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
for (const listen of thisTraitListens) {
|
|
3544
|
+
if (otherEmits.includes(listen.event)) {
|
|
3545
|
+
externalLinks.push({
|
|
3546
|
+
targetOrbital: other.name,
|
|
3547
|
+
eventName: listen.event,
|
|
3548
|
+
direction: "in",
|
|
3549
|
+
traitName: listen.trait
|
|
3550
|
+
});
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3554
|
+
return {
|
|
3555
|
+
name: orbital.name,
|
|
3556
|
+
entity: {
|
|
3557
|
+
name: entity.name,
|
|
3558
|
+
fields,
|
|
3559
|
+
persistence: entity.persistence
|
|
3560
|
+
},
|
|
3561
|
+
traits: traitInfos,
|
|
3562
|
+
pages: pageInfos,
|
|
3563
|
+
externalLinks
|
|
3564
|
+
};
|
|
3565
|
+
}
|
|
3566
|
+
function parseTraitLevel(schema, orbitalName, traitName) {
|
|
3567
|
+
const orbital = schema.orbitals.find((o) => o.name === orbitalName);
|
|
3568
|
+
if (!orbital) return null;
|
|
3569
|
+
const traits = getTraits(orbital);
|
|
3570
|
+
const trait = traits.find((t) => t.name === traitName);
|
|
3571
|
+
if (!trait) return null;
|
|
3572
|
+
const sm = getStateMachine(trait);
|
|
3573
|
+
if (!sm) return null;
|
|
3574
|
+
const states = getStates(sm).map((s) => ({
|
|
3575
|
+
name: s.name ?? "",
|
|
3576
|
+
isInitial: s.isInitial ?? false,
|
|
3577
|
+
isTerminal: s.isTerminal ?? false
|
|
3578
|
+
}));
|
|
3579
|
+
const transitions = getTransitions(sm).map((t, i) => ({
|
|
3580
|
+
from: t.from ?? "",
|
|
3581
|
+
to: t.to ?? "",
|
|
3582
|
+
event: t.event ?? "",
|
|
3583
|
+
guard: t.guard,
|
|
3584
|
+
effects: (t.effects ?? []).map(parseEffectType),
|
|
3585
|
+
index: i
|
|
3586
|
+
}));
|
|
3587
|
+
const entity = getEntity(orbital);
|
|
3588
|
+
return {
|
|
3589
|
+
name: traitName,
|
|
3590
|
+
linkedEntity: entity.name,
|
|
3591
|
+
states,
|
|
3592
|
+
transitions,
|
|
3593
|
+
emittedEvents: getEmits(trait),
|
|
3594
|
+
listenedEvents: getListens(trait)
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
function parseTransitionLevel(schema, orbitalName, traitName, transitionIndex) {
|
|
3598
|
+
const traitData = parseTraitLevel(schema, orbitalName, traitName);
|
|
3599
|
+
if (!traitData) return null;
|
|
3600
|
+
const transition = traitData.transitions[transitionIndex];
|
|
3601
|
+
if (!transition) return null;
|
|
3602
|
+
const guard = transition.guard ? exprToTree(transition.guard) : null;
|
|
3603
|
+
const effects = transition.effects.map(
|
|
3604
|
+
(e) => exprToTree([e.type, ...e.args])
|
|
3605
|
+
);
|
|
3606
|
+
const slotTargets = transition.effects.filter((e) => e.type === "render-ui").map((e) => ({
|
|
3607
|
+
name: String(e.args[0] ?? "main"),
|
|
3608
|
+
pattern: typeof e.args[1] === "object" && e.args[1] !== null ? e.args[1].type ?? "unknown" : String(e.args[1] ?? "unknown")
|
|
3609
|
+
}));
|
|
3610
|
+
return {
|
|
3611
|
+
from: transition.from,
|
|
3612
|
+
to: transition.to,
|
|
3613
|
+
event: transition.event,
|
|
3614
|
+
guard,
|
|
3615
|
+
effects,
|
|
3616
|
+
slotTargets
|
|
3617
|
+
};
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
// components/organisms/avl/avl-zoom-state.ts
|
|
3621
|
+
var initialZoomState = {
|
|
3622
|
+
level: "application",
|
|
3623
|
+
selectedOrbital: null,
|
|
3624
|
+
selectedTrait: null,
|
|
3625
|
+
selectedTransition: null,
|
|
3626
|
+
animating: false,
|
|
3627
|
+
animationDirection: "in",
|
|
3628
|
+
animationTarget: null
|
|
3629
|
+
};
|
|
3630
|
+
function zoomReducer(state, action) {
|
|
3631
|
+
switch (action.type) {
|
|
3632
|
+
case "ZOOM_INTO_ORBITAL": {
|
|
3633
|
+
if (state.level !== "application" || state.animating) return state;
|
|
3634
|
+
return {
|
|
3635
|
+
...state,
|
|
3636
|
+
animating: true,
|
|
3637
|
+
animationDirection: "in",
|
|
3638
|
+
animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
|
|
3639
|
+
selectedOrbital: action.orbital
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3642
|
+
case "ZOOM_INTO_TRAIT": {
|
|
3643
|
+
if (state.level !== "orbital" || state.animating) return state;
|
|
3644
|
+
return {
|
|
3645
|
+
...state,
|
|
3646
|
+
animating: true,
|
|
3647
|
+
animationDirection: "in",
|
|
3648
|
+
animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
|
|
3649
|
+
selectedTrait: action.trait
|
|
3650
|
+
};
|
|
3651
|
+
}
|
|
3652
|
+
case "ZOOM_INTO_TRANSITION": {
|
|
3653
|
+
if (state.level !== "trait" || state.animating) return state;
|
|
3654
|
+
return {
|
|
3655
|
+
...state,
|
|
3656
|
+
animating: true,
|
|
3657
|
+
animationDirection: "in",
|
|
3658
|
+
animationTarget: { x: action.targetPosition.x, y: action.targetPosition.y, scale: 3 },
|
|
3659
|
+
selectedTransition: action.transitionIndex
|
|
3660
|
+
};
|
|
3661
|
+
}
|
|
3662
|
+
case "ZOOM_OUT": {
|
|
3663
|
+
if (state.level === "application" || state.animating) return state;
|
|
3664
|
+
return {
|
|
3665
|
+
...state,
|
|
3666
|
+
animating: true,
|
|
3667
|
+
animationDirection: "out",
|
|
3668
|
+
animationTarget: { x: 300, y: 200, scale: 0.3 }
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
case "ANIMATION_COMPLETE": {
|
|
3672
|
+
if (!state.animating) return state;
|
|
3673
|
+
if (state.animationDirection === "in") {
|
|
3674
|
+
const nextLevel = state.level === "application" ? "orbital" : state.level === "orbital" ? "trait" : "transition";
|
|
3675
|
+
return {
|
|
3676
|
+
...state,
|
|
3677
|
+
level: nextLevel,
|
|
3678
|
+
animating: false,
|
|
3679
|
+
animationTarget: null
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3682
|
+
if (state.level === "transition") {
|
|
3683
|
+
return {
|
|
3684
|
+
...state,
|
|
3685
|
+
level: "trait",
|
|
3686
|
+
selectedTransition: null,
|
|
3687
|
+
animating: false,
|
|
3688
|
+
animationTarget: null
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
if (state.level === "trait") {
|
|
3692
|
+
return {
|
|
3693
|
+
...state,
|
|
3694
|
+
level: "orbital",
|
|
3695
|
+
selectedTrait: null,
|
|
3696
|
+
animating: false,
|
|
3697
|
+
animationTarget: null
|
|
3698
|
+
};
|
|
3699
|
+
}
|
|
3700
|
+
if (state.level === "orbital") {
|
|
3701
|
+
return {
|
|
3702
|
+
...state,
|
|
3703
|
+
level: "application",
|
|
3704
|
+
selectedOrbital: null,
|
|
3705
|
+
animating: false,
|
|
3706
|
+
animationTarget: null
|
|
3707
|
+
};
|
|
3708
|
+
}
|
|
3709
|
+
return state;
|
|
3710
|
+
}
|
|
3711
|
+
case "SWITCH_TRAIT": {
|
|
3712
|
+
if (state.level !== "trait" || state.animating) return state;
|
|
3713
|
+
return {
|
|
3714
|
+
...state,
|
|
3715
|
+
selectedTrait: action.trait,
|
|
3716
|
+
selectedTransition: null
|
|
3717
|
+
};
|
|
3718
|
+
}
|
|
3719
|
+
case "RESET": {
|
|
3720
|
+
return initialZoomState;
|
|
3721
|
+
}
|
|
3722
|
+
default:
|
|
3723
|
+
return state;
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3726
|
+
function getBreadcrumbs(state) {
|
|
3727
|
+
const crumbs = [{ label: "Application", level: "application" }];
|
|
3728
|
+
if (state.selectedOrbital) {
|
|
3729
|
+
crumbs.push({ label: state.selectedOrbital, level: "orbital" });
|
|
3730
|
+
}
|
|
3731
|
+
if (state.selectedTrait) {
|
|
3732
|
+
crumbs.push({ label: state.selectedTrait, level: "trait" });
|
|
3733
|
+
}
|
|
3734
|
+
if (state.selectedTransition !== null) {
|
|
3735
|
+
crumbs.push({ label: `Transition #${state.selectedTransition}`, level: "transition" });
|
|
3736
|
+
}
|
|
3737
|
+
return crumbs;
|
|
3738
|
+
}
|
|
3739
|
+
var AVL_3D_COLORS = {
|
|
3740
|
+
// Orbital node: deep indigo body with soft cyan-blue rim glow
|
|
3741
|
+
orbitalSphere: "#161b2e",
|
|
3742
|
+
orbitalRim: "#5b9bd5",
|
|
3743
|
+
// Entity core: warm amber-gold (slightly desaturated for dark bg)
|
|
3744
|
+
entityCore: "#f0c040",
|
|
3745
|
+
entityCoreGlow: "#ffd866",
|
|
3746
|
+
// Trait orbit ring
|
|
3747
|
+
traitOrbit: "#5b9bd5",
|
|
3748
|
+
traitOrbitHighlight: "#7ab8f5",
|
|
3749
|
+
// State nodes
|
|
3750
|
+
stateIdle: "#1e2a3a",
|
|
3751
|
+
stateEdge: "#5b9bd5",
|
|
3752
|
+
stateActive: "#4ecb71",
|
|
3753
|
+
// Transitions: warm copper-orange
|
|
3754
|
+
transitionArc: "#e0944a",
|
|
3755
|
+
transitionArcHover: "#f0a860",
|
|
3756
|
+
// Guards
|
|
3757
|
+
guardPass: "#4ecb71",
|
|
3758
|
+
guardFail: "#f06060",
|
|
3759
|
+
// Cross-orbital wires: soft lavender
|
|
3760
|
+
crossWire: "#a78bda",
|
|
3761
|
+
crossWireGlow: "#c4a8f0",
|
|
3762
|
+
// Page portals: soft teal
|
|
3763
|
+
pagePortal: "#40c8aa",
|
|
3764
|
+
// Background: deep navy with blue undertone (not pure black)
|
|
3765
|
+
background: "#0c1222",
|
|
3766
|
+
backgroundSurface: "#111a2e",
|
|
3767
|
+
// Fog: matches background for seamless fade
|
|
3768
|
+
fog: "#0c1222",
|
|
3769
|
+
// Sparkle/particle accent
|
|
3770
|
+
sparkle: "#7ab8f5",
|
|
3771
|
+
sparkleWarm: "#f0c040"
|
|
3772
|
+
};
|
|
3773
|
+
var GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));
|
|
3774
|
+
function goldenSpiralPositions(count, baseRadius) {
|
|
3775
|
+
if (count === 0) return [];
|
|
3776
|
+
if (count === 1) return [{ x: 0, y: 0, z: 0 }];
|
|
3777
|
+
const positions = [];
|
|
3778
|
+
for (let i = 0; i < count; i++) {
|
|
3779
|
+
const angle = i * GOLDEN_ANGLE;
|
|
3780
|
+
const r = baseRadius * Math.sqrt(i / count);
|
|
3781
|
+
positions.push({
|
|
3782
|
+
x: r * Math.cos(angle),
|
|
3783
|
+
y: 0,
|
|
3784
|
+
z: r * Math.sin(angle)
|
|
3785
|
+
});
|
|
3786
|
+
}
|
|
3787
|
+
return positions;
|
|
3788
|
+
}
|
|
3789
|
+
function forceDirectedPositions(count, edges, baseRadius, iterations = 80) {
|
|
3790
|
+
if (count === 0) return [];
|
|
3791
|
+
if (count === 1) return [{ x: 0, y: 0, z: 0 }];
|
|
3792
|
+
const positions = goldenSpiralPositions(count, baseRadius);
|
|
3793
|
+
const repulsionStrength = baseRadius * baseRadius * 0.5;
|
|
3794
|
+
const attractionStrength = 0.15;
|
|
3795
|
+
const damping = 0.85;
|
|
3796
|
+
const velocities = positions.map(() => ({ x: 0, y: 0, z: 0 }));
|
|
3797
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
3798
|
+
for (let i = 0; i < count; i++) {
|
|
3799
|
+
for (let j = i + 1; j < count; j++) {
|
|
3800
|
+
const dx = positions[i].x - positions[j].x;
|
|
3801
|
+
const dz = positions[i].z - positions[j].z;
|
|
3802
|
+
const distSq = dx * dx + dz * dz + 0.01;
|
|
3803
|
+
const force = repulsionStrength / distSq;
|
|
3804
|
+
const dist = Math.sqrt(distSq);
|
|
3805
|
+
const fx = dx / dist * force;
|
|
3806
|
+
const fz = dz / dist * force;
|
|
3807
|
+
velocities[i].x += fx;
|
|
3808
|
+
velocities[i].z += fz;
|
|
3809
|
+
velocities[j].x -= fx;
|
|
3810
|
+
velocities[j].z -= fz;
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
for (const edge of edges) {
|
|
3814
|
+
const dx = positions[edge.to].x - positions[edge.from].x;
|
|
3815
|
+
const dz = positions[edge.to].z - positions[edge.from].z;
|
|
3816
|
+
const dist = Math.sqrt(dx * dx + dz * dz + 0.01);
|
|
3817
|
+
const force = dist * attractionStrength;
|
|
3818
|
+
const fx = dx / dist * force;
|
|
3819
|
+
const fz = dz / dist * force;
|
|
3820
|
+
velocities[edge.from].x += fx;
|
|
3821
|
+
velocities[edge.from].z += fz;
|
|
3822
|
+
velocities[edge.to].x -= fx;
|
|
3823
|
+
velocities[edge.to].z -= fz;
|
|
3824
|
+
}
|
|
3825
|
+
for (let i = 0; i < count; i++) {
|
|
3826
|
+
positions[i].x += velocities[i].x * 0.1;
|
|
3827
|
+
positions[i].z += velocities[i].z * 0.1;
|
|
3828
|
+
velocities[i].x *= damping;
|
|
3829
|
+
velocities[i].z *= damping;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
let cx = 0, cz = 0;
|
|
3833
|
+
for (const p of positions) {
|
|
3834
|
+
cx += p.x;
|
|
3835
|
+
cz += p.z;
|
|
3836
|
+
}
|
|
3837
|
+
cx /= count;
|
|
3838
|
+
cz /= count;
|
|
3839
|
+
for (const p of positions) {
|
|
3840
|
+
p.x -= cx;
|
|
3841
|
+
p.z -= cz;
|
|
3842
|
+
}
|
|
3843
|
+
return positions;
|
|
3844
|
+
}
|
|
3845
|
+
function fibonacciSpherePositions(count, radius) {
|
|
3846
|
+
if (count === 0) return [];
|
|
3847
|
+
if (count === 1) return [{ x: 0, y: 0, z: 0 }];
|
|
3848
|
+
const positions = [];
|
|
3849
|
+
for (let i = 0; i < count; i++) {
|
|
3850
|
+
const y = 1 - 2 * i / (count - 1);
|
|
3851
|
+
const radiusAtY = Math.sqrt(1 - y * y);
|
|
3852
|
+
const theta = GOLDEN_ANGLE * i;
|
|
3853
|
+
positions.push({
|
|
3854
|
+
x: radius * radiusAtY * Math.cos(theta),
|
|
3855
|
+
y: radius * y,
|
|
3856
|
+
z: radius * radiusAtY * Math.sin(theta)
|
|
3857
|
+
});
|
|
3858
|
+
}
|
|
3859
|
+
return positions;
|
|
3860
|
+
}
|
|
3861
|
+
function orbitRingPositions(count, radius, tilt) {
|
|
3862
|
+
if (count === 0) return [];
|
|
3863
|
+
const positions = [];
|
|
3864
|
+
const step = 2 * Math.PI / count;
|
|
3865
|
+
for (let i = 0; i < count; i++) {
|
|
3866
|
+
const angle = i * step;
|
|
3867
|
+
const x = radius * Math.cos(angle);
|
|
3868
|
+
const flatZ = radius * Math.sin(angle);
|
|
3869
|
+
const y = flatZ * Math.sin(tilt);
|
|
3870
|
+
const z = flatZ * Math.cos(tilt);
|
|
3871
|
+
positions.push({ x, y, z });
|
|
3872
|
+
}
|
|
3873
|
+
return positions;
|
|
3874
|
+
}
|
|
3875
|
+
function arcCurve3D(from, to, offset) {
|
|
3876
|
+
const start = new THREE6.Vector3(...from);
|
|
3877
|
+
const end = new THREE6.Vector3(...to);
|
|
3878
|
+
const mid = new THREE6.Vector3().addVectors(start, end).multiplyScalar(0.5);
|
|
3879
|
+
const dir = new THREE6.Vector3().subVectors(end, start).normalize();
|
|
3880
|
+
const up = new THREE6.Vector3(0, 1, 0);
|
|
3881
|
+
const perp = new THREE6.Vector3().crossVectors(dir, up).normalize();
|
|
3882
|
+
if (perp.length() < 1e-3) {
|
|
3883
|
+
perp.crossVectors(dir, new THREE6.Vector3(1, 0, 0)).normalize();
|
|
3884
|
+
}
|
|
3885
|
+
const control = mid.clone().add(perp.multiplyScalar(offset));
|
|
3886
|
+
control.y += Math.abs(offset) * 0.3;
|
|
3887
|
+
return new THREE6.QuadraticBezierCurve3(start, control, end);
|
|
3888
|
+
}
|
|
3889
|
+
function selfLoopCurve3D(position, loopRadius) {
|
|
3890
|
+
const base = new THREE6.Vector3(...position);
|
|
3891
|
+
const start = base.clone().add(new THREE6.Vector3(-loopRadius * 0.3, 0, 0));
|
|
3892
|
+
const end = base.clone().add(new THREE6.Vector3(loopRadius * 0.3, 0, 0));
|
|
3893
|
+
const control = base.clone().add(new THREE6.Vector3(0, loopRadius, 0));
|
|
3894
|
+
return new THREE6.QuadraticBezierCurve3(start, control, end);
|
|
3895
|
+
}
|
|
3896
|
+
function treeLayout3D(node, origin, horizontalSpacing, verticalSpacing = 2) {
|
|
3897
|
+
const results = [];
|
|
3898
|
+
function layoutNode(n, pos, depth) {
|
|
3899
|
+
results.push({ node: n, position: pos });
|
|
3900
|
+
if (!n.children || n.children.length === 0) return;
|
|
3901
|
+
const childCount = n.children.length;
|
|
3902
|
+
const totalWidth = (childCount - 1) * horizontalSpacing / (depth + 1);
|
|
3903
|
+
const startX = pos.x - totalWidth / 2;
|
|
3904
|
+
for (let i = 0; i < childCount; i++) {
|
|
3905
|
+
const childPos = {
|
|
3906
|
+
x: startX + i * totalWidth / Math.max(childCount - 1, 1),
|
|
3907
|
+
y: pos.y - verticalSpacing,
|
|
3908
|
+
z: pos.z
|
|
3909
|
+
};
|
|
3910
|
+
layoutNode(n.children[i], childPos, depth + 1);
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
layoutNode(node, origin, 0);
|
|
3914
|
+
return results;
|
|
3915
|
+
}
|
|
3916
|
+
var CAMERA_POSITIONS = {
|
|
3917
|
+
application: { position: [0, 20, 30], target: [0, 0, 0] },
|
|
3918
|
+
orbital: { position: [0, 8, 12], target: [0, 0, 0] },
|
|
3919
|
+
trait: { position: [0, 6, 10], target: [0, 0, 0] },
|
|
3920
|
+
transition: { position: [0, 4, 8], target: [0, 0, 0] }
|
|
3921
|
+
};
|
|
3922
|
+
var Avl3DLabel = ({
|
|
3923
|
+
position,
|
|
3924
|
+
text,
|
|
3925
|
+
color = "#ffffff",
|
|
3926
|
+
fontSize = 12,
|
|
3927
|
+
className,
|
|
3928
|
+
occlude = false
|
|
3929
|
+
}) => {
|
|
3930
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3931
|
+
drei.Html,
|
|
3932
|
+
{
|
|
3933
|
+
position,
|
|
3934
|
+
center: true,
|
|
3935
|
+
distanceFactor: 10,
|
|
3936
|
+
occlude: occlude ? "blending" : void 0,
|
|
3937
|
+
className,
|
|
3938
|
+
style: { pointerEvents: "none" },
|
|
3939
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3940
|
+
Typography,
|
|
3941
|
+
{
|
|
3942
|
+
variant: "small",
|
|
3943
|
+
style: {
|
|
3944
|
+
color,
|
|
3945
|
+
fontSize: `${fontSize}px`,
|
|
3946
|
+
whiteSpace: "nowrap",
|
|
3947
|
+
textShadow: "0 0 4px rgba(0,0,0,0.8)",
|
|
3948
|
+
userSelect: "none"
|
|
3949
|
+
},
|
|
3950
|
+
children: text
|
|
3951
|
+
}
|
|
3952
|
+
)
|
|
3953
|
+
}
|
|
3954
|
+
);
|
|
3955
|
+
};
|
|
3956
|
+
Avl3DLabel.displayName = "Avl3DLabel";
|
|
3957
|
+
var Avl3DTooltip = ({
|
|
3958
|
+
position,
|
|
3959
|
+
title,
|
|
3960
|
+
rows,
|
|
3961
|
+
accentColor = "#5b9bd5"
|
|
3962
|
+
}) => {
|
|
3963
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3964
|
+
drei.Html,
|
|
3965
|
+
{
|
|
3966
|
+
position,
|
|
3967
|
+
center: true,
|
|
3968
|
+
distanceFactor: 8,
|
|
3969
|
+
style: { pointerEvents: "none" },
|
|
3970
|
+
zIndexRange: [100, 0],
|
|
3971
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3972
|
+
Box,
|
|
3973
|
+
{
|
|
3974
|
+
style: {
|
|
3975
|
+
background: "rgba(12, 18, 34, 0.92)",
|
|
3976
|
+
backdropFilter: "blur(8px)",
|
|
3977
|
+
borderLeft: `3px solid ${accentColor}`,
|
|
3978
|
+
borderRadius: "6px",
|
|
3979
|
+
padding: "8px 12px",
|
|
3980
|
+
minWidth: "140px",
|
|
3981
|
+
maxWidth: "220px",
|
|
3982
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.4)"
|
|
3983
|
+
},
|
|
3984
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
3985
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3986
|
+
Typography,
|
|
3987
|
+
{
|
|
3988
|
+
variant: "small",
|
|
3989
|
+
style: {
|
|
3990
|
+
color: "#ffffff",
|
|
3991
|
+
fontWeight: 600,
|
|
3992
|
+
fontSize: "12px",
|
|
3993
|
+
lineHeight: 1.3
|
|
3994
|
+
},
|
|
3995
|
+
children: title
|
|
3996
|
+
}
|
|
3997
|
+
),
|
|
3998
|
+
rows.map((row) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3999
|
+
Box,
|
|
4000
|
+
{
|
|
4001
|
+
style: {
|
|
4002
|
+
display: "flex",
|
|
4003
|
+
justifyContent: "space-between",
|
|
4004
|
+
gap: "12px"
|
|
4005
|
+
},
|
|
4006
|
+
children: [
|
|
4007
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4008
|
+
Typography,
|
|
4009
|
+
{
|
|
4010
|
+
variant: "small",
|
|
4011
|
+
style: {
|
|
4012
|
+
color: "#8899bb",
|
|
4013
|
+
fontSize: "10px",
|
|
4014
|
+
whiteSpace: "nowrap"
|
|
4015
|
+
},
|
|
4016
|
+
children: row.label
|
|
4017
|
+
}
|
|
4018
|
+
),
|
|
4019
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4020
|
+
Typography,
|
|
4021
|
+
{
|
|
4022
|
+
variant: "small",
|
|
4023
|
+
style: {
|
|
4024
|
+
color: "#ccddf0",
|
|
4025
|
+
fontSize: "10px",
|
|
4026
|
+
fontWeight: 500,
|
|
4027
|
+
textAlign: "right"
|
|
4028
|
+
},
|
|
4029
|
+
children: row.value
|
|
4030
|
+
}
|
|
4031
|
+
)
|
|
4032
|
+
]
|
|
4033
|
+
},
|
|
4034
|
+
row.label
|
|
4035
|
+
))
|
|
4036
|
+
] })
|
|
4037
|
+
}
|
|
4038
|
+
)
|
|
4039
|
+
}
|
|
4040
|
+
);
|
|
4041
|
+
};
|
|
4042
|
+
Avl3DTooltip.displayName = "Avl3DTooltip";
|
|
4043
|
+
var Avl3DOrbitalNode = ({
|
|
4044
|
+
name,
|
|
4045
|
+
entityName,
|
|
4046
|
+
traitCount,
|
|
4047
|
+
pageCount = 0,
|
|
4048
|
+
persistence = "persistent",
|
|
4049
|
+
position,
|
|
4050
|
+
onClick
|
|
4051
|
+
}) => {
|
|
4052
|
+
const groupRef = React21.useRef(null);
|
|
4053
|
+
const [hovered, setHovered] = React21.useState(false);
|
|
4054
|
+
const scale = React21.useMemo(() => 0.6 + Math.min(traitCount, 8) * 0.3, [traitCount]);
|
|
4055
|
+
const currentScale = React21.useRef(scale);
|
|
4056
|
+
const targetScale = hovered ? scale * 1.06 : scale;
|
|
4057
|
+
fiber.useFrame((_, delta) => {
|
|
4058
|
+
if (!groupRef.current) return;
|
|
4059
|
+
groupRef.current.rotation.y += delta * (hovered ? 0.4 : 0.2);
|
|
4060
|
+
groupRef.current.rotation.x += delta * 0.05;
|
|
4061
|
+
currentScale.current = THREE6.MathUtils.damp(currentScale.current, targetScale, 6, delta);
|
|
4062
|
+
});
|
|
4063
|
+
const baseBrightness = 0.3 + Math.min(pageCount, 5) * 0.05;
|
|
4064
|
+
const emissiveIntensity = hovered ? 0.8 : baseBrightness;
|
|
4065
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position, children: [
|
|
4066
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: scale * 1.3, children: [
|
|
4067
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 16, 16] }),
|
|
4068
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4069
|
+
"meshStandardMaterial",
|
|
4070
|
+
{
|
|
4071
|
+
color: AVL_3D_COLORS.orbitalRim,
|
|
4072
|
+
emissive: AVL_3D_COLORS.orbitalRim,
|
|
4073
|
+
emissiveIntensity: hovered ? 0.2 : 0.06,
|
|
4074
|
+
transparent: true,
|
|
4075
|
+
opacity: hovered ? 0.08 : 0.03,
|
|
4076
|
+
depthWrite: false
|
|
4077
|
+
}
|
|
4078
|
+
)
|
|
4079
|
+
] }),
|
|
4080
|
+
/* @__PURE__ */ jsxRuntime.jsxs("group", { ref: groupRef, children: [
|
|
4081
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4082
|
+
"mesh",
|
|
4083
|
+
{
|
|
4084
|
+
onClick: (e) => {
|
|
4085
|
+
e.stopPropagation();
|
|
4086
|
+
onClick?.();
|
|
4087
|
+
},
|
|
4088
|
+
onPointerOver: (e) => {
|
|
4089
|
+
e.stopPropagation();
|
|
4090
|
+
setHovered(true);
|
|
4091
|
+
document.body.style.cursor = "pointer";
|
|
4092
|
+
},
|
|
4093
|
+
onPointerOut: () => {
|
|
4094
|
+
setHovered(false);
|
|
4095
|
+
document.body.style.cursor = "auto";
|
|
4096
|
+
},
|
|
4097
|
+
scale: currentScale.current,
|
|
4098
|
+
rotation: [Math.PI / 4, 0, 0],
|
|
4099
|
+
children: [
|
|
4100
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [1, 0.18, 24, 64] }),
|
|
4101
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4102
|
+
"meshStandardMaterial",
|
|
4103
|
+
{
|
|
4104
|
+
color: AVL_3D_COLORS.orbitalSphere,
|
|
4105
|
+
emissive: AVL_3D_COLORS.orbitalRim,
|
|
4106
|
+
emissiveIntensity,
|
|
4107
|
+
roughness: 0.2,
|
|
4108
|
+
metalness: 0.7
|
|
4109
|
+
}
|
|
4110
|
+
)
|
|
4111
|
+
]
|
|
4112
|
+
}
|
|
4113
|
+
),
|
|
4114
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4115
|
+
"mesh",
|
|
4116
|
+
{
|
|
4117
|
+
scale: scale * 0.9,
|
|
4118
|
+
rotation: [Math.PI / 2 + 0.3, Math.PI / 5, 0],
|
|
4119
|
+
children: [
|
|
4120
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [1, 0.06, 12, 64] }),
|
|
4121
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4122
|
+
"meshStandardMaterial",
|
|
4123
|
+
{
|
|
4124
|
+
color: AVL_3D_COLORS.traitOrbit,
|
|
4125
|
+
emissive: AVL_3D_COLORS.traitOrbit,
|
|
4126
|
+
emissiveIntensity: 0.25,
|
|
4127
|
+
transparent: true,
|
|
4128
|
+
opacity: 0.4
|
|
4129
|
+
}
|
|
4130
|
+
)
|
|
4131
|
+
]
|
|
4132
|
+
}
|
|
4133
|
+
)
|
|
4134
|
+
] }),
|
|
4135
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: scale * 0.25, children: [
|
|
4136
|
+
/* @__PURE__ */ jsxRuntime.jsx("icosahedronGeometry", { args: [1, 1] }),
|
|
4137
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4138
|
+
"meshStandardMaterial",
|
|
4139
|
+
{
|
|
4140
|
+
color: AVL_3D_COLORS.entityCore,
|
|
4141
|
+
emissive: AVL_3D_COLORS.entityCoreGlow,
|
|
4142
|
+
emissiveIntensity: 2,
|
|
4143
|
+
roughness: 0.1
|
|
4144
|
+
}
|
|
4145
|
+
)
|
|
4146
|
+
] }),
|
|
4147
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4148
|
+
"pointLight",
|
|
4149
|
+
{
|
|
4150
|
+
color: AVL_3D_COLORS.entityCoreGlow,
|
|
4151
|
+
intensity: 0.5,
|
|
4152
|
+
distance: 3,
|
|
4153
|
+
decay: 2
|
|
4154
|
+
}
|
|
4155
|
+
),
|
|
4156
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4157
|
+
Avl3DLabel,
|
|
4158
|
+
{
|
|
4159
|
+
position: [0, scale + 0.6, 0],
|
|
4160
|
+
text: name,
|
|
4161
|
+
color: "#ffffff",
|
|
4162
|
+
fontSize: hovered ? 14 : 12
|
|
4163
|
+
}
|
|
4164
|
+
),
|
|
4165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4166
|
+
Avl3DLabel,
|
|
4167
|
+
{
|
|
4168
|
+
position: [0, -(scale + 0.4), 0],
|
|
4169
|
+
text: entityName,
|
|
4170
|
+
color: "#999999",
|
|
4171
|
+
fontSize: 10
|
|
4172
|
+
}
|
|
4173
|
+
),
|
|
4174
|
+
hovered && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4175
|
+
Avl3DTooltip,
|
|
4176
|
+
{
|
|
4177
|
+
position: [scale + 1.2, 0.3, 0],
|
|
4178
|
+
title: name,
|
|
4179
|
+
accentColor: AVL_3D_COLORS.orbitalRim,
|
|
4180
|
+
rows: [
|
|
4181
|
+
{ label: "Entity", value: entityName },
|
|
4182
|
+
{ label: "Persistence", value: persistence },
|
|
4183
|
+
{ label: "Traits", value: String(traitCount) },
|
|
4184
|
+
{ label: "Pages", value: String(pageCount) }
|
|
4185
|
+
]
|
|
4186
|
+
}
|
|
4187
|
+
)
|
|
4188
|
+
] });
|
|
4189
|
+
};
|
|
4190
|
+
Avl3DOrbitalNode.displayName = "Avl3DOrbitalNode";
|
|
4191
|
+
var Avl3DCrossWire = ({
|
|
4192
|
+
from,
|
|
4193
|
+
to,
|
|
4194
|
+
eventName,
|
|
4195
|
+
color = AVL_3D_COLORS.crossWire
|
|
4196
|
+
}) => {
|
|
4197
|
+
const { tubeArgs, midpoint } = React21.useMemo(() => {
|
|
4198
|
+
const curve = arcCurve3D(from, to, 2);
|
|
4199
|
+
const mid = curve.getPoint(0.5);
|
|
4200
|
+
return {
|
|
4201
|
+
tubeArgs: [curve, 32, 0.03, 8, false],
|
|
4202
|
+
midpoint: [mid.x, mid.y, mid.z]
|
|
4203
|
+
};
|
|
4204
|
+
}, [from, to]);
|
|
4205
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
4206
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { children: [
|
|
4207
|
+
/* @__PURE__ */ jsxRuntime.jsx("tubeGeometry", { args: [...tubeArgs] }),
|
|
4208
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4209
|
+
"meshStandardMaterial",
|
|
4210
|
+
{
|
|
4211
|
+
color,
|
|
4212
|
+
emissive: color,
|
|
4213
|
+
emissiveIntensity: 0.4,
|
|
4214
|
+
transparent: true,
|
|
4215
|
+
opacity: 0.6,
|
|
4216
|
+
roughness: 0.5
|
|
4217
|
+
}
|
|
4218
|
+
)
|
|
4219
|
+
] }),
|
|
4220
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4221
|
+
Avl3DLabel,
|
|
4222
|
+
{
|
|
4223
|
+
position: midpoint,
|
|
4224
|
+
text: eventName,
|
|
4225
|
+
color,
|
|
4226
|
+
fontSize: 9
|
|
4227
|
+
}
|
|
4228
|
+
)
|
|
4229
|
+
] });
|
|
4230
|
+
};
|
|
4231
|
+
Avl3DCrossWire.displayName = "Avl3DCrossWire";
|
|
4232
|
+
var Avl3DApplicationScene = ({
|
|
4233
|
+
data,
|
|
4234
|
+
onOrbitalClick
|
|
4235
|
+
}) => {
|
|
4236
|
+
const groupRef = React21.useRef(null);
|
|
4237
|
+
const [, setHoverTrigger] = React21.useState(0);
|
|
4238
|
+
const orbitalPositions = React21.useMemo(() => {
|
|
4239
|
+
const baseRadius = Math.max(4, data.orbitals.length * 1.5);
|
|
4240
|
+
if (data.crossLinks.length === 0) {
|
|
4241
|
+
return goldenSpiralPositions(data.orbitals.length, baseRadius);
|
|
4242
|
+
}
|
|
4243
|
+
const nameToIdx = /* @__PURE__ */ new Map();
|
|
4244
|
+
data.orbitals.forEach((o, i) => nameToIdx.set(o.name, i));
|
|
4245
|
+
const edges = data.crossLinks.map((link) => ({
|
|
4246
|
+
from: nameToIdx.get(link.emitterOrbital) ?? -1,
|
|
4247
|
+
to: nameToIdx.get(link.listenerOrbital) ?? -1
|
|
4248
|
+
})).filter((e) => e.from >= 0 && e.to >= 0);
|
|
4249
|
+
return forceDirectedPositions(data.orbitals.length, edges, baseRadius);
|
|
4250
|
+
}, [data.orbitals, data.crossLinks]);
|
|
4251
|
+
const positionByName = React21.useMemo(() => {
|
|
4252
|
+
const map = /* @__PURE__ */ new Map();
|
|
4253
|
+
data.orbitals.forEach((orb, i) => {
|
|
4254
|
+
const pos = orbitalPositions[i];
|
|
4255
|
+
map.set(orb.name, [pos.x, pos.y, pos.z]);
|
|
4256
|
+
});
|
|
4257
|
+
return map;
|
|
4258
|
+
}, [data.orbitals, orbitalPositions]);
|
|
4259
|
+
fiber.useFrame((_, delta) => {
|
|
4260
|
+
if (!groupRef.current) return;
|
|
4261
|
+
groupRef.current.rotation.y += delta * 0.03;
|
|
4262
|
+
});
|
|
4263
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { ref: groupRef, children: [
|
|
4264
|
+
data.orbitals.map((orbital, i) => {
|
|
4265
|
+
const pos = orbitalPositions[i];
|
|
4266
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4267
|
+
Avl3DOrbitalNode,
|
|
4268
|
+
{
|
|
4269
|
+
name: orbital.name,
|
|
4270
|
+
entityName: orbital.entityName,
|
|
4271
|
+
traitCount: orbital.traitNames.length,
|
|
4272
|
+
pageCount: orbital.pageNames.length,
|
|
4273
|
+
persistence: orbital.persistence,
|
|
4274
|
+
position: [pos.x, pos.y, pos.z],
|
|
4275
|
+
onClick: () => {
|
|
4276
|
+
onOrbitalClick?.(orbital.name);
|
|
4277
|
+
setHoverTrigger((v) => v + 1);
|
|
4278
|
+
}
|
|
4279
|
+
},
|
|
4280
|
+
orbital.name
|
|
4281
|
+
);
|
|
4282
|
+
}),
|
|
4283
|
+
data.crossLinks.map((link, i) => {
|
|
4284
|
+
const fromPos = positionByName.get(link.emitterOrbital);
|
|
4285
|
+
const toPos = positionByName.get(link.listenerOrbital);
|
|
4286
|
+
if (!fromPos || !toPos) return null;
|
|
4287
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4288
|
+
Avl3DCrossWire,
|
|
4289
|
+
{
|
|
4290
|
+
from: fromPos,
|
|
4291
|
+
to: toPos,
|
|
4292
|
+
eventName: link.eventName
|
|
4293
|
+
},
|
|
4294
|
+
`${link.emitterOrbital}-${link.eventName}-${link.listenerOrbital}-${i}`
|
|
4295
|
+
);
|
|
4296
|
+
})
|
|
4297
|
+
] });
|
|
4298
|
+
};
|
|
4299
|
+
Avl3DApplicationScene.displayName = "Avl3DApplicationScene";
|
|
4300
|
+
function fieldPositions(count, radius) {
|
|
4301
|
+
const positions = [];
|
|
4302
|
+
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
4303
|
+
for (let i = 0; i < Math.min(count, 12); i++) {
|
|
4304
|
+
const y = 1 - 2 * i / Math.max(count - 1, 1);
|
|
4305
|
+
const r = Math.sqrt(1 - y * y);
|
|
4306
|
+
const theta = goldenAngle * i;
|
|
4307
|
+
positions.push([
|
|
4308
|
+
radius * r * Math.cos(theta),
|
|
4309
|
+
radius * y,
|
|
4310
|
+
radius * r * Math.sin(theta)
|
|
4311
|
+
]);
|
|
4312
|
+
}
|
|
4313
|
+
return positions;
|
|
4314
|
+
}
|
|
4315
|
+
function persistenceColor(persistence) {
|
|
4316
|
+
switch (persistence) {
|
|
4317
|
+
case "persistent":
|
|
4318
|
+
return "#4A90D9";
|
|
4319
|
+
case "runtime":
|
|
4320
|
+
return "#27AE60";
|
|
4321
|
+
case "singleton":
|
|
4322
|
+
return "#E8913A";
|
|
4323
|
+
default:
|
|
4324
|
+
return "#999999";
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4327
|
+
var Avl3DEntityCore = ({
|
|
4328
|
+
name,
|
|
4329
|
+
fieldCount,
|
|
4330
|
+
persistence,
|
|
4331
|
+
position,
|
|
4332
|
+
fields
|
|
4333
|
+
}) => {
|
|
4334
|
+
const coreRef = React21.useRef(null);
|
|
4335
|
+
fiber.useFrame((_, delta) => {
|
|
4336
|
+
if (!coreRef.current) return;
|
|
4337
|
+
coreRef.current.rotation.y += delta * 0.3;
|
|
4338
|
+
coreRef.current.rotation.x += delta * 0.1;
|
|
4339
|
+
});
|
|
4340
|
+
const fieldPos = fieldPositions(fieldCount, 1.4);
|
|
4341
|
+
const pColor = persistenceColor(persistence);
|
|
4342
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position, children: [
|
|
4343
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { ref: coreRef, children: [
|
|
4344
|
+
/* @__PURE__ */ jsxRuntime.jsx("icosahedronGeometry", { args: [1, 2] }),
|
|
4345
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4346
|
+
"meshStandardMaterial",
|
|
4347
|
+
{
|
|
4348
|
+
color: AVL_3D_COLORS.entityCore,
|
|
4349
|
+
emissive: AVL_3D_COLORS.entityCoreGlow,
|
|
4350
|
+
emissiveIntensity: 2,
|
|
4351
|
+
roughness: 0.15,
|
|
4352
|
+
metalness: 0.85
|
|
4353
|
+
}
|
|
4354
|
+
)
|
|
4355
|
+
] }),
|
|
4356
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: 1.2, children: [
|
|
4357
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 24, 24] }),
|
|
4358
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4359
|
+
"meshStandardMaterial",
|
|
4360
|
+
{
|
|
4361
|
+
color: AVL_3D_COLORS.entityCoreGlow,
|
|
4362
|
+
emissive: AVL_3D_COLORS.entityCoreGlow,
|
|
4363
|
+
emissiveIntensity: 0.6,
|
|
4364
|
+
transparent: true,
|
|
4365
|
+
opacity: 0.1,
|
|
4366
|
+
depthWrite: false
|
|
4367
|
+
}
|
|
4368
|
+
)
|
|
4369
|
+
] }),
|
|
4370
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: 1.6, children: [
|
|
4371
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 16, 16] }),
|
|
4372
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4373
|
+
"meshStandardMaterial",
|
|
4374
|
+
{
|
|
4375
|
+
color: AVL_3D_COLORS.entityCore,
|
|
4376
|
+
emissive: AVL_3D_COLORS.entityCore,
|
|
4377
|
+
emissiveIntensity: 0.2,
|
|
4378
|
+
transparent: true,
|
|
4379
|
+
opacity: 0.04,
|
|
4380
|
+
depthWrite: false
|
|
4381
|
+
}
|
|
4382
|
+
)
|
|
4383
|
+
] }),
|
|
4384
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4385
|
+
"pointLight",
|
|
4386
|
+
{
|
|
4387
|
+
color: AVL_3D_COLORS.entityCoreGlow,
|
|
4388
|
+
intensity: 2.5,
|
|
4389
|
+
distance: 10,
|
|
4390
|
+
decay: 2
|
|
4391
|
+
}
|
|
4392
|
+
),
|
|
4393
|
+
fieldPos.map((pos, i) => {
|
|
4394
|
+
const fieldType = fields?.[i];
|
|
4395
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: pos, scale: 0.08, rotation: [Math.PI / 6, Math.PI / 4, 0], children: [
|
|
4396
|
+
fieldType === "number" ? /* @__PURE__ */ jsxRuntime.jsx("tetrahedronGeometry", { args: [1, 0] }) : fieldType === "boolean" ? /* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [1.2, 1.2, 1.2] }) : fieldType === "date" ? /* @__PURE__ */ jsxRuntime.jsx("octahedronGeometry", { args: [1, 0] }) : fieldType === "enum" ? /* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [0.8, 0.3, 6, 12] }) : fieldType === "object" ? /* @__PURE__ */ jsxRuntime.jsx("dodecahedronGeometry", { args: [1, 0] }) : fieldType === "array" ? /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.8, 0.8, 1.5, 6] }) : (
|
|
4397
|
+
// string (default): sphere
|
|
4398
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 8, 8] })
|
|
4399
|
+
),
|
|
4400
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4401
|
+
"meshStandardMaterial",
|
|
4402
|
+
{
|
|
4403
|
+
color: "#ffffff",
|
|
4404
|
+
emissive: "#ffffff",
|
|
4405
|
+
emissiveIntensity: 0.8,
|
|
4406
|
+
transparent: true,
|
|
4407
|
+
opacity: 0.7
|
|
4408
|
+
}
|
|
4409
|
+
)
|
|
4410
|
+
] }, i);
|
|
4411
|
+
}),
|
|
4412
|
+
persistence === "singleton" ? (
|
|
4413
|
+
// Singleton: double concentric rings (thick outer + thin inner)
|
|
4414
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4415
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4416
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [1.6, 0.04, 8, 64] }),
|
|
4417
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
|
|
4418
|
+
] }),
|
|
4419
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4420
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [1.4, 0.02, 8, 64] }),
|
|
4421
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.4, transparent: true, opacity: 0.4 })
|
|
4422
|
+
] })
|
|
4423
|
+
] })
|
|
4424
|
+
) : persistence === "runtime" ? (
|
|
4425
|
+
// Runtime: segmented ring (8 arc segments with gaps)
|
|
4426
|
+
/* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 8 }).map((_, i) => {
|
|
4427
|
+
const angle = i / 8 * Math.PI * 2;
|
|
4428
|
+
const x = 1.6 * Math.cos(angle);
|
|
4429
|
+
const z = 1.6 * Math.sin(angle);
|
|
4430
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [x, 0, z], rotation: [Math.PI / 2, 0, angle], children: [
|
|
4431
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [0.25, 0.025, 6, 12, Math.PI * 0.7] }),
|
|
4432
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
|
|
4433
|
+
] }, i);
|
|
4434
|
+
}) })
|
|
4435
|
+
) : persistence === "instance" ? (
|
|
4436
|
+
// Instance: dotted ring (small spheres in a circle)
|
|
4437
|
+
/* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 16 }).map((_, i) => {
|
|
4438
|
+
const angle = i / 16 * Math.PI * 2;
|
|
4439
|
+
const x = 1.6 * Math.cos(angle);
|
|
4440
|
+
const z = 1.6 * Math.sin(angle);
|
|
4441
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [x, 0, z], scale: 0.04, children: [
|
|
4442
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 6, 6] }),
|
|
4443
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.8 })
|
|
4444
|
+
] }, i);
|
|
4445
|
+
}) })
|
|
4446
|
+
) : (
|
|
4447
|
+
// Persistent (default): solid torus ring
|
|
4448
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4449
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [1.6, 0.03, 8, 64] }),
|
|
4450
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: pColor, emissive: pColor, emissiveIntensity: 0.6, transparent: true, opacity: 0.6 })
|
|
4451
|
+
] })
|
|
4452
|
+
),
|
|
4453
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4454
|
+
Avl3DLabel,
|
|
4455
|
+
{
|
|
4456
|
+
position: [0, -1.8, 0],
|
|
4457
|
+
text: name,
|
|
4458
|
+
color: AVL_3D_COLORS.entityCore,
|
|
4459
|
+
fontSize: 14
|
|
4460
|
+
}
|
|
4461
|
+
),
|
|
4462
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4463
|
+
Avl3DLabel,
|
|
4464
|
+
{
|
|
4465
|
+
position: [0, -2.3, 0],
|
|
4466
|
+
text: `${fieldCount} fields`,
|
|
4467
|
+
color: "#999999",
|
|
4468
|
+
fontSize: 10
|
|
4469
|
+
}
|
|
4470
|
+
)
|
|
4471
|
+
] });
|
|
4472
|
+
};
|
|
4473
|
+
Avl3DEntityCore.displayName = "Avl3DEntityCore";
|
|
4474
|
+
function TraitOrbit({
|
|
4475
|
+
name,
|
|
4476
|
+
radius,
|
|
4477
|
+
tilt,
|
|
4478
|
+
speed,
|
|
4479
|
+
highlighted,
|
|
4480
|
+
dimmed,
|
|
4481
|
+
stateCount = 0,
|
|
4482
|
+
eventCount = 0,
|
|
4483
|
+
transitionCount = 0,
|
|
4484
|
+
onClick,
|
|
4485
|
+
onHover
|
|
4486
|
+
}) {
|
|
4487
|
+
const groupRef = React21.useRef(null);
|
|
4488
|
+
const angleRef = React21.useRef(Math.random() * Math.PI * 2);
|
|
4489
|
+
fiber.useFrame((_, delta) => {
|
|
4490
|
+
angleRef.current += delta * speed;
|
|
4491
|
+
if (!groupRef.current) return;
|
|
4492
|
+
const x = radius * Math.cos(angleRef.current);
|
|
4493
|
+
const flatZ = radius * Math.sin(angleRef.current);
|
|
4494
|
+
const y = flatZ * Math.sin(tilt);
|
|
4495
|
+
const z = flatZ * Math.cos(tilt);
|
|
4496
|
+
groupRef.current.position.set(x, y, z);
|
|
4497
|
+
});
|
|
4498
|
+
const opacity = dimmed ? 0.2 : 0.5;
|
|
4499
|
+
const emissiveIntensity = highlighted ? 0.8 : 0.4;
|
|
4500
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
4501
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [tilt, 0, 0], children: [
|
|
4502
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [radius, 0.015, 8, 64] }),
|
|
4503
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4504
|
+
"meshStandardMaterial",
|
|
4505
|
+
{
|
|
4506
|
+
color: AVL_3D_COLORS.traitOrbit,
|
|
4507
|
+
emissive: AVL_3D_COLORS.traitOrbit,
|
|
4508
|
+
emissiveIntensity,
|
|
4509
|
+
transparent: true,
|
|
4510
|
+
opacity
|
|
4511
|
+
}
|
|
4512
|
+
)
|
|
4513
|
+
] }),
|
|
4514
|
+
/* @__PURE__ */ jsxRuntime.jsxs("group", { ref: groupRef, children: [
|
|
4515
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4516
|
+
"mesh",
|
|
4517
|
+
{
|
|
4518
|
+
onClick: (e) => {
|
|
4519
|
+
e.stopPropagation();
|
|
4520
|
+
onClick?.();
|
|
4521
|
+
},
|
|
4522
|
+
onPointerOver: (e) => {
|
|
4523
|
+
e.stopPropagation();
|
|
4524
|
+
onHover?.(true);
|
|
4525
|
+
document.body.style.cursor = "pointer";
|
|
4526
|
+
},
|
|
4527
|
+
onPointerOut: () => {
|
|
4528
|
+
onHover?.(false);
|
|
4529
|
+
document.body.style.cursor = "auto";
|
|
4530
|
+
},
|
|
4531
|
+
scale: highlighted ? 1.3 : 1,
|
|
4532
|
+
children: [
|
|
4533
|
+
/* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [0.25, 16, 16] }),
|
|
4534
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4535
|
+
"meshStandardMaterial",
|
|
4536
|
+
{
|
|
4537
|
+
color: AVL_3D_COLORS.traitOrbit,
|
|
4538
|
+
emissive: AVL_3D_COLORS.traitOrbit,
|
|
4539
|
+
emissiveIntensity: highlighted ? 1.2 : 0.6,
|
|
4540
|
+
transparent: true,
|
|
4541
|
+
opacity: dimmed ? 0.3 : 0.9
|
|
4542
|
+
}
|
|
4543
|
+
)
|
|
4544
|
+
]
|
|
4545
|
+
}
|
|
4546
|
+
),
|
|
4547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4548
|
+
Avl3DLabel,
|
|
4549
|
+
{
|
|
4550
|
+
position: [0, 0.5, 0],
|
|
4551
|
+
text: name,
|
|
4552
|
+
color: dimmed ? "#666666" : "#ffffff",
|
|
4553
|
+
fontSize: highlighted ? 13 : 11
|
|
4554
|
+
}
|
|
4555
|
+
),
|
|
4556
|
+
highlighted && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4557
|
+
Avl3DTooltip,
|
|
4558
|
+
{
|
|
4559
|
+
position: [0.8, 0.8, 0],
|
|
4560
|
+
title: name,
|
|
4561
|
+
accentColor: AVL_3D_COLORS.traitOrbitHighlight,
|
|
4562
|
+
rows: [
|
|
4563
|
+
{ label: "States", value: String(stateCount) },
|
|
4564
|
+
{ label: "Events", value: String(eventCount) },
|
|
4565
|
+
{ label: "Transitions", value: String(transitionCount) }
|
|
4566
|
+
]
|
|
4567
|
+
}
|
|
4568
|
+
)
|
|
4569
|
+
] })
|
|
4570
|
+
] });
|
|
4571
|
+
}
|
|
4572
|
+
function PagePortal({ name, position }) {
|
|
4573
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position, children: [
|
|
4574
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4575
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.35, 0.35, 0.12, 6] }),
|
|
4576
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4577
|
+
"meshStandardMaterial",
|
|
4578
|
+
{
|
|
4579
|
+
color: AVL_3D_COLORS.pagePortal,
|
|
4580
|
+
emissive: AVL_3D_COLORS.pagePortal,
|
|
4581
|
+
emissiveIntensity: 0.5,
|
|
4582
|
+
transparent: true,
|
|
4583
|
+
opacity: 0.7,
|
|
4584
|
+
roughness: 0.3
|
|
4585
|
+
}
|
|
4586
|
+
)
|
|
4587
|
+
] }),
|
|
4588
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4589
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.25, 0.25, 0.14, 6] }),
|
|
4590
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4591
|
+
"meshStandardMaterial",
|
|
4592
|
+
{
|
|
4593
|
+
color: AVL_3D_COLORS.pagePortal,
|
|
4594
|
+
emissive: AVL_3D_COLORS.pagePortal,
|
|
4595
|
+
emissiveIntensity: 0.8,
|
|
4596
|
+
transparent: true,
|
|
4597
|
+
opacity: 0.2,
|
|
4598
|
+
depthWrite: false
|
|
4599
|
+
}
|
|
4600
|
+
)
|
|
4601
|
+
] }),
|
|
4602
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4603
|
+
Avl3DLabel,
|
|
4604
|
+
{
|
|
4605
|
+
position: [0, -0.5, 0],
|
|
4606
|
+
text: name,
|
|
4607
|
+
color: AVL_3D_COLORS.pagePortal,
|
|
4608
|
+
fontSize: 9
|
|
4609
|
+
}
|
|
4610
|
+
)
|
|
4611
|
+
] });
|
|
4612
|
+
}
|
|
4613
|
+
var Avl3DOrbitalScene = ({
|
|
4614
|
+
data,
|
|
4615
|
+
onTraitClick,
|
|
4616
|
+
highlightedTrait,
|
|
4617
|
+
onTraitHighlight
|
|
4618
|
+
}) => {
|
|
4619
|
+
const [localHighlight, setLocalHighlight] = React21.useState(null);
|
|
4620
|
+
const activeHighlight = highlightedTrait ?? localHighlight;
|
|
4621
|
+
const traitOrbits = React21.useMemo(() => {
|
|
4622
|
+
return data.traits.map((trait, i) => ({
|
|
4623
|
+
name: trait.name,
|
|
4624
|
+
radius: 3 + i * 1.2,
|
|
4625
|
+
tilt: i * Math.PI / (data.traits.length + 1) - Math.PI / 4,
|
|
4626
|
+
speed: 0.3 - i * 0.04,
|
|
4627
|
+
stateCount: trait.stateCount,
|
|
4628
|
+
eventCount: trait.eventCount,
|
|
4629
|
+
transitionCount: trait.transitionCount
|
|
4630
|
+
}));
|
|
4631
|
+
}, [data.traits]);
|
|
4632
|
+
const pagePositions = React21.useMemo(() => {
|
|
4633
|
+
const outerRadius = 3 + data.traits.length * 1.2 + 1.5;
|
|
4634
|
+
return data.pages.map((_, i) => {
|
|
4635
|
+
const angle = 2 * Math.PI * i / data.pages.length - Math.PI / 2;
|
|
4636
|
+
return [
|
|
4637
|
+
outerRadius * Math.cos(angle),
|
|
4638
|
+
0,
|
|
4639
|
+
outerRadius * Math.sin(angle)
|
|
4640
|
+
];
|
|
4641
|
+
});
|
|
4642
|
+
}, [data.pages, data.traits.length]);
|
|
4643
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
4644
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4645
|
+
Avl3DEntityCore,
|
|
4646
|
+
{
|
|
4647
|
+
name: data.entity.name,
|
|
4648
|
+
fieldCount: data.entity.fields.length,
|
|
4649
|
+
persistence: data.entity.persistence,
|
|
4650
|
+
position: [0, 0, 0],
|
|
4651
|
+
fields: data.entity.fields.map((f) => f.type)
|
|
4652
|
+
}
|
|
4653
|
+
),
|
|
4654
|
+
traitOrbits.map((orbit) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4655
|
+
TraitOrbit,
|
|
4656
|
+
{
|
|
4657
|
+
name: orbit.name,
|
|
4658
|
+
radius: orbit.radius,
|
|
4659
|
+
tilt: orbit.tilt,
|
|
4660
|
+
speed: orbit.speed,
|
|
4661
|
+
highlighted: activeHighlight === orbit.name,
|
|
4662
|
+
dimmed: activeHighlight !== null && activeHighlight !== orbit.name,
|
|
4663
|
+
stateCount: orbit.stateCount,
|
|
4664
|
+
eventCount: orbit.eventCount,
|
|
4665
|
+
transitionCount: orbit.transitionCount,
|
|
4666
|
+
onClick: () => onTraitClick?.(orbit.name),
|
|
4667
|
+
onHover: (h) => {
|
|
4668
|
+
const value = h ? orbit.name : null;
|
|
4669
|
+
onTraitHighlight?.(value);
|
|
4670
|
+
setLocalHighlight(value);
|
|
4671
|
+
}
|
|
4672
|
+
},
|
|
4673
|
+
orbit.name
|
|
4674
|
+
)),
|
|
4675
|
+
data.pages.map((page, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4676
|
+
PagePortal,
|
|
4677
|
+
{
|
|
4678
|
+
name: page.name,
|
|
4679
|
+
position: pagePositions[i]
|
|
4680
|
+
},
|
|
4681
|
+
page.name
|
|
4682
|
+
))
|
|
4683
|
+
] });
|
|
4684
|
+
};
|
|
4685
|
+
Avl3DOrbitalScene.displayName = "Avl3DOrbitalScene";
|
|
4686
|
+
var Avl3DStateNode = ({
|
|
4687
|
+
name,
|
|
4688
|
+
isInitial = false,
|
|
4689
|
+
isTerminal = false,
|
|
4690
|
+
position,
|
|
4691
|
+
active = false,
|
|
4692
|
+
incomingCount = 0,
|
|
4693
|
+
outgoingCount = 0,
|
|
4694
|
+
onClick
|
|
4695
|
+
}) => {
|
|
4696
|
+
const [hovered, setHovered] = React21.useState(false);
|
|
4697
|
+
const baseColor = active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateIdle;
|
|
4698
|
+
const emissiveColor = active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateEdge;
|
|
4699
|
+
const emissiveIntensity = active ? 2 : hovered ? 0.8 : 0.3;
|
|
4700
|
+
const targetScale = hovered ? 1.08 : 1;
|
|
4701
|
+
const currentScale = React21.useRef(1);
|
|
4702
|
+
fiber.useFrame((_, delta) => {
|
|
4703
|
+
currentScale.current = THREE6.MathUtils.damp(currentScale.current, targetScale, 6, delta);
|
|
4704
|
+
});
|
|
4705
|
+
const scale = currentScale.current;
|
|
4706
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position, children: [
|
|
4707
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: scale * 1.4, children: [
|
|
4708
|
+
/* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [1.2, 0.7, 0.5] }),
|
|
4709
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4710
|
+
"meshStandardMaterial",
|
|
4711
|
+
{
|
|
4712
|
+
color: emissiveColor,
|
|
4713
|
+
emissive: emissiveColor,
|
|
4714
|
+
emissiveIntensity: active ? 0.3 : hovered ? 0.1 : 0.03,
|
|
4715
|
+
transparent: true,
|
|
4716
|
+
opacity: active ? 0.08 : 0.03,
|
|
4717
|
+
depthWrite: false
|
|
4718
|
+
}
|
|
4719
|
+
)
|
|
4720
|
+
] }),
|
|
4721
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4722
|
+
drei.RoundedBox,
|
|
4723
|
+
{
|
|
4724
|
+
args: [1, 0.55, 0.35],
|
|
4725
|
+
radius: 0.12,
|
|
4726
|
+
smoothness: 4,
|
|
4727
|
+
scale,
|
|
4728
|
+
onClick: (e) => {
|
|
4729
|
+
e.stopPropagation();
|
|
4730
|
+
onClick?.();
|
|
4731
|
+
},
|
|
4732
|
+
onPointerOver: (e) => {
|
|
4733
|
+
e.stopPropagation();
|
|
4734
|
+
setHovered(true);
|
|
4735
|
+
document.body.style.cursor = "pointer";
|
|
4736
|
+
},
|
|
4737
|
+
onPointerOut: () => {
|
|
4738
|
+
setHovered(false);
|
|
4739
|
+
document.body.style.cursor = "auto";
|
|
4740
|
+
},
|
|
4741
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4742
|
+
"meshStandardMaterial",
|
|
4743
|
+
{
|
|
4744
|
+
color: baseColor,
|
|
4745
|
+
emissive: emissiveColor,
|
|
4746
|
+
emissiveIntensity,
|
|
4747
|
+
roughness: 0.35,
|
|
4748
|
+
metalness: 0.5
|
|
4749
|
+
}
|
|
4750
|
+
)
|
|
4751
|
+
}
|
|
4752
|
+
),
|
|
4753
|
+
isInitial && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [-0.75, 0, 0], children: [
|
|
4754
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [0, 0, -Math.PI / 2], children: [
|
|
4755
|
+
/* @__PURE__ */ jsxRuntime.jsx("coneGeometry", { args: [0.12, 0.25, 8] }),
|
|
4756
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4757
|
+
"meshStandardMaterial",
|
|
4758
|
+
{
|
|
4759
|
+
color: AVL_3D_COLORS.stateActive,
|
|
4760
|
+
emissive: AVL_3D_COLORS.stateActive,
|
|
4761
|
+
emissiveIntensity: 1
|
|
4762
|
+
}
|
|
4763
|
+
)
|
|
4764
|
+
] }),
|
|
4765
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [-0.2, 0, 0], rotation: [0, 0, Math.PI / 2], children: [
|
|
4766
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.02, 0.02, 0.25, 6] }),
|
|
4767
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4768
|
+
"meshStandardMaterial",
|
|
4769
|
+
{
|
|
4770
|
+
color: AVL_3D_COLORS.stateActive,
|
|
4771
|
+
emissive: AVL_3D_COLORS.stateActive,
|
|
4772
|
+
emissiveIntensity: 0.6
|
|
4773
|
+
}
|
|
4774
|
+
)
|
|
4775
|
+
] })
|
|
4776
|
+
] }),
|
|
4777
|
+
isTerminal && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0.75, 0, 0], children: [
|
|
4778
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: 0.15, children: [
|
|
4779
|
+
/* @__PURE__ */ jsxRuntime.jsx("octahedronGeometry", { args: [1, 0] }),
|
|
4780
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4781
|
+
"meshStandardMaterial",
|
|
4782
|
+
{
|
|
4783
|
+
color: AVL_3D_COLORS.guardFail,
|
|
4784
|
+
emissive: AVL_3D_COLORS.guardFail,
|
|
4785
|
+
emissiveIntensity: 1
|
|
4786
|
+
}
|
|
4787
|
+
)
|
|
4788
|
+
] }),
|
|
4789
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
4790
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [0.2, 0.015, 8, 24] }),
|
|
4791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4792
|
+
"meshStandardMaterial",
|
|
4793
|
+
{
|
|
4794
|
+
color: AVL_3D_COLORS.guardFail,
|
|
4795
|
+
emissive: AVL_3D_COLORS.guardFail,
|
|
4796
|
+
emissiveIntensity: 0.5
|
|
4797
|
+
}
|
|
4798
|
+
)
|
|
4799
|
+
] })
|
|
4800
|
+
] }),
|
|
4801
|
+
active && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4802
|
+
"pointLight",
|
|
4803
|
+
{
|
|
4804
|
+
color: AVL_3D_COLORS.stateActive,
|
|
4805
|
+
intensity: 1.5,
|
|
4806
|
+
distance: 4,
|
|
4807
|
+
decay: 2
|
|
4808
|
+
}
|
|
4809
|
+
),
|
|
4810
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4811
|
+
Avl3DLabel,
|
|
4812
|
+
{
|
|
4813
|
+
position: [0, -0.55, 0],
|
|
4814
|
+
text: name,
|
|
4815
|
+
color: active ? AVL_3D_COLORS.stateActive : "#ffffff",
|
|
4816
|
+
fontSize: 11
|
|
4817
|
+
}
|
|
4818
|
+
),
|
|
4819
|
+
hovered && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4820
|
+
Avl3DTooltip,
|
|
4821
|
+
{
|
|
4822
|
+
position: [0.9, 0.3, 0],
|
|
4823
|
+
title: name,
|
|
4824
|
+
accentColor: active ? AVL_3D_COLORS.stateActive : AVL_3D_COLORS.stateEdge,
|
|
4825
|
+
rows: [
|
|
4826
|
+
{ label: "Type", value: isInitial ? "Initial" : isTerminal ? "Terminal" : "Standard" },
|
|
4827
|
+
{ label: "Incoming", value: String(incomingCount) },
|
|
4828
|
+
{ label: "Outgoing", value: String(outgoingCount) },
|
|
4829
|
+
...active ? [{ label: "Status", value: "Active" }] : []
|
|
4830
|
+
]
|
|
4831
|
+
}
|
|
4832
|
+
)
|
|
4833
|
+
] });
|
|
4834
|
+
};
|
|
4835
|
+
Avl3DStateNode.displayName = "Avl3DStateNode";
|
|
4836
|
+
function effectTypeColor(type) {
|
|
4837
|
+
switch (type) {
|
|
4838
|
+
case "render-ui":
|
|
4839
|
+
return "#5b9bd5";
|
|
4840
|
+
case "set":
|
|
4841
|
+
return "#e0944a";
|
|
4842
|
+
case "persist":
|
|
4843
|
+
return "#4ecb71";
|
|
4844
|
+
case "fetch":
|
|
4845
|
+
return "#5b9bd5";
|
|
4846
|
+
case "emit":
|
|
4847
|
+
return "#a78bda";
|
|
4848
|
+
case "navigate":
|
|
4849
|
+
return "#40c8aa";
|
|
4850
|
+
case "notify":
|
|
4851
|
+
return "#f0c040";
|
|
4852
|
+
case "call-service":
|
|
4853
|
+
return "#a78bda";
|
|
4854
|
+
case "spawn":
|
|
4855
|
+
return "#4ecb71";
|
|
4856
|
+
case "despawn":
|
|
4857
|
+
return "#f06060";
|
|
4858
|
+
default:
|
|
4859
|
+
return "#888888";
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
var Avl3DTransitionArc = ({
|
|
4863
|
+
from,
|
|
4864
|
+
to,
|
|
4865
|
+
event,
|
|
4866
|
+
hasGuard = false,
|
|
4867
|
+
effectTypes,
|
|
4868
|
+
index,
|
|
4869
|
+
isSelf = false,
|
|
4870
|
+
fromState,
|
|
4871
|
+
toState,
|
|
4872
|
+
onClick,
|
|
4873
|
+
color = AVL_3D_COLORS.transitionArc
|
|
4874
|
+
}) => {
|
|
4875
|
+
const [hovered, setHovered] = React21.useState(false);
|
|
4876
|
+
const { tubeArgs, labelPos, guardPos, arrowPos, arrowQuat, effectPositions } = React21.useMemo(() => {
|
|
4877
|
+
const offset = 1.5 + index * 0.8;
|
|
4878
|
+
const curve = isSelf ? selfLoopCurve3D(from, 1.2) : arcCurve3D(from, to, offset);
|
|
4879
|
+
const mid = curve.getPoint(0.5);
|
|
4880
|
+
const guardPt = curve.getPoint(0.3);
|
|
4881
|
+
const arrowPt = curve.getPoint(0.9);
|
|
4882
|
+
const arrowTangent = curve.getTangent(0.9);
|
|
4883
|
+
const upVec = new THREE6.Vector3(0, 1, 0);
|
|
4884
|
+
const tangentVec = new THREE6.Vector3(arrowTangent.x, arrowTangent.y, arrowTangent.z).normalize();
|
|
4885
|
+
const quat = new THREE6.Quaternion().setFromUnitVectors(upVec, tangentVec);
|
|
4886
|
+
const effectPositions2 = [];
|
|
4887
|
+
for (let ei = 0; ei < 4; ei++) {
|
|
4888
|
+
const t = 0.7 + ei * 0.05;
|
|
4889
|
+
const ep = curve.getPoint(t);
|
|
4890
|
+
effectPositions2.push([ep.x, ep.y + 0.2, ep.z]);
|
|
4891
|
+
}
|
|
4892
|
+
return {
|
|
4893
|
+
tubeArgs: [curve, 48, 0.02, 8, false],
|
|
4894
|
+
labelPos: [mid.x, mid.y + 0.3, mid.z],
|
|
4895
|
+
guardPos: [guardPt.x, guardPt.y, guardPt.z],
|
|
4896
|
+
arrowPos: [arrowPt.x, arrowPt.y, arrowPt.z],
|
|
4897
|
+
arrowQuat: [quat.x, quat.y, quat.z, quat.w],
|
|
4898
|
+
effectPositions: effectPositions2
|
|
4899
|
+
};
|
|
4900
|
+
}, [from, to, index, isSelf]);
|
|
4901
|
+
const emissiveIntensity = hovered ? 0.8 : 0.4;
|
|
4902
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
4903
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4904
|
+
"mesh",
|
|
4905
|
+
{
|
|
4906
|
+
onClick: (e) => {
|
|
4907
|
+
e.stopPropagation();
|
|
4908
|
+
onClick?.();
|
|
4909
|
+
},
|
|
4910
|
+
onPointerOver: (e) => {
|
|
4911
|
+
e.stopPropagation();
|
|
4912
|
+
setHovered(true);
|
|
4913
|
+
document.body.style.cursor = "pointer";
|
|
4914
|
+
},
|
|
4915
|
+
onPointerOut: () => {
|
|
4916
|
+
setHovered(false);
|
|
4917
|
+
document.body.style.cursor = "auto";
|
|
4918
|
+
},
|
|
4919
|
+
children: [
|
|
4920
|
+
/* @__PURE__ */ jsxRuntime.jsx("tubeGeometry", { args: [...tubeArgs] }),
|
|
4921
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4922
|
+
"meshStandardMaterial",
|
|
4923
|
+
{
|
|
4924
|
+
color,
|
|
4925
|
+
emissive: color,
|
|
4926
|
+
emissiveIntensity,
|
|
4927
|
+
transparent: true,
|
|
4928
|
+
opacity: hovered ? 0.9 : 0.7
|
|
4929
|
+
}
|
|
4930
|
+
)
|
|
4931
|
+
]
|
|
4932
|
+
}
|
|
4933
|
+
),
|
|
4934
|
+
hasGuard && /* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: guardPos, scale: 0.15, children: [
|
|
4935
|
+
/* @__PURE__ */ jsxRuntime.jsx("octahedronGeometry", { args: [1, 0] }),
|
|
4936
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4937
|
+
"meshStandardMaterial",
|
|
4938
|
+
{
|
|
4939
|
+
color: AVL_3D_COLORS.guardPass,
|
|
4940
|
+
emissive: AVL_3D_COLORS.guardPass,
|
|
4941
|
+
emissiveIntensity: 0.8
|
|
4942
|
+
}
|
|
4943
|
+
)
|
|
4944
|
+
] }),
|
|
4945
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4946
|
+
"mesh",
|
|
4947
|
+
{
|
|
4948
|
+
position: arrowPos,
|
|
4949
|
+
quaternion: arrowQuat,
|
|
4950
|
+
scale: 0.08,
|
|
4951
|
+
children: [
|
|
4952
|
+
/* @__PURE__ */ jsxRuntime.jsx("coneGeometry", { args: [1, 2, 8] }),
|
|
4953
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4954
|
+
"meshStandardMaterial",
|
|
4955
|
+
{
|
|
4956
|
+
color,
|
|
4957
|
+
emissive: color,
|
|
4958
|
+
emissiveIntensity: 0.6
|
|
4959
|
+
}
|
|
4960
|
+
)
|
|
4961
|
+
]
|
|
4962
|
+
}
|
|
4963
|
+
),
|
|
4964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4965
|
+
Avl3DLabel,
|
|
4966
|
+
{
|
|
4967
|
+
position: labelPos,
|
|
4968
|
+
text: event,
|
|
4969
|
+
color: hovered ? "#ffffff" : color,
|
|
4970
|
+
fontSize: hovered ? 11 : 9
|
|
4971
|
+
}
|
|
4972
|
+
),
|
|
4973
|
+
hovered && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4974
|
+
Avl3DTooltip,
|
|
4975
|
+
{
|
|
4976
|
+
position: [labelPos[0], labelPos[1] + 0.6, labelPos[2]],
|
|
4977
|
+
title: event,
|
|
4978
|
+
accentColor: AVL_3D_COLORS.transitionArc,
|
|
4979
|
+
rows: [
|
|
4980
|
+
...fromState && toState ? [{ label: "Transition", value: `${fromState} \u2192 ${toState}` }] : [],
|
|
4981
|
+
...hasGuard ? [{ label: "Guard", value: "Yes" }] : [],
|
|
4982
|
+
...effectTypes && effectTypes.length > 0 ? [{ label: "Effects", value: effectTypes.slice(0, 3).join(", ") + (effectTypes.length > 3 ? ` +${effectTypes.length - 3}` : "") }] : []
|
|
4983
|
+
]
|
|
4984
|
+
}
|
|
4985
|
+
),
|
|
4986
|
+
effectTypes && effectTypes.length > 0 && effectTypes.slice(0, 4).map((effectType, ei) => {
|
|
4987
|
+
const pt = effectPositions[ei];
|
|
4988
|
+
if (!pt) return null;
|
|
4989
|
+
const eColor = effectTypeColor(effectType);
|
|
4990
|
+
return /* @__PURE__ */ jsxRuntime.jsx("group", { position: pt, children: /* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: 0.06, children: [
|
|
4991
|
+
effectType === "render-ui" ? /* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [1.5, 1.5, 0.3] }) : effectType === "persist" ? /* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.6, 0.6, 1.5, 8] }) : effectType === "emit" ? /* @__PURE__ */ jsxRuntime.jsx("sphereGeometry", { args: [1, 8, 8] }) : effectType === "navigate" ? /* @__PURE__ */ jsxRuntime.jsx("coneGeometry", { args: [0.8, 1.5, 6] }) : effectType === "set" ? /* @__PURE__ */ jsxRuntime.jsx("tetrahedronGeometry", { args: [1, 0] }) : effectType === "notify" ? /* @__PURE__ */ jsxRuntime.jsx("dodecahedronGeometry", { args: [0.8, 0] }) : effectType === "call-service" ? /* @__PURE__ */ jsxRuntime.jsx("torusGeometry", { args: [0.8, 0.3, 6, 12] }) : /* @__PURE__ */ jsxRuntime.jsx("octahedronGeometry", { args: [0.8, 0] }),
|
|
4992
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4993
|
+
"meshStandardMaterial",
|
|
4994
|
+
{
|
|
4995
|
+
color: eColor,
|
|
4996
|
+
emissive: eColor,
|
|
4997
|
+
emissiveIntensity: 0.8
|
|
4998
|
+
}
|
|
4999
|
+
)
|
|
5000
|
+
] }) }, ei);
|
|
5001
|
+
})
|
|
5002
|
+
] });
|
|
5003
|
+
};
|
|
5004
|
+
Avl3DTransitionArc.displayName = "Avl3DTransitionArc";
|
|
5005
|
+
var Avl3DTraitScene = ({
|
|
5006
|
+
data,
|
|
5007
|
+
onTransitionClick
|
|
5008
|
+
}) => {
|
|
5009
|
+
const statePositions = React21.useMemo(() => {
|
|
5010
|
+
const radius = Math.max(3, data.states.length * 0.8);
|
|
5011
|
+
const positions = fibonacciSpherePositions(data.states.length, radius);
|
|
5012
|
+
const posMap = /* @__PURE__ */ new Map();
|
|
5013
|
+
data.states.forEach((state, i) => {
|
|
5014
|
+
const pos = positions[i];
|
|
5015
|
+
posMap.set(state.name, [pos.x, pos.y, pos.z]);
|
|
5016
|
+
});
|
|
5017
|
+
return posMap;
|
|
5018
|
+
}, [data.states]);
|
|
5019
|
+
const transitionIndices = React21.useMemo(() => {
|
|
5020
|
+
const pairCount = /* @__PURE__ */ new Map();
|
|
5021
|
+
return data.transitions.map((t) => {
|
|
5022
|
+
const key = `${t.from}->${t.to}`;
|
|
5023
|
+
const idx = pairCount.get(key) ?? 0;
|
|
5024
|
+
pairCount.set(key, idx + 1);
|
|
5025
|
+
return idx;
|
|
5026
|
+
});
|
|
5027
|
+
}, [data.transitions]);
|
|
5028
|
+
const transitionCounts = React21.useMemo(() => {
|
|
5029
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
5030
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
5031
|
+
for (const t of data.transitions) {
|
|
5032
|
+
outgoing.set(t.from, (outgoing.get(t.from) ?? 0) + 1);
|
|
5033
|
+
incoming.set(t.to, (incoming.get(t.to) ?? 0) + 1);
|
|
5034
|
+
}
|
|
5035
|
+
return { incoming, outgoing };
|
|
5036
|
+
}, [data.transitions]);
|
|
5037
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
5038
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5039
|
+
Avl3DLabel,
|
|
5040
|
+
{
|
|
5041
|
+
position: [0, 5, 0],
|
|
5042
|
+
text: `${data.name} (${data.linkedEntity})`,
|
|
5043
|
+
color: "#ffffff",
|
|
5044
|
+
fontSize: 14
|
|
5045
|
+
}
|
|
5046
|
+
),
|
|
5047
|
+
data.states.map((state) => {
|
|
5048
|
+
const pos = statePositions.get(state.name);
|
|
5049
|
+
if (!pos) return null;
|
|
5050
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5051
|
+
Avl3DStateNode,
|
|
5052
|
+
{
|
|
5053
|
+
name: state.name,
|
|
5054
|
+
isInitial: state.isInitial,
|
|
5055
|
+
isTerminal: state.isTerminal,
|
|
5056
|
+
position: pos,
|
|
5057
|
+
incomingCount: transitionCounts.incoming.get(state.name) ?? 0,
|
|
5058
|
+
outgoingCount: transitionCounts.outgoing.get(state.name) ?? 0
|
|
5059
|
+
},
|
|
5060
|
+
state.name
|
|
5061
|
+
);
|
|
5062
|
+
}),
|
|
5063
|
+
data.transitions.map((transition, i) => {
|
|
5064
|
+
const fromPos = statePositions.get(transition.from);
|
|
5065
|
+
const toPos = statePositions.get(transition.to);
|
|
5066
|
+
if (!fromPos || !toPos) return null;
|
|
5067
|
+
const isSelf = transition.from === transition.to;
|
|
5068
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5069
|
+
Avl3DTransitionArc,
|
|
5070
|
+
{
|
|
5071
|
+
from: fromPos,
|
|
5072
|
+
to: toPos,
|
|
5073
|
+
event: transition.event,
|
|
5074
|
+
hasGuard: !!transition.guard,
|
|
5075
|
+
effectCount: transition.effects?.length ?? 0,
|
|
5076
|
+
effectTypes: transition.effects?.map((e) => {
|
|
5077
|
+
if (Array.isArray(e)) return String(e[0]);
|
|
5078
|
+
return typeof e === "string" ? e : "unknown";
|
|
5079
|
+
}),
|
|
5080
|
+
index: transitionIndices[i],
|
|
5081
|
+
isSelf,
|
|
5082
|
+
fromState: transition.from,
|
|
5083
|
+
toState: transition.to,
|
|
5084
|
+
onClick: () => onTransitionClick?.(i)
|
|
5085
|
+
},
|
|
5086
|
+
`${transition.from}-${transition.event}-${transition.to}-${i}`
|
|
5087
|
+
);
|
|
5088
|
+
})
|
|
5089
|
+
] });
|
|
5090
|
+
};
|
|
5091
|
+
Avl3DTraitScene.displayName = "Avl3DTraitScene";
|
|
5092
|
+
|
|
5093
|
+
// components/atoms/avl/types.ts
|
|
5094
|
+
var AVL_OPERATOR_COLORS = {
|
|
5095
|
+
arithmetic: "#4A90D9",
|
|
5096
|
+
comparison: "#E8913A",
|
|
5097
|
+
logic: "#9B59B6",
|
|
5098
|
+
string: "#27AE60",
|
|
5099
|
+
collection: "#1ABC9C"};
|
|
5100
|
+
function operatorColor(label) {
|
|
5101
|
+
if (["+", "-", "*", "/", "%", "mod"].includes(label)) return AVL_OPERATOR_COLORS.arithmetic;
|
|
5102
|
+
if (["=", "!=", "<", ">", "<=", ">=", "eq", "neq", "lt", "gt"].includes(label)) return AVL_OPERATOR_COLORS.comparison;
|
|
5103
|
+
if (["and", "or", "not", "if", "cond"].includes(label)) return AVL_OPERATOR_COLORS.logic;
|
|
5104
|
+
if (["concat", "upper", "lower", "trim", "substr"].includes(label)) return AVL_OPERATOR_COLORS.string;
|
|
5105
|
+
if (["map", "filter", "reduce", "find", "count", "sum"].includes(label)) return AVL_OPERATOR_COLORS.collection;
|
|
5106
|
+
return "#4A90D9";
|
|
5107
|
+
}
|
|
5108
|
+
function edgeGeometry(parent, child) {
|
|
5109
|
+
const p = new THREE6.Vector3(parent.x, parent.y, parent.z);
|
|
5110
|
+
const c = new THREE6.Vector3(child.x, child.y, child.z);
|
|
5111
|
+
const mid = new THREE6.Vector3().addVectors(p, c).multiplyScalar(0.5);
|
|
5112
|
+
const dir = new THREE6.Vector3().subVectors(c, p);
|
|
5113
|
+
const length = dir.length();
|
|
5114
|
+
const yAxis = new THREE6.Vector3(0, 1, 0);
|
|
5115
|
+
const angle = yAxis.angleTo(dir.normalize());
|
|
5116
|
+
const axis = new THREE6.Vector3().crossVectors(yAxis, dir).normalize();
|
|
5117
|
+
if (axis.length() < 1e-3) {
|
|
5118
|
+
return {
|
|
5119
|
+
position: [mid.x, mid.y, mid.z],
|
|
5120
|
+
rotation: [0, 0, 0],
|
|
5121
|
+
length
|
|
5122
|
+
};
|
|
5123
|
+
}
|
|
5124
|
+
return {
|
|
5125
|
+
position: [mid.x, mid.y, mid.z],
|
|
5126
|
+
rotation: [
|
|
5127
|
+
axis.x * angle,
|
|
5128
|
+
axis.y * angle,
|
|
5129
|
+
axis.z * angle
|
|
5130
|
+
],
|
|
5131
|
+
length
|
|
5132
|
+
};
|
|
5133
|
+
}
|
|
5134
|
+
var Avl3DExprTree = ({
|
|
5135
|
+
expression,
|
|
5136
|
+
position
|
|
5137
|
+
}) => {
|
|
5138
|
+
const layoutResults = React21.useMemo(() => {
|
|
5139
|
+
const origin = { x: position[0], y: position[1], z: position[2] };
|
|
5140
|
+
return treeLayout3D(expression, origin, 2.5, 1.5);
|
|
5141
|
+
}, [expression, position]);
|
|
5142
|
+
const edges = React21.useMemo(() => {
|
|
5143
|
+
const result = [];
|
|
5144
|
+
function collectEdges(node, parentPos) {
|
|
5145
|
+
const entry = layoutResults.find((r) => r.node === node);
|
|
5146
|
+
if (!entry) return;
|
|
5147
|
+
if (parentPos) {
|
|
5148
|
+
result.push({
|
|
5149
|
+
parent: parentPos,
|
|
5150
|
+
child: entry.position,
|
|
5151
|
+
key: `${parentPos.x}-${parentPos.y}-${entry.position.x}-${entry.position.y}`
|
|
5152
|
+
});
|
|
5153
|
+
}
|
|
5154
|
+
if (node.children) {
|
|
5155
|
+
for (const child of node.children) {
|
|
5156
|
+
collectEdges(child, entry.position);
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
collectEdges(expression, null);
|
|
5161
|
+
return result;
|
|
5162
|
+
}, [expression, layoutResults]);
|
|
5163
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
5164
|
+
edges.map((edge) => {
|
|
5165
|
+
const geo = edgeGeometry(edge.parent, edge.child);
|
|
5166
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5167
|
+
"mesh",
|
|
5168
|
+
{
|
|
5169
|
+
position: geo.position,
|
|
5170
|
+
rotation: geo.rotation,
|
|
5171
|
+
children: [
|
|
5172
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.015, 0.015, geo.length, 6] }),
|
|
5173
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5174
|
+
"meshStandardMaterial",
|
|
5175
|
+
{
|
|
5176
|
+
color: "#555555",
|
|
5177
|
+
transparent: true,
|
|
5178
|
+
opacity: 0.5
|
|
5179
|
+
}
|
|
5180
|
+
)
|
|
5181
|
+
]
|
|
5182
|
+
},
|
|
5183
|
+
edge.key
|
|
5184
|
+
);
|
|
5185
|
+
}),
|
|
5186
|
+
layoutResults.map((entry, i) => {
|
|
5187
|
+
const pos = [
|
|
5188
|
+
entry.position.x,
|
|
5189
|
+
entry.position.y,
|
|
5190
|
+
entry.position.z
|
|
5191
|
+
];
|
|
5192
|
+
if (entry.node.type === "operator") {
|
|
5193
|
+
const opColor = operatorColor(entry.node.label);
|
|
5194
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position: pos, children: [
|
|
5195
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { children: [
|
|
5196
|
+
/* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [0.6, 0.4, 0.3] }),
|
|
5197
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5198
|
+
"meshStandardMaterial",
|
|
5199
|
+
{
|
|
5200
|
+
color: opColor,
|
|
5201
|
+
emissive: opColor,
|
|
5202
|
+
emissiveIntensity: 0.4,
|
|
5203
|
+
roughness: 0.3
|
|
5204
|
+
}
|
|
5205
|
+
)
|
|
5206
|
+
] }),
|
|
5207
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5208
|
+
Avl3DLabel,
|
|
5209
|
+
{
|
|
5210
|
+
position: [0, -0.4, 0],
|
|
5211
|
+
text: entry.node.label,
|
|
5212
|
+
color: opColor,
|
|
5213
|
+
fontSize: 10
|
|
5214
|
+
}
|
|
5215
|
+
)
|
|
5216
|
+
] }, i);
|
|
5217
|
+
}
|
|
5218
|
+
if (entry.node.type === "binding") {
|
|
5219
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position: pos, children: [
|
|
5220
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { scale: 0.08, children: [
|
|
5221
|
+
/* @__PURE__ */ jsxRuntime.jsx("torusKnotGeometry", { args: [2, 0.6, 48, 8, 2, 3] }),
|
|
5222
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5223
|
+
"meshStandardMaterial",
|
|
5224
|
+
{
|
|
5225
|
+
color: "#4A90D9",
|
|
5226
|
+
emissive: "#4A90D9",
|
|
5227
|
+
emissiveIntensity: 0.4,
|
|
5228
|
+
transparent: true,
|
|
5229
|
+
opacity: 0.85,
|
|
5230
|
+
roughness: 0.3
|
|
5231
|
+
}
|
|
5232
|
+
)
|
|
5233
|
+
] }),
|
|
5234
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5235
|
+
Avl3DLabel,
|
|
5236
|
+
{
|
|
5237
|
+
position: [0, -0.35, 0],
|
|
5238
|
+
text: entry.node.label,
|
|
5239
|
+
color: "#4A90D9",
|
|
5240
|
+
fontSize: 9
|
|
5241
|
+
}
|
|
5242
|
+
)
|
|
5243
|
+
] }, i);
|
|
5244
|
+
}
|
|
5245
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { position: pos, children: [
|
|
5246
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [Math.PI / 6, Math.PI / 4, 0], children: [
|
|
5247
|
+
/* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [0.2, 0.2, 0.2] }),
|
|
5248
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5249
|
+
"meshStandardMaterial",
|
|
5250
|
+
{
|
|
5251
|
+
color: "#888888",
|
|
5252
|
+
emissive: "#666666",
|
|
5253
|
+
emissiveIntensity: 0.2,
|
|
5254
|
+
roughness: 0.5
|
|
5255
|
+
}
|
|
5256
|
+
)
|
|
5257
|
+
] }),
|
|
5258
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5259
|
+
Avl3DLabel,
|
|
5260
|
+
{
|
|
5261
|
+
position: [0, -0.3, 0],
|
|
5262
|
+
text: entry.node.label,
|
|
5263
|
+
color: "#999999",
|
|
5264
|
+
fontSize: 8
|
|
5265
|
+
}
|
|
5266
|
+
)
|
|
5267
|
+
] }, i);
|
|
5268
|
+
})
|
|
5269
|
+
] });
|
|
5270
|
+
};
|
|
5271
|
+
Avl3DExprTree.displayName = "Avl3DExprTree";
|
|
5272
|
+
var Avl3DTransitionScene = ({
|
|
5273
|
+
data
|
|
5274
|
+
}) => {
|
|
5275
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("group", { children: [
|
|
5276
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5277
|
+
Avl3DStateNode,
|
|
5278
|
+
{
|
|
5279
|
+
name: data.from,
|
|
5280
|
+
position: [0, 4, 0]
|
|
5281
|
+
}
|
|
5282
|
+
),
|
|
5283
|
+
/* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0, 2.2, 0], children: [
|
|
5284
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { children: [
|
|
5285
|
+
/* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [2, 0.6, 0.4] }),
|
|
5286
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5287
|
+
"meshStandardMaterial",
|
|
5288
|
+
{
|
|
5289
|
+
color: AVL_3D_COLORS.transitionArc,
|
|
5290
|
+
emissive: AVL_3D_COLORS.transitionArc,
|
|
5291
|
+
emissiveIntensity: 0.5,
|
|
5292
|
+
roughness: 0.3
|
|
5293
|
+
}
|
|
5294
|
+
)
|
|
5295
|
+
] }),
|
|
5296
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5297
|
+
Avl3DLabel,
|
|
5298
|
+
{
|
|
5299
|
+
position: [0, 0, 0.3],
|
|
5300
|
+
text: data.event,
|
|
5301
|
+
color: "#ffffff",
|
|
5302
|
+
fontSize: 13
|
|
5303
|
+
}
|
|
5304
|
+
)
|
|
5305
|
+
] }),
|
|
5306
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 3.1, 0], children: [
|
|
5307
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.02, 0.02, 1.2, 6] }),
|
|
5308
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
|
|
5309
|
+
] }),
|
|
5310
|
+
data.guard && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0, 1, 0], children: [
|
|
5311
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { rotation: [0, 0, Math.PI / 4], children: [
|
|
5312
|
+
/* @__PURE__ */ jsxRuntime.jsx("boxGeometry", { args: [0.5, 0.5, 0.3] }),
|
|
5313
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5314
|
+
"meshStandardMaterial",
|
|
5315
|
+
{
|
|
5316
|
+
color: AVL_3D_COLORS.guardPass,
|
|
5317
|
+
emissive: AVL_3D_COLORS.guardPass,
|
|
5318
|
+
emissiveIntensity: 0.6
|
|
5319
|
+
}
|
|
5320
|
+
)
|
|
5321
|
+
] }),
|
|
5322
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, 0.7, 0], children: [
|
|
5323
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.02, 0.02, 0.8, 6] }),
|
|
5324
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
|
|
5325
|
+
] }),
|
|
5326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5327
|
+
Avl3DExprTree,
|
|
5328
|
+
{
|
|
5329
|
+
expression: data.guard,
|
|
5330
|
+
position: [3, 0, 0]
|
|
5331
|
+
}
|
|
5332
|
+
),
|
|
5333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5334
|
+
Avl3DLabel,
|
|
5335
|
+
{
|
|
5336
|
+
position: [1.5, 0.3, 0],
|
|
5337
|
+
text: "guard",
|
|
5338
|
+
color: AVL_3D_COLORS.guardPass,
|
|
5339
|
+
fontSize: 9
|
|
5340
|
+
}
|
|
5341
|
+
)
|
|
5342
|
+
] }),
|
|
5343
|
+
data.effects.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("group", { position: [0, data.guard ? -0.5 : 0.5, 0], children: [
|
|
5344
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5345
|
+
Avl3DLabel,
|
|
5346
|
+
{
|
|
5347
|
+
position: [0, 0.4, 0],
|
|
5348
|
+
text: `${data.effects.length} effect${data.effects.length > 1 ? "s" : ""}`,
|
|
5349
|
+
color: "#E8913A",
|
|
5350
|
+
fontSize: 10
|
|
5351
|
+
}
|
|
5352
|
+
),
|
|
5353
|
+
data.effects.map((effect, i) => {
|
|
5354
|
+
const xOffset = (i - (data.effects.length - 1) / 2) * 3;
|
|
5355
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5356
|
+
Avl3DExprTree,
|
|
5357
|
+
{
|
|
5358
|
+
expression: effect,
|
|
5359
|
+
position: [xOffset, -1, 0]
|
|
5360
|
+
},
|
|
5361
|
+
i
|
|
5362
|
+
);
|
|
5363
|
+
})
|
|
5364
|
+
] }),
|
|
5365
|
+
/* @__PURE__ */ jsxRuntime.jsxs("mesh", { position: [0, data.guard ? -2.5 : -1.5, 0], children: [
|
|
5366
|
+
/* @__PURE__ */ jsxRuntime.jsx("cylinderGeometry", { args: [0.02, 0.02, 1.2, 6] }),
|
|
5367
|
+
/* @__PURE__ */ jsxRuntime.jsx("meshStandardMaterial", { color: "#555555", transparent: true, opacity: 0.5 })
|
|
5368
|
+
] }),
|
|
5369
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5370
|
+
Avl3DStateNode,
|
|
5371
|
+
{
|
|
5372
|
+
name: data.to,
|
|
5373
|
+
position: [0, data.guard ? -3.5 : -2.5, 0]
|
|
5374
|
+
}
|
|
5375
|
+
)
|
|
5376
|
+
] });
|
|
5377
|
+
};
|
|
5378
|
+
Avl3DTransitionScene.displayName = "Avl3DTransitionScene";
|
|
5379
|
+
var BLOOM_CONFIG = {
|
|
5380
|
+
application: { intensity: 0.4, luminanceThreshold: 0.88, luminanceSmoothing: 0.95 },
|
|
5381
|
+
orbital: { intensity: 0.5, luminanceThreshold: 0.85, luminanceSmoothing: 0.9 },
|
|
5382
|
+
trait: { intensity: 0.3, luminanceThreshold: 0.92, luminanceSmoothing: 0.9 },
|
|
5383
|
+
transition: { intensity: 0.35, luminanceThreshold: 0.9, luminanceSmoothing: 0.9 }
|
|
5384
|
+
};
|
|
5385
|
+
var DOF_CONFIG = {
|
|
5386
|
+
application: null,
|
|
5387
|
+
orbital: { focusDistance: 0.02, focalLength: 0.02, bokehScale: 1.5 },
|
|
5388
|
+
trait: null,
|
|
5389
|
+
transition: null
|
|
5390
|
+
};
|
|
5391
|
+
var SPARKLE_CONFIGS = {
|
|
5392
|
+
application: [
|
|
5393
|
+
{ count: 60, size: 1.2, speed: 0.2, opacity: 0.35, scale: 35, color: AVL_3D_COLORS.sparkle },
|
|
5394
|
+
{ count: 15, size: 1.8, speed: 0.1, opacity: 0.2, scale: 25, color: AVL_3D_COLORS.sparkleWarm }
|
|
5395
|
+
],
|
|
5396
|
+
orbital: [
|
|
5397
|
+
{ count: 30, size: 0.8, speed: 0.15, opacity: 0.25, scale: 18, color: AVL_3D_COLORS.sparkle },
|
|
5398
|
+
{ count: 8, size: 1.2, speed: 0.08, opacity: 0.15, scale: 12, color: AVL_3D_COLORS.sparkleWarm }
|
|
5399
|
+
],
|
|
5400
|
+
trait: [
|
|
5401
|
+
{ count: 15, size: 0.6, speed: 0.1, opacity: 0.2, scale: 12, color: AVL_3D_COLORS.sparkle }
|
|
5402
|
+
],
|
|
5403
|
+
transition: [
|
|
5404
|
+
{ count: 8, size: 0.4, speed: 0.08, opacity: 0.15, scale: 8, color: AVL_3D_COLORS.sparkle }
|
|
5405
|
+
]
|
|
5406
|
+
};
|
|
5407
|
+
var STARS_CONFIG = {
|
|
5408
|
+
application: { radius: 80, count: 3e3, factor: 5, fade: true },
|
|
5409
|
+
orbital: { radius: 60, count: 1500, factor: 4, fade: true },
|
|
5410
|
+
trait: { radius: 40, count: 800, factor: 3, fade: true },
|
|
5411
|
+
transition: { radius: 30, count: 400, factor: 2, fade: true }
|
|
5412
|
+
};
|
|
5413
|
+
var Avl3DEffects = ({
|
|
5414
|
+
level,
|
|
5415
|
+
enabled = true
|
|
5416
|
+
}) => {
|
|
5417
|
+
if (!enabled) return null;
|
|
5418
|
+
const bloom = BLOOM_CONFIG[level];
|
|
5419
|
+
const dof = DOF_CONFIG[level];
|
|
5420
|
+
const sparkles = SPARKLE_CONFIGS[level];
|
|
5421
|
+
const stars = STARS_CONFIG[level];
|
|
5422
|
+
const starsKey = React21.useMemo(() => `stars-${level}`, [level]);
|
|
5423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5424
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5425
|
+
drei.Stars,
|
|
5426
|
+
{
|
|
5427
|
+
radius: stars.radius,
|
|
5428
|
+
count: stars.count,
|
|
5429
|
+
factor: stars.factor,
|
|
5430
|
+
saturation: 0.1,
|
|
5431
|
+
fade: stars.fade,
|
|
5432
|
+
speed: 0.3
|
|
5433
|
+
},
|
|
5434
|
+
starsKey
|
|
5435
|
+
),
|
|
5436
|
+
sparkles.map((cfg, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5437
|
+
drei.Sparkles,
|
|
5438
|
+
{
|
|
5439
|
+
count: cfg.count,
|
|
5440
|
+
size: cfg.size,
|
|
5441
|
+
speed: cfg.speed,
|
|
5442
|
+
opacity: cfg.opacity,
|
|
5443
|
+
scale: cfg.scale,
|
|
5444
|
+
color: cfg.color
|
|
5445
|
+
},
|
|
5446
|
+
`sparkle-${level}-${i}`
|
|
5447
|
+
)),
|
|
5448
|
+
dof ? /* @__PURE__ */ jsxRuntime.jsxs(postprocessing.EffectComposer, { children: [
|
|
5449
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5450
|
+
postprocessing.Bloom,
|
|
5451
|
+
{
|
|
5452
|
+
intensity: bloom.intensity,
|
|
5453
|
+
luminanceThreshold: bloom.luminanceThreshold,
|
|
5454
|
+
luminanceSmoothing: bloom.luminanceSmoothing,
|
|
5455
|
+
mipmapBlur: true
|
|
5456
|
+
}
|
|
5457
|
+
),
|
|
5458
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5459
|
+
postprocessing.DepthOfField,
|
|
5460
|
+
{
|
|
5461
|
+
focusDistance: dof.focusDistance,
|
|
5462
|
+
focalLength: dof.focalLength,
|
|
5463
|
+
bokehScale: dof.bokehScale
|
|
5464
|
+
}
|
|
5465
|
+
),
|
|
5466
|
+
/* @__PURE__ */ jsxRuntime.jsx(postprocessing.Vignette, { eskil: false, offset: 0.2, darkness: 0.35 })
|
|
5467
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(postprocessing.EffectComposer, { children: [
|
|
5468
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5469
|
+
postprocessing.Bloom,
|
|
5470
|
+
{
|
|
5471
|
+
intensity: bloom.intensity,
|
|
5472
|
+
luminanceThreshold: bloom.luminanceThreshold,
|
|
5473
|
+
luminanceSmoothing: bloom.luminanceSmoothing,
|
|
5474
|
+
mipmapBlur: true
|
|
5475
|
+
}
|
|
5476
|
+
),
|
|
5477
|
+
/* @__PURE__ */ jsxRuntime.jsx(postprocessing.Vignette, { eskil: false, offset: 0.2, darkness: 0.35 })
|
|
5478
|
+
] })
|
|
5479
|
+
] });
|
|
5480
|
+
};
|
|
5481
|
+
Avl3DEffects.displayName = "Avl3DEffects";
|
|
5482
|
+
var DEFAULT_CONFIG2 = {
|
|
5483
|
+
modelOverrides: {},
|
|
5484
|
+
effectsEnabled: true
|
|
5485
|
+
};
|
|
5486
|
+
var Avl3DContext = React21.createContext(DEFAULT_CONFIG2);
|
|
5487
|
+
function useAvl3DConfig() {
|
|
5488
|
+
return React21.useContext(Avl3DContext);
|
|
5489
|
+
}
|
|
5490
|
+
function CameraController2({ targetPosition, targetLookAt, animated }) {
|
|
5491
|
+
const { camera } = fiber.useThree();
|
|
5492
|
+
const targetPosVec = React21.useRef(new THREE6__namespace.Vector3(...targetPosition));
|
|
5493
|
+
const targetLookVec = React21.useRef(new THREE6__namespace.Vector3(...targetLookAt));
|
|
5494
|
+
const isAnimating = React21.useRef(false);
|
|
5495
|
+
React21.useEffect(() => {
|
|
5496
|
+
const newTarget = new THREE6__namespace.Vector3(...targetPosition);
|
|
5497
|
+
const newLookAt = new THREE6__namespace.Vector3(...targetLookAt);
|
|
5498
|
+
if (!newTarget.equals(targetPosVec.current) || !newLookAt.equals(targetLookVec.current)) {
|
|
5499
|
+
targetPosVec.current.copy(newTarget);
|
|
5500
|
+
targetLookVec.current.copy(newLookAt);
|
|
5501
|
+
if (animated) {
|
|
5502
|
+
isAnimating.current = true;
|
|
5503
|
+
} else {
|
|
5504
|
+
camera.position.copy(targetPosVec.current);
|
|
5505
|
+
camera.lookAt(targetLookVec.current);
|
|
5506
|
+
}
|
|
5507
|
+
}
|
|
5508
|
+
}, [targetPosition, targetLookAt, animated, camera]);
|
|
5509
|
+
fiber.useFrame((_, delta) => {
|
|
5510
|
+
if (!isAnimating.current) return;
|
|
5511
|
+
const speed = 3;
|
|
5512
|
+
camera.position.x = THREE6__namespace.MathUtils.damp(camera.position.x, targetPosVec.current.x, speed, delta);
|
|
5513
|
+
camera.position.y = THREE6__namespace.MathUtils.damp(camera.position.y, targetPosVec.current.y, speed, delta);
|
|
5514
|
+
camera.position.z = THREE6__namespace.MathUtils.damp(camera.position.z, targetPosVec.current.z, speed, delta);
|
|
5515
|
+
camera.lookAt(targetLookVec.current);
|
|
5516
|
+
const dist = camera.position.distanceTo(targetPosVec.current);
|
|
5517
|
+
if (dist < 0.05) {
|
|
5518
|
+
isAnimating.current = false;
|
|
5519
|
+
}
|
|
5520
|
+
});
|
|
5521
|
+
return null;
|
|
5522
|
+
}
|
|
5523
|
+
function SceneFade({ animating, children }) {
|
|
5524
|
+
const groupRef = React21.useRef(null);
|
|
5525
|
+
const opacityRef = React21.useRef(1);
|
|
5526
|
+
fiber.useFrame((_, delta) => {
|
|
5527
|
+
if (!groupRef.current) return;
|
|
5528
|
+
const target = animating ? 0 : 1;
|
|
5529
|
+
opacityRef.current = THREE6__namespace.MathUtils.damp(opacityRef.current, target, 5, delta);
|
|
5530
|
+
groupRef.current.visible = opacityRef.current > 0.05;
|
|
5531
|
+
const s = 0.9 + opacityRef.current * 0.1;
|
|
5532
|
+
groupRef.current.scale.setScalar(s);
|
|
5533
|
+
});
|
|
5534
|
+
return /* @__PURE__ */ jsxRuntime.jsx("group", { ref: groupRef, children });
|
|
5535
|
+
}
|
|
5536
|
+
var Avl3DViewer = ({
|
|
5537
|
+
schema: schemaProp,
|
|
5538
|
+
className,
|
|
5539
|
+
animated = true,
|
|
5540
|
+
initialOrbital,
|
|
5541
|
+
initialTrait,
|
|
5542
|
+
onZoomChange,
|
|
5543
|
+
width = "100%",
|
|
5544
|
+
height = 500,
|
|
5545
|
+
effects = true,
|
|
5546
|
+
modelOverrides = {}
|
|
5547
|
+
}) => {
|
|
5548
|
+
const schema = React21.useMemo(() => {
|
|
5549
|
+
if (typeof schemaProp === "string") {
|
|
5550
|
+
try {
|
|
5551
|
+
return JSON.parse(schemaProp);
|
|
5552
|
+
} catch {
|
|
5553
|
+
return { name: "Error", orbitals: [] };
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
return schemaProp;
|
|
5557
|
+
}, [schemaProp]);
|
|
5558
|
+
const configValue = React21.useMemo(() => ({
|
|
5559
|
+
modelOverrides,
|
|
5560
|
+
effectsEnabled: effects
|
|
5561
|
+
}), [modelOverrides, effects]);
|
|
5562
|
+
const [state, dispatch] = React21.useReducer(zoomReducer, initialZoomState);
|
|
5563
|
+
React21.useEffect(() => {
|
|
5564
|
+
if (initialOrbital) {
|
|
5565
|
+
dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: initialOrbital, targetPosition: { x: 0, y: 0 } });
|
|
5566
|
+
setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
|
|
5567
|
+
if (initialTrait) {
|
|
5568
|
+
setTimeout(() => {
|
|
5569
|
+
dispatch({ type: "ZOOM_INTO_TRAIT", trait: initialTrait, targetPosition: { x: 0, y: 0 } });
|
|
5570
|
+
setTimeout(() => dispatch({ type: "ANIMATION_COMPLETE" }), 0);
|
|
5571
|
+
}, 10);
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
}, [initialOrbital, initialTrait]);
|
|
5575
|
+
React21.useEffect(() => {
|
|
5576
|
+
onZoomChange?.(state.level, {
|
|
5577
|
+
orbital: state.selectedOrbital ?? void 0,
|
|
5578
|
+
trait: state.selectedTrait ?? void 0
|
|
5579
|
+
});
|
|
5580
|
+
}, [state.level, state.selectedOrbital, state.selectedTrait, onZoomChange]);
|
|
5581
|
+
React21.useEffect(() => {
|
|
5582
|
+
if (!state.animating) return;
|
|
5583
|
+
const timer = setTimeout(() => {
|
|
5584
|
+
dispatch({ type: "ANIMATION_COMPLETE" });
|
|
5585
|
+
}, 800);
|
|
5586
|
+
return () => clearTimeout(timer);
|
|
5587
|
+
}, [state.animating]);
|
|
5588
|
+
const handleKeyDown = React21.useCallback((e) => {
|
|
5589
|
+
if (e.key === "Escape") {
|
|
5590
|
+
dispatch({ type: "ZOOM_OUT" });
|
|
5591
|
+
}
|
|
5592
|
+
}, []);
|
|
5593
|
+
const handleOrbitalClick = React21.useCallback((name) => {
|
|
5594
|
+
dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: name, targetPosition: { x: 0, y: 0 } });
|
|
5595
|
+
}, []);
|
|
5596
|
+
const handleTraitClick = React21.useCallback((name) => {
|
|
5597
|
+
dispatch({ type: "ZOOM_INTO_TRAIT", trait: name, targetPosition: { x: 0, y: 0 } });
|
|
5598
|
+
}, []);
|
|
5599
|
+
const [highlightedTrait, setHighlightedTrait] = React21__default.default.useState(null);
|
|
5600
|
+
const handleTransitionClick = React21.useCallback((index) => {
|
|
5601
|
+
dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex: index, targetPosition: { x: 0, y: 0 } });
|
|
5602
|
+
}, []);
|
|
5603
|
+
const handleBreadcrumbClick = React21.useCallback((targetLevel) => {
|
|
5604
|
+
const levelOrder = ["application", "orbital", "trait", "transition"];
|
|
5605
|
+
const currentIdx = levelOrder.indexOf(state.level);
|
|
5606
|
+
const targetIdx = levelOrder.indexOf(targetLevel);
|
|
5607
|
+
if (targetIdx < currentIdx) {
|
|
5608
|
+
dispatch({ type: "ZOOM_OUT" });
|
|
5609
|
+
}
|
|
5610
|
+
}, [state.level]);
|
|
5611
|
+
const cameraConfig = CAMERA_POSITIONS[state.level];
|
|
5612
|
+
const sceneContent = React21.useMemo(() => {
|
|
5613
|
+
switch (state.level) {
|
|
5614
|
+
case "application": {
|
|
5615
|
+
const data = parseApplicationLevel(schema);
|
|
5616
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5617
|
+
Avl3DApplicationScene,
|
|
5618
|
+
{
|
|
5619
|
+
data,
|
|
5620
|
+
onOrbitalClick: handleOrbitalClick
|
|
5621
|
+
}
|
|
5622
|
+
);
|
|
5623
|
+
}
|
|
5624
|
+
case "orbital": {
|
|
5625
|
+
if (!state.selectedOrbital) return null;
|
|
5626
|
+
const orbData = parseOrbitalLevel(schema, state.selectedOrbital);
|
|
5627
|
+
if (!orbData) return null;
|
|
5628
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5629
|
+
Avl3DOrbitalScene,
|
|
5630
|
+
{
|
|
5631
|
+
data: orbData,
|
|
5632
|
+
onTraitClick: handleTraitClick,
|
|
5633
|
+
highlightedTrait,
|
|
5634
|
+
onTraitHighlight: setHighlightedTrait
|
|
5635
|
+
}
|
|
5636
|
+
);
|
|
5637
|
+
}
|
|
5638
|
+
case "trait": {
|
|
5639
|
+
if (!state.selectedOrbital || !state.selectedTrait) return null;
|
|
5640
|
+
const traitData = parseTraitLevel(schema, state.selectedOrbital, state.selectedTrait);
|
|
5641
|
+
if (!traitData) return null;
|
|
5642
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5643
|
+
Avl3DTraitScene,
|
|
5644
|
+
{
|
|
5645
|
+
data: traitData,
|
|
5646
|
+
onTransitionClick: handleTransitionClick
|
|
5647
|
+
}
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
case "transition": {
|
|
5651
|
+
if (!state.selectedOrbital || !state.selectedTrait || state.selectedTransition === null) return null;
|
|
5652
|
+
const transData = parseTransitionLevel(schema, state.selectedOrbital, state.selectedTrait, state.selectedTransition);
|
|
5653
|
+
if (!transData) return null;
|
|
5654
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5655
|
+
Avl3DTransitionScene,
|
|
5656
|
+
{
|
|
5657
|
+
data: transData
|
|
5658
|
+
}
|
|
5659
|
+
);
|
|
5660
|
+
}
|
|
5661
|
+
default:
|
|
5662
|
+
return null;
|
|
5663
|
+
}
|
|
5664
|
+
}, [state.level, state.selectedOrbital, state.selectedTrait, state.selectedTransition, schema, handleOrbitalClick, handleTraitClick, handleTransitionClick, highlightedTrait, setHighlightedTrait]);
|
|
5665
|
+
const breadcrumbs = getBreadcrumbs(state);
|
|
5666
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5667
|
+
Box,
|
|
5668
|
+
{
|
|
5669
|
+
className: `relative ${className ?? ""}`,
|
|
5670
|
+
style: {
|
|
5671
|
+
width,
|
|
5672
|
+
height: typeof height === "number" ? `${height}px` : height,
|
|
5673
|
+
backgroundColor: AVL_3D_COLORS.background,
|
|
5674
|
+
borderRadius: "8px",
|
|
5675
|
+
overflow: "hidden"
|
|
5676
|
+
},
|
|
5677
|
+
onKeyDown: handleKeyDown,
|
|
5678
|
+
tabIndex: 0,
|
|
5679
|
+
children: [
|
|
5680
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5681
|
+
HStack,
|
|
5682
|
+
{
|
|
5683
|
+
gap: "xs",
|
|
5684
|
+
align: "center",
|
|
5685
|
+
className: "absolute top-2 left-2 z-10 bg-[var(--color-surface)]/80 backdrop-blur rounded-md px-3 py-1.5",
|
|
5686
|
+
children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxRuntime.jsxs(React21__default.default.Fragment, { children: [
|
|
5687
|
+
i > 0 && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "muted", className: "mx-1", children: "/" }),
|
|
5688
|
+
i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5689
|
+
Box,
|
|
5690
|
+
{
|
|
5691
|
+
as: "span",
|
|
5692
|
+
className: "cursor-pointer hover:underline",
|
|
5693
|
+
onClick: () => handleBreadcrumbClick(crumb.level),
|
|
5694
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "muted", children: crumb.label })
|
|
5695
|
+
}
|
|
5696
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "primary", className: "font-bold", children: crumb.label })
|
|
5697
|
+
] }, crumb.level))
|
|
5698
|
+
}
|
|
5699
|
+
),
|
|
5700
|
+
state.level !== "application" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5701
|
+
Typography,
|
|
5702
|
+
{
|
|
5703
|
+
variant: "small",
|
|
5704
|
+
color: "muted",
|
|
5705
|
+
className: "absolute bottom-2 right-2 z-10 bg-[var(--color-surface)]/60 backdrop-blur rounded px-2 py-1",
|
|
5706
|
+
children: "Press Esc to zoom out"
|
|
5707
|
+
}
|
|
5708
|
+
),
|
|
5709
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5710
|
+
fiber.Canvas,
|
|
5711
|
+
{
|
|
5712
|
+
style: { width: "100%", height: "100%" },
|
|
5713
|
+
camera: {
|
|
5714
|
+
position: cameraConfig.position,
|
|
5715
|
+
fov: 60,
|
|
5716
|
+
near: 0.1,
|
|
5717
|
+
far: 200
|
|
5718
|
+
},
|
|
5719
|
+
onCreated: ({ gl }) => {
|
|
5720
|
+
gl.setClearColor(AVL_3D_COLORS.background);
|
|
5721
|
+
},
|
|
5722
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Avl3DContext.Provider, { value: configValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5723
|
+
Scene3D,
|
|
5724
|
+
{
|
|
5725
|
+
background: AVL_3D_COLORS.background,
|
|
5726
|
+
fog: { color: AVL_3D_COLORS.fog, near: 30, far: 80 },
|
|
5727
|
+
children: [
|
|
5728
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5729
|
+
Camera3D,
|
|
5730
|
+
{
|
|
5731
|
+
mode: "perspective",
|
|
5732
|
+
position: cameraConfig.position,
|
|
5733
|
+
target: cameraConfig.target,
|
|
5734
|
+
enableOrbit: true,
|
|
5735
|
+
minDistance: 3,
|
|
5736
|
+
maxDistance: 80
|
|
5737
|
+
}
|
|
5738
|
+
),
|
|
5739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5740
|
+
Lighting3D,
|
|
5741
|
+
{
|
|
5742
|
+
ambientIntensity: 0.35,
|
|
5743
|
+
ambientColor: "#8090c0",
|
|
5744
|
+
directionalIntensity: 0.5,
|
|
5745
|
+
directionalColor: "#c0d0f0",
|
|
5746
|
+
directionalPosition: [8, 15, 12],
|
|
5747
|
+
shadows: false
|
|
5748
|
+
}
|
|
5749
|
+
),
|
|
5750
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5751
|
+
"pointLight",
|
|
5752
|
+
{
|
|
5753
|
+
position: [0, -10, 0],
|
|
5754
|
+
color: "#2040a0",
|
|
5755
|
+
intensity: 0.15,
|
|
5756
|
+
distance: 50,
|
|
5757
|
+
decay: 2
|
|
5758
|
+
}
|
|
5759
|
+
),
|
|
5760
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5761
|
+
CameraController2,
|
|
5762
|
+
{
|
|
5763
|
+
targetPosition: cameraConfig.position,
|
|
5764
|
+
targetLookAt: cameraConfig.target,
|
|
5765
|
+
animated
|
|
5766
|
+
}
|
|
5767
|
+
),
|
|
5768
|
+
/* @__PURE__ */ jsxRuntime.jsx(SceneFade, { animating: state.animating, children: sceneContent }),
|
|
5769
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avl3DEffects, { level: state.level, enabled: effects })
|
|
5770
|
+
]
|
|
5771
|
+
}
|
|
5772
|
+
) })
|
|
5773
|
+
}
|
|
5774
|
+
)
|
|
5775
|
+
]
|
|
5776
|
+
}
|
|
5777
|
+
);
|
|
5778
|
+
};
|
|
5779
|
+
Avl3DViewer.displayName = "Avl3DViewer";
|
|
3367
5780
|
function isInFrustum(position, camera, padding = 0) {
|
|
3368
5781
|
const frustum = new THREE6__namespace.Frustum();
|
|
3369
5782
|
const projScreenMatrix = new THREE6__namespace.Matrix4();
|
|
@@ -3546,7 +5959,16 @@ var SpatialHashGrid = class {
|
|
|
3546
5959
|
}
|
|
3547
5960
|
};
|
|
3548
5961
|
|
|
5962
|
+
exports.AVL_3D_COLORS = AVL_3D_COLORS;
|
|
3549
5963
|
exports.AssetLoader = AssetLoader;
|
|
5964
|
+
exports.Avl3DApplicationScene = Avl3DApplicationScene;
|
|
5965
|
+
exports.Avl3DContext = Avl3DContext;
|
|
5966
|
+
exports.Avl3DEffects = Avl3DEffects;
|
|
5967
|
+
exports.Avl3DOrbitalScene = Avl3DOrbitalScene;
|
|
5968
|
+
exports.Avl3DTraitScene = Avl3DTraitScene;
|
|
5969
|
+
exports.Avl3DTransitionScene = Avl3DTransitionScene;
|
|
5970
|
+
exports.Avl3DViewer = Avl3DViewer;
|
|
5971
|
+
exports.CAMERA_POSITIONS = CAMERA_POSITIONS;
|
|
3550
5972
|
exports.Camera3D = Camera3D;
|
|
3551
5973
|
exports.Canvas3DErrorBoundary = Canvas3DErrorBoundary;
|
|
3552
5974
|
exports.Canvas3DLoadingState = Canvas3DLoadingState;
|
|
@@ -3563,25 +5985,32 @@ exports.Scene3D = Scene3D;
|
|
|
3563
5985
|
exports.SpatialHashGrid = SpatialHashGrid;
|
|
3564
5986
|
exports.TileRenderer = TileRenderer;
|
|
3565
5987
|
exports.UnitRenderer = UnitRenderer;
|
|
5988
|
+
exports.arcCurve3D = arcCurve3D;
|
|
3566
5989
|
exports.assetLoader = assetLoader;
|
|
3567
5990
|
exports.calculateLODLevel = calculateLODLevel;
|
|
3568
5991
|
exports.createGridHighlight = createGridHighlight;
|
|
3569
5992
|
exports.cullInstancedMesh = cullInstancedMesh;
|
|
5993
|
+
exports.fibonacciSpherePositions = fibonacciSpherePositions;
|
|
3570
5994
|
exports.filterByFrustum = filterByFrustum;
|
|
3571
5995
|
exports.getCellsInRadius = getCellsInRadius;
|
|
3572
5996
|
exports.getNeighbors = getNeighbors;
|
|
3573
5997
|
exports.getVisibleIndices = getVisibleIndices;
|
|
5998
|
+
exports.goldenSpiralPositions = goldenSpiralPositions;
|
|
3574
5999
|
exports.gridDistance = gridDistance;
|
|
3575
6000
|
exports.gridManhattanDistance = gridManhattanDistance;
|
|
3576
6001
|
exports.gridToWorld = gridToWorld;
|
|
3577
6002
|
exports.isInBounds = isInBounds;
|
|
3578
6003
|
exports.isInFrustum = isInFrustum;
|
|
3579
6004
|
exports.normalizeMouseCoordinates = normalizeMouseCoordinates;
|
|
6005
|
+
exports.orbitRingPositions = orbitRingPositions;
|
|
3580
6006
|
exports.preloadFeatures = preloadFeatures;
|
|
3581
6007
|
exports.raycastToObjects = raycastToObjects;
|
|
3582
6008
|
exports.raycastToPlane = raycastToPlane;
|
|
6009
|
+
exports.selfLoopCurve3D = selfLoopCurve3D;
|
|
6010
|
+
exports.treeLayout3D = treeLayout3D;
|
|
3583
6011
|
exports.updateInstanceLOD = updateInstanceLOD;
|
|
3584
6012
|
exports.useAssetLoader = useAssetLoader;
|
|
6013
|
+
exports.useAvl3DConfig = useAvl3DConfig;
|
|
3585
6014
|
exports.useGameCanvas3DEvents = useGameCanvas3DEvents;
|
|
3586
6015
|
exports.usePhysics3DController = usePhysics3DController;
|
|
3587
6016
|
exports.useRaycaster = useRaycaster;
|