@almadar/ui 5.148.0 → 5.149.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{GameAudioProvider-CPGwD49P.d.cts → GameAudioProvider-B48iXwz3.d.ts} +2 -50
- package/dist/{GameAudioProvider-CPGwD49P.d.ts → GameAudioProvider-CQAdPreB.d.cts} +2 -50
- package/dist/avl/index.cjs +438 -13
- package/dist/avl/index.js +438 -13
- package/dist/{avl-schema-parser-DVmrgdwc.d.cts → avl-schema-parser-CVzkNzg7.d.cts} +18 -9
- package/dist/{avl-schema-parser-BRJ77Yze.d.ts → avl-schema-parser-Cx_4SVg9.d.ts} +18 -9
- package/dist/{cn-BAn68sNO.d.cts → cn-BnAJZcNb.d.cts} +2 -8
- package/dist/{cn-CWxxLkri.d.ts → cn-DJTUjk1M.d.ts} +2 -8
- package/dist/components/index.cjs +448 -16
- package/dist/components/index.d.cts +269 -95
- package/dist/components/index.d.ts +269 -95
- package/dist/components/index.js +444 -18
- package/dist/lib/drawable/three/index.cjs +56 -29
- package/dist/lib/drawable/three/index.d.cts +4 -3
- package/dist/lib/drawable/three/index.d.ts +4 -3
- package/dist/lib/drawable/three/index.js +56 -29
- package/dist/lib/index.d.cts +3 -2
- package/dist/lib/index.d.ts +3 -2
- package/dist/{paintDispatch-Cb_hQj4Y.d.ts → paintDispatch-BjZjUbcb.d.cts} +63 -69
- package/dist/{paintDispatch-Cb_hQj4Y.d.cts → paintDispatch-CxdLjHQq.d.ts} +63 -69
- package/dist/providers/index.cjs +438 -13
- package/dist/providers/index.d.cts +2 -1
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/index.js +438 -13
- package/dist/runtime/index.cjs +438 -13
- package/dist/runtime/index.js +438 -13
- package/dist/types-B3nHgnMG.d.cts +51 -0
- package/dist/types-B3nHgnMG.d.ts +51 -0
- package/package.json +3 -3
|
@@ -9878,23 +9878,188 @@ var init_BehaviorView = __esm({
|
|
|
9878
9878
|
exports.BehaviorView.displayName = "BehaviorView";
|
|
9879
9879
|
}
|
|
9880
9880
|
});
|
|
9881
|
-
|
|
9881
|
+
function LearningScene3D({
|
|
9882
|
+
className,
|
|
9883
|
+
width = 600,
|
|
9884
|
+
height = 400,
|
|
9885
|
+
title,
|
|
9886
|
+
backgroundColor,
|
|
9887
|
+
drawables,
|
|
9888
|
+
camera,
|
|
9889
|
+
lighting,
|
|
9890
|
+
post,
|
|
9891
|
+
showGrid = false,
|
|
9892
|
+
shadows,
|
|
9893
|
+
interactive,
|
|
9894
|
+
isLoading,
|
|
9895
|
+
error,
|
|
9896
|
+
onItemClick
|
|
9897
|
+
}) {
|
|
9898
|
+
const instanceId = React77.useId().replace(/[^a-zA-Z0-9]/g, "");
|
|
9899
|
+
const clickEvent = onItemClick ? `LEARNING_SCENE_3D.ITEM_CLICK.${instanceId}` : void 0;
|
|
9900
|
+
const onItemClickRef = React77.useRef(onItemClick);
|
|
9901
|
+
onItemClickRef.current = onItemClick;
|
|
9902
|
+
useEventListener(`UI:${clickEvent ?? "LEARNING_SCENE_3D.ITEM_CLICK.__disabled"}`, (event) => {
|
|
9903
|
+
const unitId = event.payload?.unitId;
|
|
9904
|
+
if (typeof unitId === "string") onItemClickRef.current?.(unitId);
|
|
9905
|
+
});
|
|
9906
|
+
const props3d = {
|
|
9907
|
+
drawables,
|
|
9908
|
+
isLoading,
|
|
9909
|
+
error: error ? error.message : null,
|
|
9910
|
+
cameraMode: camera?.mode ?? "perspective",
|
|
9911
|
+
...camera?.zoom !== void 0 ? { zoom: camera.zoom } : {},
|
|
9912
|
+
...camera?.fov !== void 0 ? { fov: camera.fov } : {},
|
|
9913
|
+
...camera?.azimuth !== void 0 ? { azimuth: camera.azimuth } : {},
|
|
9914
|
+
...camera?.elevation !== void 0 ? { elevation: camera.elevation } : {},
|
|
9915
|
+
...camera?.target !== void 0 ? { followTarget: camera.target } : {},
|
|
9916
|
+
backgroundColor,
|
|
9917
|
+
showGrid,
|
|
9918
|
+
...shadows !== void 0 ? { shadows } : {},
|
|
9919
|
+
...interactive !== void 0 ? { controlsEnabled: interactive } : {},
|
|
9920
|
+
lighting,
|
|
9921
|
+
post,
|
|
9922
|
+
...clickEvent !== void 0 ? { unitClickEvent: clickEvent } : {}
|
|
9923
|
+
};
|
|
9924
|
+
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", children: [
|
|
9925
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", children: title }) : null,
|
|
9926
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { width, height, display: "flex" }, children: /* @__PURE__ */ jsxRuntime.jsx(React77.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(Canvas3DHost, { ...props3d }) }) })
|
|
9927
|
+
] }) });
|
|
9928
|
+
}
|
|
9929
|
+
function meshSphere(id, x, y, z, radius, color, opts) {
|
|
9930
|
+
return {
|
|
9931
|
+
type: "draw-mesh",
|
|
9932
|
+
...id !== void 0 ? { id } : {},
|
|
9933
|
+
shape: opts?.shape ?? "sphere",
|
|
9934
|
+
position: { x, y, z },
|
|
9935
|
+
radius,
|
|
9936
|
+
pivot: "center",
|
|
9937
|
+
segments: opts?.segments ?? 24,
|
|
9938
|
+
material: { color, ...opts?.material },
|
|
9939
|
+
...opts?.opacity !== void 0 ? { opacity: opts.opacity } : {}
|
|
9940
|
+
};
|
|
9941
|
+
}
|
|
9942
|
+
function axisRotation(from, to) {
|
|
9943
|
+
const wx = to[0] - from[0];
|
|
9944
|
+
const wy = to[2] - from[2];
|
|
9945
|
+
const wz = to[1] - from[1];
|
|
9946
|
+
const len = Math.sqrt(wx * wx + wy * wy + wz * wz);
|
|
9947
|
+
const tilt = Math.acos(Math.min(1, Math.max(-1, len > 0 ? wy / len : 1)));
|
|
9948
|
+
return [0, Math.atan2(wz, -wx), tilt];
|
|
9949
|
+
}
|
|
9950
|
+
function segmentLength(from, to) {
|
|
9951
|
+
const dx = to[0] - from[0];
|
|
9952
|
+
const dy = to[1] - from[1];
|
|
9953
|
+
const dz = to[2] - from[2];
|
|
9954
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
9955
|
+
}
|
|
9956
|
+
function cylinderBetween(from, to, radius, color) {
|
|
9957
|
+
const len = segmentLength(from, to);
|
|
9958
|
+
if (len < 1e-6) return null;
|
|
9959
|
+
return {
|
|
9960
|
+
type: "draw-mesh",
|
|
9961
|
+
shape: "cylinder",
|
|
9962
|
+
position: { x: (from[0] + to[0]) / 2, y: (from[1] + to[1]) / 2, z: (from[2] + to[2]) / 2 },
|
|
9963
|
+
radius,
|
|
9964
|
+
height: len,
|
|
9965
|
+
rotation: axisRotation(from, to),
|
|
9966
|
+
pivot: "center",
|
|
9967
|
+
segments: 12,
|
|
9968
|
+
material: { color }
|
|
9969
|
+
};
|
|
9970
|
+
}
|
|
9971
|
+
function arrowBetween(from, to, color, shaftRadius = 0.08) {
|
|
9972
|
+
const len = segmentLength(from, to);
|
|
9973
|
+
if (len < 1e-6) return null;
|
|
9974
|
+
const tipLen = Math.min(shaftRadius * 8, len * 0.35);
|
|
9975
|
+
const k = (len - tipLen) / len;
|
|
9976
|
+
const delta = [to[0] - from[0], to[1] - from[1], to[2] - from[2]];
|
|
9977
|
+
const shaftEnd = [delta[0] * k, delta[1] * k, delta[2] * k];
|
|
9978
|
+
const tipStart = shaftEnd;
|
|
9979
|
+
const tipEnd = delta;
|
|
9980
|
+
const shaft = cylinderBetween([0, 0, 0], shaftEnd, shaftRadius, color);
|
|
9981
|
+
const tipLenActual = segmentLength(tipStart, tipEnd);
|
|
9982
|
+
const tip = {
|
|
9983
|
+
type: "draw-mesh",
|
|
9984
|
+
shape: "cone",
|
|
9985
|
+
position: {
|
|
9986
|
+
x: (tipStart[0] + tipEnd[0]) / 2,
|
|
9987
|
+
y: (tipStart[1] + tipEnd[1]) / 2,
|
|
9988
|
+
z: (tipStart[2] + tipEnd[2]) / 2
|
|
9989
|
+
},
|
|
9990
|
+
radius: shaftRadius * 3,
|
|
9991
|
+
height: tipLenActual,
|
|
9992
|
+
rotation: axisRotation(tipStart, tipEnd),
|
|
9993
|
+
pivot: "center",
|
|
9994
|
+
segments: 12,
|
|
9995
|
+
material: { color }
|
|
9996
|
+
};
|
|
9997
|
+
return {
|
|
9998
|
+
type: "draw-group",
|
|
9999
|
+
position: { x: from[0], y: from[1], z: from[2] },
|
|
10000
|
+
items: tipLenActual < 1e-6 ? shaft ? [shaft] : [] : shaft ? [shaft, tip] : [tip]
|
|
10001
|
+
};
|
|
10002
|
+
}
|
|
10003
|
+
function billboardLabel(text, x, y, z, opts) {
|
|
10004
|
+
return {
|
|
10005
|
+
type: "draw-text",
|
|
10006
|
+
text,
|
|
10007
|
+
position: { x, y, z },
|
|
10008
|
+
color: opts?.color ?? "#111827"
|
|
10009
|
+
};
|
|
10010
|
+
}
|
|
10011
|
+
function labelColorForBackground(backgroundColor) {
|
|
10012
|
+
const m = /^#(?:([0-9a-f]{3})|([0-9a-f]{6}))$/i.exec(backgroundColor ?? "");
|
|
10013
|
+
if (!m) return "#111827";
|
|
10014
|
+
const hex = m[1] !== void 0 ? m[1].split("").map((c) => c + c).join("") : m[2];
|
|
10015
|
+
const r = parseInt(hex.slice(0, 2), 16) / 255;
|
|
10016
|
+
const g = parseInt(hex.slice(2, 4), 16) / 255;
|
|
10017
|
+
const b = parseInt(hex.slice(4, 6), 16) / 255;
|
|
10018
|
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
10019
|
+
return luminance < 0.5 ? "#e5e7eb" : "#111827";
|
|
10020
|
+
}
|
|
10021
|
+
function get3DClickPayload(onShapeClick, idToIndex) {
|
|
10022
|
+
if (!onShapeClick) return void 0;
|
|
10023
|
+
return (id) => onShapeClick({ id, index: idToIndex.get(id) ?? -1 });
|
|
10024
|
+
}
|
|
10025
|
+
var Canvas3DHost;
|
|
10026
|
+
var init_learningScene3D = __esm({
|
|
10027
|
+
"components/learning/molecules/learningScene3D.tsx"() {
|
|
10028
|
+
"use client";
|
|
10029
|
+
init_atoms();
|
|
10030
|
+
init_Stack();
|
|
10031
|
+
init_useEventBus();
|
|
10032
|
+
Canvas3DHost = React77.lazy(
|
|
10033
|
+
() => import('@almadar/ui/components/molecules/game/three').then((m) => ({ default: m.Canvas3DHost }))
|
|
10034
|
+
);
|
|
10035
|
+
LearningScene3D.displayName = "LearningScene3D";
|
|
10036
|
+
}
|
|
10037
|
+
});
|
|
10038
|
+
var biologyLog; exports.BiologyCanvas = void 0;
|
|
9882
10039
|
var init_BiologyCanvas = __esm({
|
|
9883
10040
|
"components/learning/molecules/BiologyCanvas.tsx"() {
|
|
9884
10041
|
"use client";
|
|
9885
10042
|
init_atoms();
|
|
9886
10043
|
init_Stack();
|
|
9887
10044
|
init_LearningCanvas();
|
|
10045
|
+
init_learningScene3D();
|
|
10046
|
+
biologyLog = logger.createLogger("almadar:ui:biology-canvas");
|
|
9888
10047
|
exports.BiologyCanvas = ({
|
|
9889
10048
|
className,
|
|
9890
10049
|
width = 600,
|
|
9891
10050
|
height = 400,
|
|
9892
10051
|
title,
|
|
9893
10052
|
backgroundColor,
|
|
10053
|
+
mode = "2d",
|
|
10054
|
+
camera,
|
|
10055
|
+
lighting,
|
|
10056
|
+
post,
|
|
9894
10057
|
nodes = [],
|
|
9895
10058
|
edges = [],
|
|
9896
10059
|
shapes = [],
|
|
9897
|
-
|
|
10060
|
+
showGrid,
|
|
10061
|
+
shadows,
|
|
10062
|
+
interactive,
|
|
9898
10063
|
animate = false,
|
|
9899
10064
|
onShapeClick,
|
|
9900
10065
|
isLoading,
|
|
@@ -9955,6 +10120,75 @@ var init_BiologyCanvas = __esm({
|
|
|
9955
10120
|
out.push(...shapes);
|
|
9956
10121
|
return out;
|
|
9957
10122
|
}, [nodes, edges, shapes]);
|
|
10123
|
+
const drawables3D = React77.useMemo(() => {
|
|
10124
|
+
if (mode !== "3d") return [];
|
|
10125
|
+
if (shapes.length > 0) {
|
|
10126
|
+
biologyLog.debug("shapes ignored in 3D mode (pixel-authored 2D vocabulary)", { count: shapes.length });
|
|
10127
|
+
}
|
|
10128
|
+
const out = [];
|
|
10129
|
+
const labelColor = labelColorForBackground(backgroundColor);
|
|
10130
|
+
const nodeById = /* @__PURE__ */ new Map();
|
|
10131
|
+
for (const n of nodes) {
|
|
10132
|
+
if (n.id) nodeById.set(n.id, n);
|
|
10133
|
+
}
|
|
10134
|
+
for (const e of edges) {
|
|
10135
|
+
const a = nodeById.get(e.from);
|
|
10136
|
+
const b = nodeById.get(e.to);
|
|
10137
|
+
if (!a || !b) continue;
|
|
10138
|
+
const edgeRadius = Math.max(0.04, Math.min(a.radius ?? 0.5, b.radius ?? 0.5) * 0.12);
|
|
10139
|
+
const edge = cylinderBetween([a.x, a.y, a.z ?? 0], [b.x, b.y, b.z ?? 0], edgeRadius, e.color ?? "#9ca3af");
|
|
10140
|
+
if (edge) out.push(edge);
|
|
10141
|
+
if (e.label) {
|
|
10142
|
+
out.push(
|
|
10143
|
+
billboardLabel(
|
|
10144
|
+
e.label,
|
|
10145
|
+
(a.x + b.x) / 2,
|
|
10146
|
+
(a.y + b.y) / 2,
|
|
10147
|
+
((a.z ?? 0) + (b.z ?? 0)) / 2,
|
|
10148
|
+
{ color: labelColor }
|
|
10149
|
+
)
|
|
10150
|
+
);
|
|
10151
|
+
}
|
|
10152
|
+
}
|
|
10153
|
+
for (const n of nodes) {
|
|
10154
|
+
const radius = n.radius ?? 0.5;
|
|
10155
|
+
const nz = n.z ?? 0;
|
|
10156
|
+
out.push(meshSphere(n.id, n.x, n.y, nz, radius, n.color ?? "#16a34a", { shape: n.shape, ...n.opacity !== void 0 ? { opacity: n.opacity } : {} }));
|
|
10157
|
+
if (n.label) {
|
|
10158
|
+
out.push(billboardLabel(n.label, n.x, n.y, nz + radius, { color: labelColor }));
|
|
10159
|
+
}
|
|
10160
|
+
}
|
|
10161
|
+
return out;
|
|
10162
|
+
}, [mode, nodes, edges, shapes, backgroundColor]);
|
|
10163
|
+
const nodeIndexById = React77.useMemo(() => {
|
|
10164
|
+
const m = /* @__PURE__ */ new Map();
|
|
10165
|
+
nodes.forEach((n, i) => {
|
|
10166
|
+
if (n.id) m.set(n.id, i);
|
|
10167
|
+
});
|
|
10168
|
+
return m;
|
|
10169
|
+
}, [nodes]);
|
|
10170
|
+
if (mode === "3d") {
|
|
10171
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10172
|
+
LearningScene3D,
|
|
10173
|
+
{
|
|
10174
|
+
className,
|
|
10175
|
+
width,
|
|
10176
|
+
height,
|
|
10177
|
+
title,
|
|
10178
|
+
backgroundColor,
|
|
10179
|
+
drawables: drawables3D,
|
|
10180
|
+
camera,
|
|
10181
|
+
lighting,
|
|
10182
|
+
post,
|
|
10183
|
+
showGrid,
|
|
10184
|
+
shadows,
|
|
10185
|
+
interactive,
|
|
10186
|
+
isLoading,
|
|
10187
|
+
error,
|
|
10188
|
+
onItemClick: get3DClickPayload(onShapeClick, nodeIndexById)
|
|
10189
|
+
}
|
|
10190
|
+
);
|
|
10191
|
+
}
|
|
9958
10192
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", children: [
|
|
9959
10193
|
title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", children: title }) : null,
|
|
9960
10194
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9964,7 +10198,7 @@ var init_BiologyCanvas = __esm({
|
|
|
9964
10198
|
height,
|
|
9965
10199
|
backgroundColor,
|
|
9966
10200
|
shapes: derivedShapes,
|
|
9967
|
-
interactive,
|
|
10201
|
+
interactive: interactive ?? false,
|
|
9968
10202
|
animate,
|
|
9969
10203
|
onShapeClick,
|
|
9970
10204
|
isLoading,
|
|
@@ -17356,9 +17590,10 @@ function Canvas({
|
|
|
17356
17590
|
drawables: [...drawables ?? [], ...childDrawables],
|
|
17357
17591
|
isLoading,
|
|
17358
17592
|
cameraMode: to3DCameraMode(camera?.mode),
|
|
17359
|
-
...zoom !== void 0 ? {
|
|
17593
|
+
...zoom !== void 0 ? { zoom } : {},
|
|
17360
17594
|
...camera?.fov !== void 0 ? { fov: camera.fov } : {},
|
|
17361
17595
|
...camera?.azimuth !== void 0 ? { azimuth: camera.azimuth } : {},
|
|
17596
|
+
...camera?.elevation !== void 0 ? { elevation: camera.elevation } : {},
|
|
17362
17597
|
...camera?.target !== void 0 ? { followTarget: camera.target } : {},
|
|
17363
17598
|
unitScale,
|
|
17364
17599
|
backgroundColor,
|
|
@@ -17381,7 +17616,7 @@ function Canvas({
|
|
|
17381
17616
|
keyUpMap
|
|
17382
17617
|
};
|
|
17383
17618
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
17384
|
-
/* @__PURE__ */ jsxRuntime.jsx(React77.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17619
|
+
/* @__PURE__ */ jsxRuntime.jsx(React77.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(Canvas3DHost2, { ...props3d }) }),
|
|
17385
17620
|
React77__namespace.Children.count(children) > 0 && /* @__PURE__ */ jsxRuntime.jsx(DrawableRegistryContext.Provider, { value: registerChildDrawable, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, children }) })
|
|
17386
17621
|
] });
|
|
17387
17622
|
}
|
|
@@ -17411,13 +17646,13 @@ function Canvas({
|
|
|
17411
17646
|
}
|
|
17412
17647
|
);
|
|
17413
17648
|
}
|
|
17414
|
-
var
|
|
17649
|
+
var Canvas3DHost2, canvasLog;
|
|
17415
17650
|
var init_Canvas = __esm({
|
|
17416
17651
|
"components/game/molecules/Canvas.tsx"() {
|
|
17417
17652
|
"use client";
|
|
17418
17653
|
init_registry();
|
|
17419
17654
|
init_Canvas2D();
|
|
17420
|
-
|
|
17655
|
+
Canvas3DHost2 = React77.lazy(
|
|
17421
17656
|
() => import('@almadar/ui/components/molecules/game/three').then((m) => ({ default: m.Canvas3DHost }))
|
|
17422
17657
|
);
|
|
17423
17658
|
canvasLog = logger.createLogger("almadar:ui:game-canvas");
|
|
@@ -19144,24 +19379,41 @@ var init_ChatBar = __esm({
|
|
|
19144
19379
|
ChatBar.displayName = "ChatBar";
|
|
19145
19380
|
}
|
|
19146
19381
|
});
|
|
19147
|
-
|
|
19382
|
+
function bondPerpendicular(a, b) {
|
|
19383
|
+
const dx = b[0] - a[0];
|
|
19384
|
+
const dy = b[1] - a[1];
|
|
19385
|
+
const px = dy;
|
|
19386
|
+
const py = -dx;
|
|
19387
|
+
const len = Math.sqrt(px * px + py * py);
|
|
19388
|
+
if (len < 1e-6) return [1, 0, 0];
|
|
19389
|
+
return [px / len, py / len, 0];
|
|
19390
|
+
}
|
|
19391
|
+
var chemistryLog; exports.ChemistryCanvas = void 0;
|
|
19148
19392
|
var init_ChemistryCanvas = __esm({
|
|
19149
19393
|
"components/learning/molecules/ChemistryCanvas.tsx"() {
|
|
19150
19394
|
"use client";
|
|
19151
19395
|
init_atoms();
|
|
19152
19396
|
init_Stack();
|
|
19153
19397
|
init_LearningCanvas();
|
|
19398
|
+
init_learningScene3D();
|
|
19399
|
+
chemistryLog = logger.createLogger("almadar:ui:chemistry-canvas");
|
|
19154
19400
|
exports.ChemistryCanvas = ({
|
|
19155
19401
|
className,
|
|
19156
19402
|
width = 600,
|
|
19157
19403
|
height = 400,
|
|
19158
19404
|
title,
|
|
19159
19405
|
backgroundColor,
|
|
19406
|
+
mode = "2d",
|
|
19407
|
+
camera,
|
|
19408
|
+
lighting,
|
|
19409
|
+
post,
|
|
19160
19410
|
atoms = [],
|
|
19161
19411
|
bonds = [],
|
|
19162
19412
|
arrows = [],
|
|
19163
19413
|
shapes = [],
|
|
19164
|
-
|
|
19414
|
+
showGrid,
|
|
19415
|
+
shadows,
|
|
19416
|
+
interactive,
|
|
19165
19417
|
animate = false,
|
|
19166
19418
|
onShapeClick,
|
|
19167
19419
|
isLoading,
|
|
@@ -19240,6 +19492,88 @@ var init_ChemistryCanvas = __esm({
|
|
|
19240
19492
|
out.push(...shapes);
|
|
19241
19493
|
return out;
|
|
19242
19494
|
}, [atoms, bonds, arrows, shapes]);
|
|
19495
|
+
const drawables3D = React77.useMemo(() => {
|
|
19496
|
+
if (mode !== "3d") return [];
|
|
19497
|
+
if (shapes.length > 0) {
|
|
19498
|
+
chemistryLog.debug("shapes ignored in 3D mode (pixel-authored 2D vocabulary)", { count: shapes.length });
|
|
19499
|
+
}
|
|
19500
|
+
const out = [];
|
|
19501
|
+
const labelColor = labelColorForBackground(backgroundColor);
|
|
19502
|
+
const atomById = /* @__PURE__ */ new Map();
|
|
19503
|
+
for (const a of atoms) {
|
|
19504
|
+
if (a.id) atomById.set(a.id, a);
|
|
19505
|
+
}
|
|
19506
|
+
for (const b of bonds) {
|
|
19507
|
+
const a = atomById.get(b.from);
|
|
19508
|
+
const c = atomById.get(b.to);
|
|
19509
|
+
if (!a || !c) continue;
|
|
19510
|
+
const color = b.color ?? "#6b7280";
|
|
19511
|
+
const from = [a.x, a.y, a.z ?? 0];
|
|
19512
|
+
const to = [c.x, c.y, c.z ?? 0];
|
|
19513
|
+
const perp = bondPerpendicular(from, to);
|
|
19514
|
+
const bondRadius = Math.max(0.06, Math.min(a.radius ?? 0.45, c.radius ?? 0.45) * 0.22);
|
|
19515
|
+
const step = bondRadius * 2.2;
|
|
19516
|
+
const offsets = b.type === "double" ? [-step, step] : b.type === "triple" ? [-step, 0, step] : [0];
|
|
19517
|
+
for (const off of offsets) {
|
|
19518
|
+
const bond = cylinderBetween(
|
|
19519
|
+
[from[0] + perp[0] * off, from[1] + perp[1] * off, from[2] + perp[2] * off],
|
|
19520
|
+
[to[0] + perp[0] * off, to[1] + perp[1] * off, to[2] + perp[2] * off],
|
|
19521
|
+
bondRadius,
|
|
19522
|
+
color
|
|
19523
|
+
);
|
|
19524
|
+
if (bond) out.push(bond);
|
|
19525
|
+
}
|
|
19526
|
+
}
|
|
19527
|
+
for (const a of arrows) {
|
|
19528
|
+
const angle = (a.angle ?? 0) * (Math.PI / 180);
|
|
19529
|
+
const len = a.length ?? 60;
|
|
19530
|
+
const x2 = a.x + Math.cos(angle) * len;
|
|
19531
|
+
const y2 = a.y + Math.sin(angle) * len;
|
|
19532
|
+
const arrow = arrowBetween([a.x, a.y, 0], [x2, y2, 0], a.color ?? "#dc2626");
|
|
19533
|
+
if (arrow) out.push(arrow);
|
|
19534
|
+
if (a.label) {
|
|
19535
|
+
out.push(billboardLabel(a.label, (a.x + x2) / 2, (a.y + y2) / 2, 0, { color: labelColor }));
|
|
19536
|
+
}
|
|
19537
|
+
}
|
|
19538
|
+
for (const a of atoms) {
|
|
19539
|
+
const radius = a.radius ?? 0.45;
|
|
19540
|
+
const az = a.z ?? 0;
|
|
19541
|
+
out.push(meshSphere(a.id, a.x, a.y, az, radius, a.color ?? "#2563eb"));
|
|
19542
|
+
if (a.element) {
|
|
19543
|
+
out.push(billboardLabel(a.element, a.x, a.y, az + radius, { color: labelColor }));
|
|
19544
|
+
}
|
|
19545
|
+
}
|
|
19546
|
+
return out;
|
|
19547
|
+
}, [mode, atoms, bonds, arrows, shapes, backgroundColor]);
|
|
19548
|
+
const atomIndexById = React77.useMemo(() => {
|
|
19549
|
+
const m = /* @__PURE__ */ new Map();
|
|
19550
|
+
atoms.forEach((a, i) => {
|
|
19551
|
+
if (a.id) m.set(a.id, i);
|
|
19552
|
+
});
|
|
19553
|
+
return m;
|
|
19554
|
+
}, [atoms]);
|
|
19555
|
+
if (mode === "3d") {
|
|
19556
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19557
|
+
LearningScene3D,
|
|
19558
|
+
{
|
|
19559
|
+
className,
|
|
19560
|
+
width,
|
|
19561
|
+
height,
|
|
19562
|
+
title,
|
|
19563
|
+
backgroundColor,
|
|
19564
|
+
drawables: drawables3D,
|
|
19565
|
+
camera,
|
|
19566
|
+
lighting,
|
|
19567
|
+
post,
|
|
19568
|
+
showGrid,
|
|
19569
|
+
shadows,
|
|
19570
|
+
interactive,
|
|
19571
|
+
isLoading,
|
|
19572
|
+
error,
|
|
19573
|
+
onItemClick: get3DClickPayload(onShapeClick, atomIndexById)
|
|
19574
|
+
}
|
|
19575
|
+
);
|
|
19576
|
+
}
|
|
19243
19577
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", children: [
|
|
19244
19578
|
title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", children: title }) : null,
|
|
19245
19579
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -19249,7 +19583,7 @@ var init_ChemistryCanvas = __esm({
|
|
|
19249
19583
|
height,
|
|
19250
19584
|
backgroundColor,
|
|
19251
19585
|
shapes: derivedShapes,
|
|
19252
|
-
interactive,
|
|
19586
|
+
interactive: interactive ?? false,
|
|
19253
19587
|
animate,
|
|
19254
19588
|
onShapeClick,
|
|
19255
19589
|
isLoading,
|
|
@@ -29277,19 +29611,25 @@ var init_MathCanvas = __esm({
|
|
|
29277
29611
|
};
|
|
29278
29612
|
}
|
|
29279
29613
|
});
|
|
29280
|
-
exports.PhysicsCanvas = void 0;
|
|
29614
|
+
var physicsLog2; exports.PhysicsCanvas = void 0;
|
|
29281
29615
|
var init_PhysicsCanvas = __esm({
|
|
29282
29616
|
"components/learning/molecules/PhysicsCanvas.tsx"() {
|
|
29283
29617
|
"use client";
|
|
29284
29618
|
init_atoms();
|
|
29285
29619
|
init_Stack();
|
|
29286
29620
|
init_LearningCanvas();
|
|
29621
|
+
init_learningScene3D();
|
|
29622
|
+
physicsLog2 = logger.createLogger("almadar:ui:physics-canvas");
|
|
29287
29623
|
exports.PhysicsCanvas = ({
|
|
29288
29624
|
className,
|
|
29289
29625
|
width = 600,
|
|
29290
29626
|
height = 400,
|
|
29291
29627
|
title,
|
|
29292
29628
|
backgroundColor,
|
|
29629
|
+
mode = "2d",
|
|
29630
|
+
camera,
|
|
29631
|
+
lighting,
|
|
29632
|
+
post,
|
|
29293
29633
|
bodies = [],
|
|
29294
29634
|
constraints = [],
|
|
29295
29635
|
showVelocity = true,
|
|
@@ -29297,7 +29637,9 @@ var init_PhysicsCanvas = __esm({
|
|
|
29297
29637
|
velocityScale = 20,
|
|
29298
29638
|
forceScale = 20,
|
|
29299
29639
|
shapes = [],
|
|
29300
|
-
|
|
29640
|
+
showGrid,
|
|
29641
|
+
shadows,
|
|
29642
|
+
interactive,
|
|
29301
29643
|
animate = false,
|
|
29302
29644
|
onShapeClick,
|
|
29303
29645
|
isLoading,
|
|
@@ -29369,6 +29711,89 @@ var init_PhysicsCanvas = __esm({
|
|
|
29369
29711
|
out.push(...shapes);
|
|
29370
29712
|
return out;
|
|
29371
29713
|
}, [bodies, constraints, showVelocity, showForces, velocityScale, forceScale, shapes]);
|
|
29714
|
+
const drawables3D = React77.useMemo(() => {
|
|
29715
|
+
if (mode !== "3d") return [];
|
|
29716
|
+
if (shapes.length > 0) {
|
|
29717
|
+
physicsLog2.debug("shapes ignored in 3D mode (pixel-authored 2D vocabulary)", { count: shapes.length });
|
|
29718
|
+
}
|
|
29719
|
+
const out = [];
|
|
29720
|
+
const labelColor = labelColorForBackground(backgroundColor);
|
|
29721
|
+
const bodyById = /* @__PURE__ */ new Map();
|
|
29722
|
+
for (const b of bodies) {
|
|
29723
|
+
if (b.id) bodyById.set(b.id, b);
|
|
29724
|
+
}
|
|
29725
|
+
for (const c of constraints) {
|
|
29726
|
+
const a = bodyById.get(c.from);
|
|
29727
|
+
const b = bodyById.get(c.to);
|
|
29728
|
+
if (!a || !b) continue;
|
|
29729
|
+
const rodRadius = Math.max(0.05, Math.min(a.radius ?? 0.5, b.radius ?? 0.5) * 0.15);
|
|
29730
|
+
const rod = cylinderBetween([a.x, a.y, a.z ?? 0], [b.x, b.y, b.z ?? 0], rodRadius, c.color ?? "#9ca3af");
|
|
29731
|
+
if (rod) out.push(rod);
|
|
29732
|
+
}
|
|
29733
|
+
for (const b of bodies) {
|
|
29734
|
+
const radius = b.radius ?? 0.5;
|
|
29735
|
+
const bz = b.z ?? 0;
|
|
29736
|
+
out.push(meshSphere(b.id, b.x, b.y, bz, radius, b.color ?? "#2563eb"));
|
|
29737
|
+
if (b.label) {
|
|
29738
|
+
out.push(billboardLabel(b.label, b.x, b.y, bz + radius, { color: labelColor }));
|
|
29739
|
+
}
|
|
29740
|
+
const vx = b.vx ?? 0;
|
|
29741
|
+
const vy = b.vy ?? 0;
|
|
29742
|
+
const vz = b.vz ?? 0;
|
|
29743
|
+
const arrowRadius = Math.max(0.05, radius * 0.15);
|
|
29744
|
+
if (showVelocity && (vx !== 0 || vy !== 0 || vz !== 0)) {
|
|
29745
|
+
const arrow = arrowBetween(
|
|
29746
|
+
[b.x, b.y, bz],
|
|
29747
|
+
[b.x + vx * velocityScale, b.y + vy * velocityScale, bz + vz * velocityScale],
|
|
29748
|
+
"#16a34a",
|
|
29749
|
+
arrowRadius
|
|
29750
|
+
);
|
|
29751
|
+
if (arrow) out.push(arrow);
|
|
29752
|
+
}
|
|
29753
|
+
const fx = b.fx ?? 0;
|
|
29754
|
+
const fy = b.fy ?? 0;
|
|
29755
|
+
const fz = b.fz ?? 0;
|
|
29756
|
+
if (showForces && (fx !== 0 || fy !== 0 || fz !== 0)) {
|
|
29757
|
+
const arrow = arrowBetween(
|
|
29758
|
+
[b.x, b.y, bz],
|
|
29759
|
+
[b.x + fx * forceScale, b.y + fy * forceScale, bz + fz * forceScale],
|
|
29760
|
+
"#dc2626",
|
|
29761
|
+
arrowRadius
|
|
29762
|
+
);
|
|
29763
|
+
if (arrow) out.push(arrow);
|
|
29764
|
+
}
|
|
29765
|
+
}
|
|
29766
|
+
return out;
|
|
29767
|
+
}, [mode, bodies, constraints, showVelocity, showForces, velocityScale, forceScale, shapes, backgroundColor]);
|
|
29768
|
+
const bodyIndexById = React77.useMemo(() => {
|
|
29769
|
+
const m = /* @__PURE__ */ new Map();
|
|
29770
|
+
bodies.forEach((b, i) => {
|
|
29771
|
+
if (b.id) m.set(b.id, i);
|
|
29772
|
+
});
|
|
29773
|
+
return m;
|
|
29774
|
+
}, [bodies]);
|
|
29775
|
+
if (mode === "3d") {
|
|
29776
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
29777
|
+
LearningScene3D,
|
|
29778
|
+
{
|
|
29779
|
+
className,
|
|
29780
|
+
width,
|
|
29781
|
+
height,
|
|
29782
|
+
title,
|
|
29783
|
+
backgroundColor,
|
|
29784
|
+
drawables: drawables3D,
|
|
29785
|
+
camera,
|
|
29786
|
+
lighting,
|
|
29787
|
+
post,
|
|
29788
|
+
showGrid,
|
|
29789
|
+
shadows,
|
|
29790
|
+
interactive,
|
|
29791
|
+
isLoading,
|
|
29792
|
+
error,
|
|
29793
|
+
onItemClick: get3DClickPayload(onShapeClick, bodyIndexById)
|
|
29794
|
+
}
|
|
29795
|
+
);
|
|
29796
|
+
}
|
|
29372
29797
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className, children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", children: [
|
|
29373
29798
|
title ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", children: title }) : null,
|
|
29374
29799
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -29378,7 +29803,7 @@ var init_PhysicsCanvas = __esm({
|
|
|
29378
29803
|
height,
|
|
29379
29804
|
backgroundColor,
|
|
29380
29805
|
shapes: derivedShapes,
|
|
29381
|
-
interactive,
|
|
29806
|
+
interactive: interactive ?? false,
|
|
29382
29807
|
animate,
|
|
29383
29808
|
onShapeClick,
|
|
29384
29809
|
isLoading,
|
|
@@ -29996,12 +30421,12 @@ var init_MapView = __esm({
|
|
|
29996
30421
|
shadowSize: [41, 41]
|
|
29997
30422
|
});
|
|
29998
30423
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29999
|
-
const { useEffect: useEffect66, useRef:
|
|
30424
|
+
const { useEffect: useEffect66, useRef: useRef65, useCallback: useCallback107, useState: useState104 } = React77__namespace.default;
|
|
30000
30425
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
30001
30426
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
30002
30427
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
30003
30428
|
const map = useMap();
|
|
30004
|
-
const prevRef =
|
|
30429
|
+
const prevRef = useRef65({ centerLat, centerLng, zoom });
|
|
30005
30430
|
useEffect66(() => {
|
|
30006
30431
|
const prev = prevRef.current;
|
|
30007
30432
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -39793,6 +40218,7 @@ var init_molecules2 = __esm({
|
|
|
39793
40218
|
init_BiologyCanvas();
|
|
39794
40219
|
init_ChemistryCanvas();
|
|
39795
40220
|
init_AlgorithmCanvas();
|
|
40221
|
+
init_learningScene3D();
|
|
39796
40222
|
init_GraphView();
|
|
39797
40223
|
init_MapView();
|
|
39798
40224
|
init_NumberStepper();
|
|
@@ -41046,7 +41472,7 @@ function getEnumOptions(field) {
|
|
|
41046
41472
|
}));
|
|
41047
41473
|
}
|
|
41048
41474
|
const validation = field.validation;
|
|
41049
|
-
if (validation?.enum &&
|
|
41475
|
+
if (validation?.enum && validation.enum.length > 0) {
|
|
41050
41476
|
return validation.enum.map((v) => ({
|
|
41051
41477
|
value: v,
|
|
41052
41478
|
label: v.charAt(0).toUpperCase() + v.slice(1).replace(/_/g, " ")
|
|
@@ -50501,6 +50927,7 @@ exports.GameIcon = GameIcon;
|
|
|
50501
50927
|
exports.GameMenu = GameMenu;
|
|
50502
50928
|
exports.HealthBar = HealthBar;
|
|
50503
50929
|
exports.I18nProvider = I18nProvider;
|
|
50930
|
+
exports.LearningScene3D = LearningScene3D;
|
|
50504
50931
|
exports.MapView = MapView;
|
|
50505
50932
|
exports.MasterDetail = MasterDetail;
|
|
50506
50933
|
exports.NotifyListener = NotifyListener;
|
|
@@ -50526,6 +50953,8 @@ exports.TraitStateViewer = TraitStateViewer;
|
|
|
50526
50953
|
exports.TransitionArrow = TransitionArrow;
|
|
50527
50954
|
exports.UISlotComponent = UISlotComponent;
|
|
50528
50955
|
exports.UISlotRenderer = UISlotRenderer;
|
|
50956
|
+
exports.arrowBetween = arrowBetween;
|
|
50957
|
+
exports.billboardLabel = billboardLabel;
|
|
50529
50958
|
exports.boardEntity = boardEntity;
|
|
50530
50959
|
exports.bool = bool;
|
|
50531
50960
|
exports.calculateAttackTargets = calculateAttackTargets;
|
|
@@ -50535,6 +50964,8 @@ exports.createInitialGameState = createInitialGameState;
|
|
|
50535
50964
|
exports.createSharedEntityStore = createSharedEntityStore;
|
|
50536
50965
|
exports.createTranslate = createTranslate;
|
|
50537
50966
|
exports.createUnitAnimationState = createUnitAnimationState;
|
|
50967
|
+
exports.cylinderBetween = cylinderBetween;
|
|
50968
|
+
exports.get3DClickPayload = get3DClickPayload;
|
|
50538
50969
|
exports.getCurrentFrame = getCurrentFrame;
|
|
50539
50970
|
exports.getTileDimensions = getTileDimensions;
|
|
50540
50971
|
exports.inferDirection = inferDirection;
|
|
@@ -50542,6 +50973,7 @@ exports.isoToScreen = isoToScreen;
|
|
|
50542
50973
|
exports.makeAsset = makeAsset;
|
|
50543
50974
|
exports.makeAssetMap = makeAssetMap;
|
|
50544
50975
|
exports.mapBookData = mapBookData;
|
|
50976
|
+
exports.meshSphere = meshSphere;
|
|
50545
50977
|
exports.num = num;
|
|
50546
50978
|
exports.objAvailableActions = objAvailableActions;
|
|
50547
50979
|
exports.objAvailableEvents = objAvailableEvents;
|