@almadar/ui 2.16.0 → 2.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +91 -1
- package/dist/avl/index.d.cts +7 -5
- package/dist/avl/index.js +91 -1
- package/dist/components/index.cjs +131 -2411
- package/dist/components/index.css +0 -508
- package/dist/components/index.js +132 -2411
- package/dist/components/molecules/avl/AvlSlotMap.d.ts +5 -4
- package/dist/components/molecules/avl/avl-layout.d.ts +2 -1
- package/dist/components/organisms/component-registry.generated.d.ts +1 -1
- package/dist/components/organisms/game/three/index.cjs +1067 -0
- package/dist/components/organisms/game/three/index.css +192 -0
- package/dist/components/organisms/game/three/index.d.ts +4 -0
- package/dist/components/organisms/game/three/index.js +1068 -5
- package/dist/illustrations/index.cjs +91 -1
- package/dist/illustrations/index.d.cts +5 -4
- package/dist/illustrations/index.js +91 -1
- package/dist/providers/index.cjs +152 -1521
- package/dist/providers/index.css +0 -508
- package/dist/providers/index.js +62 -1430
- package/dist/runtime/index.cjs +145 -1514
- package/dist/runtime/index.css +0 -508
- package/dist/runtime/index.js +63 -1431
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React110 from 'react';
|
|
2
|
+
import React110__default, { createContext, useCallback, useState, useRef, useLayoutEffect, useEffect, lazy, useContext, useMemo } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import '@tanstack/react-query';
|
|
5
5
|
import 'react-dom';
|
|
@@ -20,12 +20,6 @@ import remarkMath from 'remark-math';
|
|
|
20
20
|
import rehypeKatex from 'rehype-katex';
|
|
21
21
|
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism';
|
|
22
22
|
import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus';
|
|
23
|
-
import { useThree, useFrame, Canvas } from '@react-three/fiber';
|
|
24
|
-
import { OrbitControls, Grid } from '@react-three/drei';
|
|
25
|
-
import * as THREE from 'three';
|
|
26
|
-
import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
27
|
-
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
28
|
-
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
|
|
29
23
|
import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1 } from '@almadar/core';
|
|
30
24
|
import { StateMachineManager, createContextFromBindings, interpolateValue, EffectExecutor } from '@almadar/runtime';
|
|
31
25
|
|
|
@@ -103,15 +97,6 @@ function useEventBus() {
|
|
|
103
97
|
const context = useContext(EventBusContext);
|
|
104
98
|
return context ?? getGlobalEventBus() ?? fallbackEventBus;
|
|
105
99
|
}
|
|
106
|
-
function useEmitEvent() {
|
|
107
|
-
const eventBus = useEventBus();
|
|
108
|
-
return useCallback(
|
|
109
|
-
(type, payload) => {
|
|
110
|
-
eventBus.emit(type, payload);
|
|
111
|
-
},
|
|
112
|
-
[eventBus]
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
100
|
createContext(null);
|
|
116
101
|
createContext(null);
|
|
117
102
|
|
|
@@ -384,7 +369,7 @@ var positionStyles = {
|
|
|
384
369
|
fixed: "fixed",
|
|
385
370
|
sticky: "sticky"
|
|
386
371
|
};
|
|
387
|
-
var Box =
|
|
372
|
+
var Box = React110__default.forwardRef(
|
|
388
373
|
({
|
|
389
374
|
padding,
|
|
390
375
|
paddingX,
|
|
@@ -403,7 +388,7 @@ var Box = React113__default.forwardRef(
|
|
|
403
388
|
position,
|
|
404
389
|
className,
|
|
405
390
|
children,
|
|
406
|
-
as:
|
|
391
|
+
as: Component = "div",
|
|
407
392
|
action,
|
|
408
393
|
actionPayload,
|
|
409
394
|
hoverEvent,
|
|
@@ -433,7 +418,7 @@ var Box = React113__default.forwardRef(
|
|
|
433
418
|
onMouseLeave?.(e);
|
|
434
419
|
}, [hoverEvent, eventBus, onMouseLeave]);
|
|
435
420
|
const isClickable = action || onClick;
|
|
436
|
-
const Comp =
|
|
421
|
+
const Comp = Component;
|
|
437
422
|
return /* @__PURE__ */ jsx(
|
|
438
423
|
Comp,
|
|
439
424
|
{
|
|
@@ -563,8 +548,8 @@ var Typography = ({
|
|
|
563
548
|
children
|
|
564
549
|
}) => {
|
|
565
550
|
const variant = variantProp ?? (level ? `h${level}` : "body1");
|
|
566
|
-
const
|
|
567
|
-
const Comp =
|
|
551
|
+
const Component = as || defaultElements[variant];
|
|
552
|
+
const Comp = Component;
|
|
568
553
|
return /* @__PURE__ */ jsx(
|
|
569
554
|
Comp,
|
|
570
555
|
{
|
|
@@ -654,7 +639,7 @@ function resolveIconProp(value, sizeClass) {
|
|
|
654
639
|
const IconComp = value;
|
|
655
640
|
return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
|
|
656
641
|
}
|
|
657
|
-
if (
|
|
642
|
+
if (React110__default.isValidElement(value)) {
|
|
658
643
|
return value;
|
|
659
644
|
}
|
|
660
645
|
if (typeof value === "object" && value !== null && "render" in value) {
|
|
@@ -663,7 +648,7 @@ function resolveIconProp(value, sizeClass) {
|
|
|
663
648
|
}
|
|
664
649
|
return value;
|
|
665
650
|
}
|
|
666
|
-
var Button =
|
|
651
|
+
var Button = React110__default.forwardRef(
|
|
667
652
|
({
|
|
668
653
|
className,
|
|
669
654
|
variant = "primary",
|
|
@@ -758,7 +743,7 @@ var sizeStyles3 = {
|
|
|
758
743
|
md: "px-2.5 py-1 text-sm",
|
|
759
744
|
lg: "px-3 py-1.5 text-base"
|
|
760
745
|
};
|
|
761
|
-
var Badge =
|
|
746
|
+
var Badge = React110__default.forwardRef(
|
|
762
747
|
({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
|
|
763
748
|
const iconSizes2 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
|
|
764
749
|
const resolvedIcon = typeof icon === "string" ? (() => {
|
|
@@ -785,7 +770,7 @@ var Badge = React113__default.forwardRef(
|
|
|
785
770
|
}
|
|
786
771
|
);
|
|
787
772
|
Badge.displayName = "Badge";
|
|
788
|
-
var Input =
|
|
773
|
+
var Input = React110__default.forwardRef(
|
|
789
774
|
({
|
|
790
775
|
className,
|
|
791
776
|
inputType,
|
|
@@ -897,7 +882,7 @@ var Input = React113__default.forwardRef(
|
|
|
897
882
|
}
|
|
898
883
|
);
|
|
899
884
|
Input.displayName = "Input";
|
|
900
|
-
var Label =
|
|
885
|
+
var Label = React110__default.forwardRef(
|
|
901
886
|
({ className, required, children, ...props }, ref) => {
|
|
902
887
|
return /* @__PURE__ */ jsxs(
|
|
903
888
|
"label",
|
|
@@ -917,7 +902,7 @@ var Label = React113__default.forwardRef(
|
|
|
917
902
|
}
|
|
918
903
|
);
|
|
919
904
|
Label.displayName = "Label";
|
|
920
|
-
var Textarea =
|
|
905
|
+
var Textarea = React110__default.forwardRef(
|
|
921
906
|
({ className, error, ...props }, ref) => {
|
|
922
907
|
return /* @__PURE__ */ jsx(
|
|
923
908
|
"textarea",
|
|
@@ -940,7 +925,7 @@ var Textarea = React113__default.forwardRef(
|
|
|
940
925
|
}
|
|
941
926
|
);
|
|
942
927
|
Textarea.displayName = "Textarea";
|
|
943
|
-
var Select =
|
|
928
|
+
var Select = React110__default.forwardRef(
|
|
944
929
|
({ className, options, placeholder, error, ...props }, ref) => {
|
|
945
930
|
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
946
931
|
/* @__PURE__ */ jsxs(
|
|
@@ -976,7 +961,7 @@ var Select = React113__default.forwardRef(
|
|
|
976
961
|
}
|
|
977
962
|
);
|
|
978
963
|
Select.displayName = "Select";
|
|
979
|
-
var Checkbox =
|
|
964
|
+
var Checkbox = React110__default.forwardRef(
|
|
980
965
|
({ className, label, id, ...props }, ref) => {
|
|
981
966
|
const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
982
967
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
@@ -1050,7 +1035,7 @@ var shadowStyles2 = {
|
|
|
1050
1035
|
md: "shadow-[var(--shadow-main)]",
|
|
1051
1036
|
lg: "shadow-[var(--shadow-lg)]"
|
|
1052
1037
|
};
|
|
1053
|
-
var Card =
|
|
1038
|
+
var Card = React110__default.forwardRef(
|
|
1054
1039
|
({
|
|
1055
1040
|
className,
|
|
1056
1041
|
variant = "bordered",
|
|
@@ -1086,9 +1071,9 @@ var Card = React113__default.forwardRef(
|
|
|
1086
1071
|
}
|
|
1087
1072
|
);
|
|
1088
1073
|
Card.displayName = "Card";
|
|
1089
|
-
var CardHeader =
|
|
1074
|
+
var CardHeader = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
|
|
1090
1075
|
CardHeader.displayName = "CardHeader";
|
|
1091
|
-
var CardTitle =
|
|
1076
|
+
var CardTitle = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1092
1077
|
"h3",
|
|
1093
1078
|
{
|
|
1094
1079
|
ref,
|
|
@@ -1101,11 +1086,11 @@ var CardTitle = React113__default.forwardRef(({ className, ...props }, ref) => /
|
|
|
1101
1086
|
}
|
|
1102
1087
|
));
|
|
1103
1088
|
CardTitle.displayName = "CardTitle";
|
|
1104
|
-
var CardContent =
|
|
1089
|
+
var CardContent = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
|
|
1105
1090
|
CardContent.displayName = "CardContent";
|
|
1106
1091
|
var CardBody = CardContent;
|
|
1107
1092
|
CardBody.displayName = "CardBody";
|
|
1108
|
-
var CardFooter =
|
|
1093
|
+
var CardFooter = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1109
1094
|
"div",
|
|
1110
1095
|
{
|
|
1111
1096
|
ref,
|
|
@@ -1120,7 +1105,7 @@ var sizeStyles4 = {
|
|
|
1120
1105
|
md: "h-6 w-6",
|
|
1121
1106
|
lg: "h-8 w-8"
|
|
1122
1107
|
};
|
|
1123
|
-
var Spinner =
|
|
1108
|
+
var Spinner = React110__default.forwardRef(
|
|
1124
1109
|
({ className, size = "md", ...props }, ref) => {
|
|
1125
1110
|
return /* @__PURE__ */ jsx(
|
|
1126
1111
|
"div",
|
|
@@ -1134,7 +1119,7 @@ var Spinner = React113__default.forwardRef(
|
|
|
1134
1119
|
}
|
|
1135
1120
|
);
|
|
1136
1121
|
Spinner.displayName = "Spinner";
|
|
1137
|
-
var Radio =
|
|
1122
|
+
var Radio = React110__default.forwardRef(
|
|
1138
1123
|
({
|
|
1139
1124
|
label,
|
|
1140
1125
|
helperText,
|
|
@@ -1238,7 +1223,7 @@ var Radio = React113__default.forwardRef(
|
|
|
1238
1223
|
}
|
|
1239
1224
|
);
|
|
1240
1225
|
Radio.displayName = "Radio";
|
|
1241
|
-
var Switch =
|
|
1226
|
+
var Switch = React110.forwardRef(
|
|
1242
1227
|
({
|
|
1243
1228
|
checked,
|
|
1244
1229
|
defaultChecked = false,
|
|
@@ -1249,10 +1234,10 @@ var Switch = React113.forwardRef(
|
|
|
1249
1234
|
name,
|
|
1250
1235
|
className
|
|
1251
1236
|
}, ref) => {
|
|
1252
|
-
const [isChecked, setIsChecked] =
|
|
1237
|
+
const [isChecked, setIsChecked] = React110.useState(
|
|
1253
1238
|
checked !== void 0 ? checked : defaultChecked
|
|
1254
1239
|
);
|
|
1255
|
-
|
|
1240
|
+
React110.useEffect(() => {
|
|
1256
1241
|
if (checked !== void 0) {
|
|
1257
1242
|
setIsChecked(checked);
|
|
1258
1243
|
}
|
|
@@ -1346,7 +1331,7 @@ var Stack = ({
|
|
|
1346
1331
|
className,
|
|
1347
1332
|
style,
|
|
1348
1333
|
children,
|
|
1349
|
-
as:
|
|
1334
|
+
as: Component = "div",
|
|
1350
1335
|
onClick,
|
|
1351
1336
|
onKeyDown,
|
|
1352
1337
|
role,
|
|
@@ -1364,7 +1349,7 @@ var Stack = ({
|
|
|
1364
1349
|
};
|
|
1365
1350
|
const isHorizontal = direction === "horizontal";
|
|
1366
1351
|
const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
|
|
1367
|
-
const Comp =
|
|
1352
|
+
const Comp = Component;
|
|
1368
1353
|
return /* @__PURE__ */ jsx(
|
|
1369
1354
|
Comp,
|
|
1370
1355
|
{
|
|
@@ -1410,7 +1395,7 @@ var sizeStyles5 = {
|
|
|
1410
1395
|
md: "w-2.5 h-2.5",
|
|
1411
1396
|
lg: "w-3 h-3"
|
|
1412
1397
|
};
|
|
1413
|
-
var StatusDot =
|
|
1398
|
+
var StatusDot = React110__default.forwardRef(
|
|
1414
1399
|
({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
|
|
1415
1400
|
return /* @__PURE__ */ jsx(
|
|
1416
1401
|
"span",
|
|
@@ -1457,7 +1442,7 @@ var iconMap2 = {
|
|
|
1457
1442
|
down: TrendingDown,
|
|
1458
1443
|
flat: ArrowRight
|
|
1459
1444
|
};
|
|
1460
|
-
var TrendIndicator =
|
|
1445
|
+
var TrendIndicator = React110__default.forwardRef(
|
|
1461
1446
|
({
|
|
1462
1447
|
className,
|
|
1463
1448
|
value,
|
|
@@ -1516,7 +1501,7 @@ var thumbSizes = {
|
|
|
1516
1501
|
md: "w-4 h-4",
|
|
1517
1502
|
lg: "w-5 h-5"
|
|
1518
1503
|
};
|
|
1519
|
-
var RangeSlider =
|
|
1504
|
+
var RangeSlider = React110__default.forwardRef(
|
|
1520
1505
|
({
|
|
1521
1506
|
className,
|
|
1522
1507
|
min = 0,
|
|
@@ -1719,7 +1704,7 @@ var paddingClasses = {
|
|
|
1719
1704
|
md: "py-16",
|
|
1720
1705
|
lg: "py-24"
|
|
1721
1706
|
};
|
|
1722
|
-
var ContentSection =
|
|
1707
|
+
var ContentSection = React110__default.forwardRef(
|
|
1723
1708
|
({ children, background = "default", padding = "lg", id, className }, ref) => {
|
|
1724
1709
|
return /* @__PURE__ */ jsx(
|
|
1725
1710
|
Box,
|
|
@@ -1772,7 +1757,7 @@ var ErrorState = ({
|
|
|
1772
1757
|
);
|
|
1773
1758
|
};
|
|
1774
1759
|
ErrorState.displayName = "ErrorState";
|
|
1775
|
-
var ErrorBoundary = class extends
|
|
1760
|
+
var ErrorBoundary = class extends React110__default.Component {
|
|
1776
1761
|
constructor(props) {
|
|
1777
1762
|
super(props);
|
|
1778
1763
|
__publicField(this, "reset", () => {
|
|
@@ -1947,7 +1932,7 @@ function waitForTransition(event, timeoutMs = 1e4) {
|
|
|
1947
1932
|
});
|
|
1948
1933
|
}
|
|
1949
1934
|
exposeOnWindow();
|
|
1950
|
-
var MarkdownContent =
|
|
1935
|
+
var MarkdownContent = React110__default.memo(
|
|
1951
1936
|
({ content, direction, className }) => {
|
|
1952
1937
|
const { t: _t } = useTranslate();
|
|
1953
1938
|
return /* @__PURE__ */ jsx(
|
|
@@ -2048,7 +2033,7 @@ var MarkdownContent = React113__default.memo(
|
|
|
2048
2033
|
(prev, next) => prev.content === next.content && prev.className === next.className && prev.direction === next.direction
|
|
2049
2034
|
);
|
|
2050
2035
|
MarkdownContent.displayName = "MarkdownContent";
|
|
2051
|
-
var CodeBlock =
|
|
2036
|
+
var CodeBlock = React110__default.memo(
|
|
2052
2037
|
({
|
|
2053
2038
|
code,
|
|
2054
2039
|
language = "text",
|
|
@@ -2155,1394 +2140,12 @@ var CodeBlock = React113__default.memo(
|
|
|
2155
2140
|
(prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight
|
|
2156
2141
|
);
|
|
2157
2142
|
CodeBlock.displayName = "CodeBlock";
|
|
2158
|
-
var Camera3D = forwardRef(
|
|
2159
|
-
({
|
|
2160
|
-
mode = "isometric",
|
|
2161
|
-
position = [10, 10, 10],
|
|
2162
|
-
target = [0, 0, 0],
|
|
2163
|
-
zoom = 1,
|
|
2164
|
-
fov = 45,
|
|
2165
|
-
enableOrbit = true,
|
|
2166
|
-
minDistance = 2,
|
|
2167
|
-
maxDistance = 100,
|
|
2168
|
-
onChange
|
|
2169
|
-
}, ref) => {
|
|
2170
|
-
const { camera, set, viewport } = useThree();
|
|
2171
|
-
const controlsRef = useRef(null);
|
|
2172
|
-
const initialPosition = useRef(new THREE.Vector3(...position));
|
|
2173
|
-
const initialTarget = useRef(new THREE.Vector3(...target));
|
|
2174
|
-
useEffect(() => {
|
|
2175
|
-
let newCamera;
|
|
2176
|
-
if (mode === "isometric") {
|
|
2177
|
-
const aspect = viewport.aspect;
|
|
2178
|
-
const size = 10 / zoom;
|
|
2179
|
-
newCamera = new THREE.OrthographicCamera(
|
|
2180
|
-
-size * aspect,
|
|
2181
|
-
size * aspect,
|
|
2182
|
-
size,
|
|
2183
|
-
-size,
|
|
2184
|
-
0.1,
|
|
2185
|
-
1e3
|
|
2186
|
-
);
|
|
2187
|
-
} else {
|
|
2188
|
-
newCamera = new THREE.PerspectiveCamera(fov, viewport.aspect, 0.1, 1e3);
|
|
2189
|
-
}
|
|
2190
|
-
newCamera.position.copy(initialPosition.current);
|
|
2191
|
-
newCamera.lookAt(initialTarget.current);
|
|
2192
|
-
set({ camera: newCamera });
|
|
2193
|
-
if (mode === "top-down") {
|
|
2194
|
-
newCamera.position.set(0, 20 / zoom, 0);
|
|
2195
|
-
newCamera.lookAt(0, 0, 0);
|
|
2196
|
-
}
|
|
2197
|
-
return () => {
|
|
2198
|
-
};
|
|
2199
|
-
}, [mode, fov, zoom, viewport.aspect, set]);
|
|
2200
|
-
useFrame(() => {
|
|
2201
|
-
if (onChange) {
|
|
2202
|
-
onChange(camera);
|
|
2203
|
-
}
|
|
2204
|
-
});
|
|
2205
|
-
useImperativeHandle(ref, () => ({
|
|
2206
|
-
getCamera: () => camera,
|
|
2207
|
-
setPosition: (x, y, z) => {
|
|
2208
|
-
camera.position.set(x, y, z);
|
|
2209
|
-
if (controlsRef.current) {
|
|
2210
|
-
controlsRef.current.update();
|
|
2211
|
-
}
|
|
2212
|
-
},
|
|
2213
|
-
lookAt: (x, y, z) => {
|
|
2214
|
-
camera.lookAt(x, y, z);
|
|
2215
|
-
if (controlsRef.current) {
|
|
2216
|
-
controlsRef.current.target.set(x, y, z);
|
|
2217
|
-
controlsRef.current.update();
|
|
2218
|
-
}
|
|
2219
|
-
},
|
|
2220
|
-
reset: () => {
|
|
2221
|
-
camera.position.copy(initialPosition.current);
|
|
2222
|
-
camera.lookAt(initialTarget.current);
|
|
2223
|
-
if (controlsRef.current) {
|
|
2224
|
-
controlsRef.current.target.copy(initialTarget.current);
|
|
2225
|
-
controlsRef.current.update();
|
|
2226
|
-
}
|
|
2227
|
-
},
|
|
2228
|
-
getViewBounds: () => {
|
|
2229
|
-
const min = new THREE.Vector3(-10, -10, -10);
|
|
2230
|
-
const max = new THREE.Vector3(10, 10, 10);
|
|
2231
|
-
return { min, max };
|
|
2232
|
-
}
|
|
2233
|
-
}));
|
|
2234
|
-
const maxPolarAngle = mode === "top-down" ? 0.1 : Math.PI / 2 - 0.1;
|
|
2235
|
-
return /* @__PURE__ */ jsx(
|
|
2236
|
-
OrbitControls,
|
|
2237
|
-
{
|
|
2238
|
-
ref: controlsRef,
|
|
2239
|
-
camera,
|
|
2240
|
-
enabled: enableOrbit,
|
|
2241
|
-
target: initialTarget.current,
|
|
2242
|
-
minDistance,
|
|
2243
|
-
maxDistance,
|
|
2244
|
-
maxPolarAngle,
|
|
2245
|
-
enableDamping: true,
|
|
2246
|
-
dampingFactor: 0.05
|
|
2247
|
-
}
|
|
2248
|
-
);
|
|
2249
|
-
}
|
|
2250
|
-
);
|
|
2251
|
-
Camera3D.displayName = "Camera3D";
|
|
2252
|
-
var Canvas3DErrorBoundary = class extends Component {
|
|
2253
|
-
constructor(props) {
|
|
2254
|
-
super(props);
|
|
2255
|
-
__publicField(this, "handleReset", () => {
|
|
2256
|
-
this.setState({
|
|
2257
|
-
hasError: false,
|
|
2258
|
-
error: null,
|
|
2259
|
-
errorInfo: null
|
|
2260
|
-
});
|
|
2261
|
-
this.props.onReset?.();
|
|
2262
|
-
});
|
|
2263
|
-
this.state = {
|
|
2264
|
-
hasError: false,
|
|
2265
|
-
error: null,
|
|
2266
|
-
errorInfo: null
|
|
2267
|
-
};
|
|
2268
|
-
}
|
|
2269
|
-
static getDerivedStateFromError(error) {
|
|
2270
|
-
return {
|
|
2271
|
-
hasError: true,
|
|
2272
|
-
error,
|
|
2273
|
-
errorInfo: null
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
componentDidCatch(error, errorInfo) {
|
|
2277
|
-
this.setState({ errorInfo });
|
|
2278
|
-
this.props.onError?.(error, errorInfo);
|
|
2279
|
-
console.error("[Canvas3DErrorBoundary] Error caught:", error);
|
|
2280
|
-
console.error("[Canvas3DErrorBoundary] Component stack:", errorInfo.componentStack);
|
|
2281
|
-
}
|
|
2282
|
-
render() {
|
|
2283
|
-
if (this.state.hasError) {
|
|
2284
|
-
if (this.props.fallback) {
|
|
2285
|
-
return this.props.fallback;
|
|
2286
|
-
}
|
|
2287
|
-
return /* @__PURE__ */ jsx("div", { className: "canvas-3d-error", children: /* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__content", children: [
|
|
2288
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-error__icon", children: "\u26A0\uFE0F" }),
|
|
2289
|
-
/* @__PURE__ */ jsx("h2", { className: "canvas-3d-error__title", children: "3D Scene Error" }),
|
|
2290
|
-
/* @__PURE__ */ jsx("p", { className: "canvas-3d-error__message", children: "Something went wrong while rendering the 3D scene." }),
|
|
2291
|
-
this.state.error && /* @__PURE__ */ jsxs("details", { className: "canvas-3d-error__details", children: [
|
|
2292
|
-
/* @__PURE__ */ jsx("summary", { children: "Error Details" }),
|
|
2293
|
-
/* @__PURE__ */ jsxs("pre", { className: "error__stack", children: [
|
|
2294
|
-
this.state.error.message,
|
|
2295
|
-
"\n",
|
|
2296
|
-
this.state.error.stack
|
|
2297
|
-
] }),
|
|
2298
|
-
this.state.errorInfo && /* @__PURE__ */ jsx("pre", { className: "error__component-stack", children: this.state.errorInfo.componentStack })
|
|
2299
|
-
] }),
|
|
2300
|
-
/* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__actions", children: [
|
|
2301
|
-
/* @__PURE__ */ jsx(
|
|
2302
|
-
"button",
|
|
2303
|
-
{
|
|
2304
|
-
className: "error__button error__button--primary",
|
|
2305
|
-
onClick: this.handleReset,
|
|
2306
|
-
children: "Try Again"
|
|
2307
|
-
}
|
|
2308
|
-
),
|
|
2309
|
-
/* @__PURE__ */ jsx(
|
|
2310
|
-
"button",
|
|
2311
|
-
{
|
|
2312
|
-
className: "error__button error__button--secondary",
|
|
2313
|
-
onClick: () => window.location.reload(),
|
|
2314
|
-
children: "Reload Page"
|
|
2315
|
-
}
|
|
2316
|
-
)
|
|
2317
|
-
] })
|
|
2318
|
-
] }) });
|
|
2319
|
-
}
|
|
2320
|
-
return this.props.children;
|
|
2321
|
-
}
|
|
2322
|
-
};
|
|
2323
|
-
function Canvas3DLoadingState({
|
|
2324
|
-
progress = 0,
|
|
2325
|
-
loaded = 0,
|
|
2326
|
-
total = 0,
|
|
2327
|
-
message = "Loading 3D Scene...",
|
|
2328
|
-
details,
|
|
2329
|
-
showSpinner = true,
|
|
2330
|
-
className
|
|
2331
|
-
}) {
|
|
2332
|
-
const clampedProgress = Math.max(0, Math.min(100, progress));
|
|
2333
|
-
const hasProgress = total > 0;
|
|
2334
|
-
return /* @__PURE__ */ jsxs("div", { className: `canvas-3d-loading ${className || ""}`, children: [
|
|
2335
|
-
/* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__content", children: [
|
|
2336
|
-
showSpinner && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__spinner", children: [
|
|
2337
|
-
/* @__PURE__ */ jsx("div", { className: "spinner__ring" }),
|
|
2338
|
-
/* @__PURE__ */ jsx("div", { className: "spinner__ring spinner__ring--secondary" })
|
|
2339
|
-
] }),
|
|
2340
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__message", children: message }),
|
|
2341
|
-
details && /* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__details", children: details }),
|
|
2342
|
-
hasProgress && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__progress", children: [
|
|
2343
|
-
/* @__PURE__ */ jsx("div", { className: "progress__bar", children: /* @__PURE__ */ jsx(
|
|
2344
|
-
"div",
|
|
2345
|
-
{
|
|
2346
|
-
className: "progress__fill",
|
|
2347
|
-
style: { width: `${clampedProgress}%` }
|
|
2348
|
-
}
|
|
2349
|
-
) }),
|
|
2350
|
-
/* @__PURE__ */ jsxs("div", { className: "progress__text", children: [
|
|
2351
|
-
/* @__PURE__ */ jsxs("span", { className: "progress__percentage", children: [
|
|
2352
|
-
clampedProgress,
|
|
2353
|
-
"%"
|
|
2354
|
-
] }),
|
|
2355
|
-
/* @__PURE__ */ jsxs("span", { className: "progress__count", children: [
|
|
2356
|
-
"(",
|
|
2357
|
-
loaded,
|
|
2358
|
-
"/",
|
|
2359
|
-
total,
|
|
2360
|
-
")"
|
|
2361
|
-
] })
|
|
2362
|
-
] })
|
|
2363
|
-
] })
|
|
2364
|
-
] }),
|
|
2365
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__background", children: /* @__PURE__ */ jsx("div", { className: "bg__grid" }) })
|
|
2366
|
-
] });
|
|
2367
|
-
}
|
|
2368
2143
|
|
|
2369
2144
|
// lib/debug.ts
|
|
2370
2145
|
typeof window !== "undefined" && (localStorage.getItem("debug") === "true" || process.env.NODE_ENV === "development");
|
|
2371
2146
|
lazy(() => import('react-markdown'));
|
|
2372
2147
|
var GameAudioContext = createContext(null);
|
|
2373
2148
|
GameAudioContext.displayName = "GameAudioContext";
|
|
2374
|
-
function detectAssetRoot2(modelUrl) {
|
|
2375
|
-
const idx = modelUrl.indexOf("/3d/");
|
|
2376
|
-
if (idx !== -1) {
|
|
2377
|
-
return modelUrl.substring(0, idx + 4);
|
|
2378
|
-
}
|
|
2379
|
-
return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
|
|
2380
|
-
}
|
|
2381
|
-
function createGLTFLoaderForUrl(url) {
|
|
2382
|
-
const loader = new GLTFLoader();
|
|
2383
|
-
loader.setResourcePath(detectAssetRoot2(url));
|
|
2384
|
-
return loader;
|
|
2385
|
-
}
|
|
2386
|
-
var AssetLoader = class {
|
|
2387
|
-
constructor() {
|
|
2388
|
-
__publicField(this, "objLoader");
|
|
2389
|
-
__publicField(this, "textureLoader");
|
|
2390
|
-
__publicField(this, "modelCache");
|
|
2391
|
-
__publicField(this, "textureCache");
|
|
2392
|
-
__publicField(this, "loadingPromises");
|
|
2393
|
-
this.objLoader = new OBJLoader();
|
|
2394
|
-
this.textureLoader = new THREE.TextureLoader();
|
|
2395
|
-
this.modelCache = /* @__PURE__ */ new Map();
|
|
2396
|
-
this.textureCache = /* @__PURE__ */ new Map();
|
|
2397
|
-
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
2398
|
-
}
|
|
2399
|
-
/**
|
|
2400
|
-
* Load a GLB/GLTF model
|
|
2401
|
-
* @param url - URL to the .glb or .gltf file
|
|
2402
|
-
* @returns Promise with loaded model scene and animations
|
|
2403
|
-
*/
|
|
2404
|
-
async loadModel(url) {
|
|
2405
|
-
if (this.modelCache.has(url)) {
|
|
2406
|
-
return this.modelCache.get(url);
|
|
2407
|
-
}
|
|
2408
|
-
if (this.loadingPromises.has(url)) {
|
|
2409
|
-
return this.loadingPromises.get(url);
|
|
2410
|
-
}
|
|
2411
|
-
const loader = createGLTFLoaderForUrl(url);
|
|
2412
|
-
const loadPromise = loader.loadAsync(url).then((gltf) => {
|
|
2413
|
-
const result = {
|
|
2414
|
-
scene: gltf.scene,
|
|
2415
|
-
animations: gltf.animations || []
|
|
2416
|
-
};
|
|
2417
|
-
this.modelCache.set(url, result);
|
|
2418
|
-
this.loadingPromises.delete(url);
|
|
2419
|
-
return result;
|
|
2420
|
-
}).catch((error) => {
|
|
2421
|
-
this.loadingPromises.delete(url);
|
|
2422
|
-
throw new Error(`Failed to load model ${url}: ${error.message}`);
|
|
2423
|
-
});
|
|
2424
|
-
this.loadingPromises.set(url, loadPromise);
|
|
2425
|
-
return loadPromise;
|
|
2426
|
-
}
|
|
2427
|
-
/**
|
|
2428
|
-
* Load an OBJ model (fallback for non-GLB assets)
|
|
2429
|
-
* @param url - URL to the .obj file
|
|
2430
|
-
* @returns Promise with loaded object group
|
|
2431
|
-
*/
|
|
2432
|
-
async loadOBJ(url) {
|
|
2433
|
-
if (this.modelCache.has(url)) {
|
|
2434
|
-
return this.modelCache.get(url).scene;
|
|
2435
|
-
}
|
|
2436
|
-
if (this.loadingPromises.has(url)) {
|
|
2437
|
-
const result = await this.loadingPromises.get(url);
|
|
2438
|
-
return result.scene;
|
|
2439
|
-
}
|
|
2440
|
-
const loadPromise = this.objLoader.loadAsync(url).then((group) => {
|
|
2441
|
-
const result = {
|
|
2442
|
-
scene: group,
|
|
2443
|
-
animations: []
|
|
2444
|
-
};
|
|
2445
|
-
this.modelCache.set(url, result);
|
|
2446
|
-
this.loadingPromises.delete(url);
|
|
2447
|
-
return result;
|
|
2448
|
-
}).catch((error) => {
|
|
2449
|
-
this.loadingPromises.delete(url);
|
|
2450
|
-
throw new Error(`Failed to load OBJ ${url}: ${error.message}`);
|
|
2451
|
-
});
|
|
2452
|
-
this.loadingPromises.set(url, loadPromise);
|
|
2453
|
-
return (await loadPromise).scene;
|
|
2454
|
-
}
|
|
2455
|
-
/**
|
|
2456
|
-
* Load a texture
|
|
2457
|
-
* @param url - URL to the texture image
|
|
2458
|
-
* @returns Promise with loaded texture
|
|
2459
|
-
*/
|
|
2460
|
-
async loadTexture(url) {
|
|
2461
|
-
if (this.textureCache.has(url)) {
|
|
2462
|
-
return this.textureCache.get(url);
|
|
2463
|
-
}
|
|
2464
|
-
if (this.loadingPromises.has(`texture:${url}`)) {
|
|
2465
|
-
return this.loadingPromises.get(`texture:${url}`);
|
|
2466
|
-
}
|
|
2467
|
-
const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
|
|
2468
|
-
texture.colorSpace = THREE.SRGBColorSpace;
|
|
2469
|
-
this.textureCache.set(url, texture);
|
|
2470
|
-
this.loadingPromises.delete(`texture:${url}`);
|
|
2471
|
-
return texture;
|
|
2472
|
-
}).catch((error) => {
|
|
2473
|
-
this.loadingPromises.delete(`texture:${url}`);
|
|
2474
|
-
throw new Error(`Failed to load texture ${url}: ${error.message}`);
|
|
2475
|
-
});
|
|
2476
|
-
this.loadingPromises.set(`texture:${url}`, loadPromise);
|
|
2477
|
-
return loadPromise;
|
|
2478
|
-
}
|
|
2479
|
-
/**
|
|
2480
|
-
* Preload multiple assets
|
|
2481
|
-
* @param urls - Array of asset URLs to preload
|
|
2482
|
-
* @returns Promise that resolves when all assets are loaded
|
|
2483
|
-
*/
|
|
2484
|
-
async preload(urls) {
|
|
2485
|
-
const promises = urls.map((url) => {
|
|
2486
|
-
if (url.endsWith(".glb") || url.endsWith(".gltf")) {
|
|
2487
|
-
return this.loadModel(url).catch(() => null);
|
|
2488
|
-
} else if (url.endsWith(".obj")) {
|
|
2489
|
-
return this.loadOBJ(url).catch(() => null);
|
|
2490
|
-
} else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
|
|
2491
|
-
return this.loadTexture(url).catch(() => null);
|
|
2492
|
-
}
|
|
2493
|
-
return Promise.resolve(null);
|
|
2494
|
-
});
|
|
2495
|
-
await Promise.all(promises);
|
|
2496
|
-
}
|
|
2497
|
-
/**
|
|
2498
|
-
* Check if a model is cached
|
|
2499
|
-
* @param url - Model URL
|
|
2500
|
-
*/
|
|
2501
|
-
hasModel(url) {
|
|
2502
|
-
return this.modelCache.has(url);
|
|
2503
|
-
}
|
|
2504
|
-
/**
|
|
2505
|
-
* Check if a texture is cached
|
|
2506
|
-
* @param url - Texture URL
|
|
2507
|
-
*/
|
|
2508
|
-
hasTexture(url) {
|
|
2509
|
-
return this.textureCache.has(url);
|
|
2510
|
-
}
|
|
2511
|
-
/**
|
|
2512
|
-
* Get cached model (throws if not cached)
|
|
2513
|
-
* @param url - Model URL
|
|
2514
|
-
*/
|
|
2515
|
-
getModel(url) {
|
|
2516
|
-
const model = this.modelCache.get(url);
|
|
2517
|
-
if (!model) {
|
|
2518
|
-
throw new Error(`Model ${url} not in cache`);
|
|
2519
|
-
}
|
|
2520
|
-
return model;
|
|
2521
|
-
}
|
|
2522
|
-
/**
|
|
2523
|
-
* Get cached texture (throws if not cached)
|
|
2524
|
-
* @param url - Texture URL
|
|
2525
|
-
*/
|
|
2526
|
-
getTexture(url) {
|
|
2527
|
-
const texture = this.textureCache.get(url);
|
|
2528
|
-
if (!texture) {
|
|
2529
|
-
throw new Error(`Texture ${url} not in cache`);
|
|
2530
|
-
}
|
|
2531
|
-
return texture;
|
|
2532
|
-
}
|
|
2533
|
-
/**
|
|
2534
|
-
* Clear all caches
|
|
2535
|
-
*/
|
|
2536
|
-
clearCache() {
|
|
2537
|
-
this.textureCache.forEach((texture) => {
|
|
2538
|
-
texture.dispose();
|
|
2539
|
-
});
|
|
2540
|
-
this.modelCache.forEach((model) => {
|
|
2541
|
-
model.scene.traverse((child) => {
|
|
2542
|
-
if (child instanceof THREE.Mesh) {
|
|
2543
|
-
child.geometry.dispose();
|
|
2544
|
-
if (Array.isArray(child.material)) {
|
|
2545
|
-
child.material.forEach((m) => m.dispose());
|
|
2546
|
-
} else {
|
|
2547
|
-
child.material.dispose();
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
});
|
|
2551
|
-
});
|
|
2552
|
-
this.modelCache.clear();
|
|
2553
|
-
this.textureCache.clear();
|
|
2554
|
-
this.loadingPromises.clear();
|
|
2555
|
-
}
|
|
2556
|
-
/**
|
|
2557
|
-
* Get cache statistics
|
|
2558
|
-
*/
|
|
2559
|
-
getStats() {
|
|
2560
|
-
return {
|
|
2561
|
-
models: this.modelCache.size,
|
|
2562
|
-
textures: this.textureCache.size,
|
|
2563
|
-
loading: this.loadingPromises.size
|
|
2564
|
-
};
|
|
2565
|
-
}
|
|
2566
|
-
};
|
|
2567
|
-
new AssetLoader();
|
|
2568
|
-
function useAssetLoader(options = {}) {
|
|
2569
|
-
const { preloadUrls = [], loader: customLoader } = options;
|
|
2570
|
-
const loaderRef = useRef(customLoader || new AssetLoader());
|
|
2571
|
-
const [state, setState] = useState({
|
|
2572
|
-
isLoading: false,
|
|
2573
|
-
progress: 0,
|
|
2574
|
-
loaded: 0,
|
|
2575
|
-
total: 0,
|
|
2576
|
-
errors: []
|
|
2577
|
-
});
|
|
2578
|
-
useEffect(() => {
|
|
2579
|
-
if (preloadUrls.length > 0) {
|
|
2580
|
-
preload(preloadUrls);
|
|
2581
|
-
}
|
|
2582
|
-
}, []);
|
|
2583
|
-
const updateProgress = useCallback((loaded, total) => {
|
|
2584
|
-
setState((prev) => ({
|
|
2585
|
-
...prev,
|
|
2586
|
-
loaded,
|
|
2587
|
-
total,
|
|
2588
|
-
progress: total > 0 ? Math.round(loaded / total * 100) : 0
|
|
2589
|
-
}));
|
|
2590
|
-
}, []);
|
|
2591
|
-
const loadModel = useCallback(
|
|
2592
|
-
async (url) => {
|
|
2593
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
2594
|
-
try {
|
|
2595
|
-
const model = await loaderRef.current.loadModel(url);
|
|
2596
|
-
setState((prev) => ({
|
|
2597
|
-
...prev,
|
|
2598
|
-
isLoading: false,
|
|
2599
|
-
loaded: prev.loaded + 1
|
|
2600
|
-
}));
|
|
2601
|
-
return model;
|
|
2602
|
-
} catch (error) {
|
|
2603
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2604
|
-
setState((prev) => ({
|
|
2605
|
-
...prev,
|
|
2606
|
-
isLoading: false,
|
|
2607
|
-
errors: [...prev.errors, errorMsg]
|
|
2608
|
-
}));
|
|
2609
|
-
throw error;
|
|
2610
|
-
}
|
|
2611
|
-
},
|
|
2612
|
-
[]
|
|
2613
|
-
);
|
|
2614
|
-
const loadOBJ = useCallback(
|
|
2615
|
-
async (url) => {
|
|
2616
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
2617
|
-
try {
|
|
2618
|
-
const model = await loaderRef.current.loadOBJ(url);
|
|
2619
|
-
setState((prev) => ({
|
|
2620
|
-
...prev,
|
|
2621
|
-
isLoading: false,
|
|
2622
|
-
loaded: prev.loaded + 1
|
|
2623
|
-
}));
|
|
2624
|
-
return model;
|
|
2625
|
-
} catch (error) {
|
|
2626
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2627
|
-
setState((prev) => ({
|
|
2628
|
-
...prev,
|
|
2629
|
-
isLoading: false,
|
|
2630
|
-
errors: [...prev.errors, errorMsg]
|
|
2631
|
-
}));
|
|
2632
|
-
throw error;
|
|
2633
|
-
}
|
|
2634
|
-
},
|
|
2635
|
-
[]
|
|
2636
|
-
);
|
|
2637
|
-
const loadTexture = useCallback(
|
|
2638
|
-
async (url) => {
|
|
2639
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
2640
|
-
try {
|
|
2641
|
-
const texture = await loaderRef.current.loadTexture(url);
|
|
2642
|
-
setState((prev) => ({
|
|
2643
|
-
...prev,
|
|
2644
|
-
isLoading: false,
|
|
2645
|
-
loaded: prev.loaded + 1
|
|
2646
|
-
}));
|
|
2647
|
-
return texture;
|
|
2648
|
-
} catch (error) {
|
|
2649
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2650
|
-
setState((prev) => ({
|
|
2651
|
-
...prev,
|
|
2652
|
-
isLoading: false,
|
|
2653
|
-
errors: [...prev.errors, errorMsg]
|
|
2654
|
-
}));
|
|
2655
|
-
throw error;
|
|
2656
|
-
}
|
|
2657
|
-
},
|
|
2658
|
-
[]
|
|
2659
|
-
);
|
|
2660
|
-
const preload = useCallback(
|
|
2661
|
-
async (urls) => {
|
|
2662
|
-
setState((prev) => ({
|
|
2663
|
-
...prev,
|
|
2664
|
-
isLoading: true,
|
|
2665
|
-
total: urls.length,
|
|
2666
|
-
loaded: 0,
|
|
2667
|
-
errors: []
|
|
2668
|
-
}));
|
|
2669
|
-
let completed = 0;
|
|
2670
|
-
const errors = [];
|
|
2671
|
-
await Promise.all(
|
|
2672
|
-
urls.map(async (url) => {
|
|
2673
|
-
try {
|
|
2674
|
-
if (url.endsWith(".glb") || url.endsWith(".gltf")) {
|
|
2675
|
-
await loaderRef.current.loadModel(url);
|
|
2676
|
-
} else if (url.endsWith(".obj")) {
|
|
2677
|
-
await loaderRef.current.loadOBJ(url);
|
|
2678
|
-
} else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
|
|
2679
|
-
await loaderRef.current.loadTexture(url);
|
|
2680
|
-
}
|
|
2681
|
-
completed++;
|
|
2682
|
-
updateProgress(completed, urls.length);
|
|
2683
|
-
} catch (error) {
|
|
2684
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2685
|
-
errors.push(`${url}: ${errorMsg}`);
|
|
2686
|
-
completed++;
|
|
2687
|
-
updateProgress(completed, urls.length);
|
|
2688
|
-
}
|
|
2689
|
-
})
|
|
2690
|
-
);
|
|
2691
|
-
setState((prev) => ({
|
|
2692
|
-
...prev,
|
|
2693
|
-
isLoading: false,
|
|
2694
|
-
errors
|
|
2695
|
-
}));
|
|
2696
|
-
},
|
|
2697
|
-
[updateProgress]
|
|
2698
|
-
);
|
|
2699
|
-
const hasModel = useCallback((url) => {
|
|
2700
|
-
return loaderRef.current.hasModel(url);
|
|
2701
|
-
}, []);
|
|
2702
|
-
const hasTexture = useCallback((url) => {
|
|
2703
|
-
return loaderRef.current.hasTexture(url);
|
|
2704
|
-
}, []);
|
|
2705
|
-
const getModel = useCallback((url) => {
|
|
2706
|
-
try {
|
|
2707
|
-
return loaderRef.current.getModel(url);
|
|
2708
|
-
} catch {
|
|
2709
|
-
return void 0;
|
|
2710
|
-
}
|
|
2711
|
-
}, []);
|
|
2712
|
-
const getTexture = useCallback((url) => {
|
|
2713
|
-
try {
|
|
2714
|
-
return loaderRef.current.getTexture(url);
|
|
2715
|
-
} catch {
|
|
2716
|
-
return void 0;
|
|
2717
|
-
}
|
|
2718
|
-
}, []);
|
|
2719
|
-
const clearCache = useCallback(() => {
|
|
2720
|
-
loaderRef.current.clearCache();
|
|
2721
|
-
setState({
|
|
2722
|
-
isLoading: false,
|
|
2723
|
-
progress: 0,
|
|
2724
|
-
loaded: 0,
|
|
2725
|
-
total: 0,
|
|
2726
|
-
errors: []
|
|
2727
|
-
});
|
|
2728
|
-
}, []);
|
|
2729
|
-
return {
|
|
2730
|
-
...state,
|
|
2731
|
-
loadModel,
|
|
2732
|
-
loadOBJ,
|
|
2733
|
-
loadTexture,
|
|
2734
|
-
preload,
|
|
2735
|
-
hasModel,
|
|
2736
|
-
hasTexture,
|
|
2737
|
-
getModel,
|
|
2738
|
-
getTexture,
|
|
2739
|
-
clearCache
|
|
2740
|
-
};
|
|
2741
|
-
}
|
|
2742
|
-
function useGameCanvas3DEvents(options) {
|
|
2743
|
-
const {
|
|
2744
|
-
tileClickEvent,
|
|
2745
|
-
unitClickEvent,
|
|
2746
|
-
featureClickEvent,
|
|
2747
|
-
canvasClickEvent,
|
|
2748
|
-
tileHoverEvent,
|
|
2749
|
-
tileLeaveEvent,
|
|
2750
|
-
unitAnimationEvent,
|
|
2751
|
-
cameraChangeEvent,
|
|
2752
|
-
onTileClick,
|
|
2753
|
-
onUnitClick,
|
|
2754
|
-
onFeatureClick,
|
|
2755
|
-
onCanvasClick,
|
|
2756
|
-
onTileHover,
|
|
2757
|
-
onUnitAnimation
|
|
2758
|
-
} = options;
|
|
2759
|
-
const emit = useEmitEvent();
|
|
2760
|
-
const optionsRef = useRef(options);
|
|
2761
|
-
optionsRef.current = options;
|
|
2762
|
-
const handleTileClick = useCallback(
|
|
2763
|
-
(tile, event) => {
|
|
2764
|
-
if (tileClickEvent) {
|
|
2765
|
-
emit(tileClickEvent, {
|
|
2766
|
-
tileId: tile.id,
|
|
2767
|
-
x: tile.x,
|
|
2768
|
-
z: tile.z ?? tile.y ?? 0,
|
|
2769
|
-
type: tile.type,
|
|
2770
|
-
terrain: tile.terrain,
|
|
2771
|
-
elevation: tile.elevation
|
|
2772
|
-
});
|
|
2773
|
-
}
|
|
2774
|
-
optionsRef.current.onTileClick?.(tile, event);
|
|
2775
|
-
},
|
|
2776
|
-
[tileClickEvent, emit]
|
|
2777
|
-
);
|
|
2778
|
-
const handleUnitClick = useCallback(
|
|
2779
|
-
(unit, event) => {
|
|
2780
|
-
if (unitClickEvent) {
|
|
2781
|
-
emit(unitClickEvent, {
|
|
2782
|
-
unitId: unit.id,
|
|
2783
|
-
x: unit.x,
|
|
2784
|
-
z: unit.z ?? unit.y ?? 0,
|
|
2785
|
-
unitType: unit.unitType,
|
|
2786
|
-
name: unit.name,
|
|
2787
|
-
team: unit.team,
|
|
2788
|
-
faction: unit.faction,
|
|
2789
|
-
health: unit.health,
|
|
2790
|
-
maxHealth: unit.maxHealth
|
|
2791
|
-
});
|
|
2792
|
-
}
|
|
2793
|
-
optionsRef.current.onUnitClick?.(unit, event);
|
|
2794
|
-
},
|
|
2795
|
-
[unitClickEvent, emit]
|
|
2796
|
-
);
|
|
2797
|
-
const handleFeatureClick = useCallback(
|
|
2798
|
-
(feature, event) => {
|
|
2799
|
-
if (featureClickEvent) {
|
|
2800
|
-
emit(featureClickEvent, {
|
|
2801
|
-
featureId: feature.id,
|
|
2802
|
-
x: feature.x,
|
|
2803
|
-
z: feature.z ?? feature.y ?? 0,
|
|
2804
|
-
type: feature.type,
|
|
2805
|
-
elevation: feature.elevation
|
|
2806
|
-
});
|
|
2807
|
-
}
|
|
2808
|
-
optionsRef.current.onFeatureClick?.(feature, event);
|
|
2809
|
-
},
|
|
2810
|
-
[featureClickEvent, emit]
|
|
2811
|
-
);
|
|
2812
|
-
const handleCanvasClick = useCallback(
|
|
2813
|
-
(event) => {
|
|
2814
|
-
if (canvasClickEvent) {
|
|
2815
|
-
emit(canvasClickEvent, {
|
|
2816
|
-
clientX: event.clientX,
|
|
2817
|
-
clientY: event.clientY,
|
|
2818
|
-
button: event.button
|
|
2819
|
-
});
|
|
2820
|
-
}
|
|
2821
|
-
optionsRef.current.onCanvasClick?.(event);
|
|
2822
|
-
},
|
|
2823
|
-
[canvasClickEvent, emit]
|
|
2824
|
-
);
|
|
2825
|
-
const handleTileHover = useCallback(
|
|
2826
|
-
(tile, event) => {
|
|
2827
|
-
if (tile) {
|
|
2828
|
-
if (tileHoverEvent) {
|
|
2829
|
-
emit(tileHoverEvent, {
|
|
2830
|
-
tileId: tile.id,
|
|
2831
|
-
x: tile.x,
|
|
2832
|
-
z: tile.z ?? tile.y ?? 0,
|
|
2833
|
-
type: tile.type
|
|
2834
|
-
});
|
|
2835
|
-
}
|
|
2836
|
-
} else {
|
|
2837
|
-
if (tileLeaveEvent) {
|
|
2838
|
-
emit(tileLeaveEvent, {});
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
optionsRef.current.onTileHover?.(tile, event);
|
|
2842
|
-
},
|
|
2843
|
-
[tileHoverEvent, tileLeaveEvent, emit]
|
|
2844
|
-
);
|
|
2845
|
-
const handleUnitAnimation = useCallback(
|
|
2846
|
-
(unitId, state) => {
|
|
2847
|
-
if (unitAnimationEvent) {
|
|
2848
|
-
emit(unitAnimationEvent, {
|
|
2849
|
-
unitId,
|
|
2850
|
-
state,
|
|
2851
|
-
timestamp: Date.now()
|
|
2852
|
-
});
|
|
2853
|
-
}
|
|
2854
|
-
optionsRef.current.onUnitAnimation?.(unitId, state);
|
|
2855
|
-
},
|
|
2856
|
-
[unitAnimationEvent, emit]
|
|
2857
|
-
);
|
|
2858
|
-
const handleCameraChange = useCallback(
|
|
2859
|
-
(position) => {
|
|
2860
|
-
if (cameraChangeEvent) {
|
|
2861
|
-
emit(cameraChangeEvent, {
|
|
2862
|
-
position,
|
|
2863
|
-
timestamp: Date.now()
|
|
2864
|
-
});
|
|
2865
|
-
}
|
|
2866
|
-
},
|
|
2867
|
-
[cameraChangeEvent, emit]
|
|
2868
|
-
);
|
|
2869
|
-
return {
|
|
2870
|
-
handleTileClick,
|
|
2871
|
-
handleUnitClick,
|
|
2872
|
-
handleFeatureClick,
|
|
2873
|
-
handleCanvasClick,
|
|
2874
|
-
handleTileHover,
|
|
2875
|
-
handleUnitAnimation,
|
|
2876
|
-
handleCameraChange
|
|
2877
|
-
};
|
|
2878
|
-
}
|
|
2879
|
-
function detectAssetRoot3(modelUrl) {
|
|
2880
|
-
const idx = modelUrl.indexOf("/3d/");
|
|
2881
|
-
if (idx !== -1) {
|
|
2882
|
-
return modelUrl.substring(0, idx + 4);
|
|
2883
|
-
}
|
|
2884
|
-
return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
|
|
2885
|
-
}
|
|
2886
|
-
function useGLTFModel2(url, resourceBasePath) {
|
|
2887
|
-
const [state, setState] = useState({
|
|
2888
|
-
model: null,
|
|
2889
|
-
isLoading: false,
|
|
2890
|
-
error: null
|
|
2891
|
-
});
|
|
2892
|
-
useEffect(() => {
|
|
2893
|
-
if (!url) {
|
|
2894
|
-
setState({ model: null, isLoading: false, error: null });
|
|
2895
|
-
return;
|
|
2896
|
-
}
|
|
2897
|
-
console.log("[ModelLoader] Loading:", url);
|
|
2898
|
-
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
2899
|
-
const assetRoot = resourceBasePath || detectAssetRoot3(url);
|
|
2900
|
-
const loader = new GLTFLoader$1();
|
|
2901
|
-
loader.setResourcePath(assetRoot);
|
|
2902
|
-
loader.load(
|
|
2903
|
-
url,
|
|
2904
|
-
(gltf) => {
|
|
2905
|
-
console.log("[ModelLoader] Loaded:", url);
|
|
2906
|
-
setState({
|
|
2907
|
-
model: gltf.scene,
|
|
2908
|
-
isLoading: false,
|
|
2909
|
-
error: null
|
|
2910
|
-
});
|
|
2911
|
-
},
|
|
2912
|
-
void 0,
|
|
2913
|
-
(err) => {
|
|
2914
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
2915
|
-
console.warn("[ModelLoader] Failed:", url, errorMsg);
|
|
2916
|
-
setState({
|
|
2917
|
-
model: null,
|
|
2918
|
-
isLoading: false,
|
|
2919
|
-
error: err instanceof Error ? err : new Error(String(err))
|
|
2920
|
-
});
|
|
2921
|
-
}
|
|
2922
|
-
);
|
|
2923
|
-
}, [url, resourceBasePath]);
|
|
2924
|
-
return state;
|
|
2925
|
-
}
|
|
2926
|
-
function ModelLoader({
|
|
2927
|
-
url,
|
|
2928
|
-
position = [0, 0, 0],
|
|
2929
|
-
scale = 1,
|
|
2930
|
-
rotation = [0, 0, 0],
|
|
2931
|
-
isSelected = false,
|
|
2932
|
-
isHovered = false,
|
|
2933
|
-
onClick,
|
|
2934
|
-
onHover,
|
|
2935
|
-
fallbackGeometry = "box",
|
|
2936
|
-
castShadow = true,
|
|
2937
|
-
receiveShadow = true,
|
|
2938
|
-
resourceBasePath
|
|
2939
|
-
}) {
|
|
2940
|
-
const { model: loadedModel, isLoading, error } = useGLTFModel2(url, resourceBasePath);
|
|
2941
|
-
const model = useMemo(() => {
|
|
2942
|
-
if (!loadedModel) return null;
|
|
2943
|
-
const cloned = loadedModel.clone();
|
|
2944
|
-
cloned.traverse((child) => {
|
|
2945
|
-
if (child instanceof THREE.Mesh) {
|
|
2946
|
-
child.castShadow = castShadow;
|
|
2947
|
-
child.receiveShadow = receiveShadow;
|
|
2948
|
-
}
|
|
2949
|
-
});
|
|
2950
|
-
return cloned;
|
|
2951
|
-
}, [loadedModel, castShadow, receiveShadow]);
|
|
2952
|
-
const scaleArray = useMemo(() => {
|
|
2953
|
-
if (typeof scale === "number") {
|
|
2954
|
-
return [scale, scale, scale];
|
|
2955
|
-
}
|
|
2956
|
-
return scale;
|
|
2957
|
-
}, [scale]);
|
|
2958
|
-
const rotationRad = useMemo(() => {
|
|
2959
|
-
return [
|
|
2960
|
-
rotation[0] * Math.PI / 180,
|
|
2961
|
-
rotation[1] * Math.PI / 180,
|
|
2962
|
-
rotation[2] * Math.PI / 180
|
|
2963
|
-
];
|
|
2964
|
-
}, [rotation]);
|
|
2965
|
-
if (isLoading) {
|
|
2966
|
-
return /* @__PURE__ */ jsx("group", { position, children: /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
2967
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.3, 0.35, 16] }),
|
|
2968
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: "#4a90d9", transparent: true, opacity: 0.8 })
|
|
2969
|
-
] }) });
|
|
2970
|
-
}
|
|
2971
|
-
if (error || !model) {
|
|
2972
|
-
if (fallbackGeometry === "none") {
|
|
2973
|
-
return /* @__PURE__ */ jsx("group", { position });
|
|
2974
|
-
}
|
|
2975
|
-
const fallbackProps = {
|
|
2976
|
-
onClick,
|
|
2977
|
-
onPointerOver: () => onHover?.(true),
|
|
2978
|
-
onPointerOut: () => onHover?.(false)
|
|
2979
|
-
};
|
|
2980
|
-
return /* @__PURE__ */ jsxs("group", { position, children: [
|
|
2981
|
-
(isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
2982
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
|
|
2983
|
-
/* @__PURE__ */ jsx(
|
|
2984
|
-
"meshBasicMaterial",
|
|
2985
|
-
{
|
|
2986
|
-
color: isSelected ? 16755200 : 16777215,
|
|
2987
|
-
transparent: true,
|
|
2988
|
-
opacity: 0.5
|
|
2989
|
-
}
|
|
2990
|
-
)
|
|
2991
|
-
] }),
|
|
2992
|
-
fallbackGeometry === "box" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
2993
|
-
/* @__PURE__ */ jsx("boxGeometry", { args: [0.8, 0.8, 0.8] }),
|
|
2994
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
2995
|
-
] }),
|
|
2996
|
-
fallbackGeometry === "sphere" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
2997
|
-
/* @__PURE__ */ jsx("sphereGeometry", { args: [0.4, 16, 16] }),
|
|
2998
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
2999
|
-
] }),
|
|
3000
|
-
fallbackGeometry === "cylinder" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
3001
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.8, 16] }),
|
|
3002
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
3003
|
-
] })
|
|
3004
|
-
] });
|
|
3005
|
-
}
|
|
3006
|
-
return /* @__PURE__ */ jsxs(
|
|
3007
|
-
"group",
|
|
3008
|
-
{
|
|
3009
|
-
position,
|
|
3010
|
-
rotation: rotationRad,
|
|
3011
|
-
onClick,
|
|
3012
|
-
onPointerOver: () => onHover?.(true),
|
|
3013
|
-
onPointerOut: () => onHover?.(false),
|
|
3014
|
-
children: [
|
|
3015
|
-
(isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
3016
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
|
|
3017
|
-
/* @__PURE__ */ jsx(
|
|
3018
|
-
"meshBasicMaterial",
|
|
3019
|
-
{
|
|
3020
|
-
color: isSelected ? 16755200 : 16777215,
|
|
3021
|
-
transparent: true,
|
|
3022
|
-
opacity: 0.5
|
|
3023
|
-
}
|
|
3024
|
-
)
|
|
3025
|
-
] }),
|
|
3026
|
-
/* @__PURE__ */ jsx("primitive", { object: model, scale: scaleArray })
|
|
3027
|
-
]
|
|
3028
|
-
}
|
|
3029
|
-
);
|
|
3030
|
-
}
|
|
3031
|
-
var DEFAULT_GRID_CONFIG = {
|
|
3032
|
-
cellSize: 1,
|
|
3033
|
-
offsetX: 0,
|
|
3034
|
-
offsetZ: 0
|
|
3035
|
-
};
|
|
3036
|
-
function CameraController({
|
|
3037
|
-
onCameraChange
|
|
3038
|
-
}) {
|
|
3039
|
-
const { camera } = useThree();
|
|
3040
|
-
useEffect(() => {
|
|
3041
|
-
if (onCameraChange) {
|
|
3042
|
-
onCameraChange({
|
|
3043
|
-
x: camera.position.x,
|
|
3044
|
-
y: camera.position.y,
|
|
3045
|
-
z: camera.position.z
|
|
3046
|
-
});
|
|
3047
|
-
}
|
|
3048
|
-
}, [camera.position, onCameraChange]);
|
|
3049
|
-
return null;
|
|
3050
|
-
}
|
|
3051
|
-
var GameCanvas3D = forwardRef(
|
|
3052
|
-
({
|
|
3053
|
-
tiles = [],
|
|
3054
|
-
units = [],
|
|
3055
|
-
features = [],
|
|
3056
|
-
events: events2 = [],
|
|
3057
|
-
orientation = "standard",
|
|
3058
|
-
cameraMode = "isometric",
|
|
3059
|
-
showGrid = true,
|
|
3060
|
-
showCoordinates = false,
|
|
3061
|
-
showTileInfo = false,
|
|
3062
|
-
overlay = "default",
|
|
3063
|
-
shadows = true,
|
|
3064
|
-
backgroundColor = "#1a1a2e",
|
|
3065
|
-
onTileClick,
|
|
3066
|
-
onUnitClick,
|
|
3067
|
-
onFeatureClick,
|
|
3068
|
-
onCanvasClick,
|
|
3069
|
-
onTileHover,
|
|
3070
|
-
onUnitAnimation,
|
|
3071
|
-
assetLoader: customAssetLoader,
|
|
3072
|
-
tileRenderer: CustomTileRenderer,
|
|
3073
|
-
unitRenderer: CustomUnitRenderer,
|
|
3074
|
-
featureRenderer: CustomFeatureRenderer,
|
|
3075
|
-
className,
|
|
3076
|
-
isLoading: externalLoading,
|
|
3077
|
-
error: externalError,
|
|
3078
|
-
entity,
|
|
3079
|
-
preloadAssets = [],
|
|
3080
|
-
tileClickEvent,
|
|
3081
|
-
unitClickEvent,
|
|
3082
|
-
featureClickEvent,
|
|
3083
|
-
canvasClickEvent,
|
|
3084
|
-
tileHoverEvent,
|
|
3085
|
-
tileLeaveEvent,
|
|
3086
|
-
unitAnimationEvent,
|
|
3087
|
-
cameraChangeEvent,
|
|
3088
|
-
loadingMessage = "Loading 3D Scene...",
|
|
3089
|
-
useInstancing = true,
|
|
3090
|
-
validMoves = [],
|
|
3091
|
-
attackTargets = [],
|
|
3092
|
-
selectedTileIds = [],
|
|
3093
|
-
selectedUnitId = null,
|
|
3094
|
-
children
|
|
3095
|
-
}, ref) => {
|
|
3096
|
-
const containerRef = useRef(null);
|
|
3097
|
-
const controlsRef = useRef(null);
|
|
3098
|
-
const [hoveredTile, setHoveredTile] = useState(null);
|
|
3099
|
-
const [internalError, setInternalError] = useState(null);
|
|
3100
|
-
const { isLoading: assetsLoading, progress, loaded, total } = useAssetLoader({
|
|
3101
|
-
preloadUrls: preloadAssets,
|
|
3102
|
-
loader: customAssetLoader
|
|
3103
|
-
});
|
|
3104
|
-
const eventHandlers = useGameCanvas3DEvents({
|
|
3105
|
-
tileClickEvent,
|
|
3106
|
-
unitClickEvent,
|
|
3107
|
-
featureClickEvent,
|
|
3108
|
-
canvasClickEvent,
|
|
3109
|
-
tileHoverEvent,
|
|
3110
|
-
tileLeaveEvent,
|
|
3111
|
-
unitAnimationEvent,
|
|
3112
|
-
cameraChangeEvent,
|
|
3113
|
-
onTileClick,
|
|
3114
|
-
onUnitClick,
|
|
3115
|
-
onFeatureClick,
|
|
3116
|
-
onCanvasClick,
|
|
3117
|
-
onTileHover,
|
|
3118
|
-
onUnitAnimation
|
|
3119
|
-
});
|
|
3120
|
-
const gridBounds = useMemo(() => {
|
|
3121
|
-
if (tiles.length === 0) {
|
|
3122
|
-
return { minX: 0, maxX: 10, minZ: 0, maxZ: 10 };
|
|
3123
|
-
}
|
|
3124
|
-
const xs = tiles.map((t) => t.x);
|
|
3125
|
-
const zs = tiles.map((t) => t.z || t.y || 0);
|
|
3126
|
-
return {
|
|
3127
|
-
minX: Math.min(...xs),
|
|
3128
|
-
maxX: Math.max(...xs),
|
|
3129
|
-
minZ: Math.min(...zs),
|
|
3130
|
-
maxZ: Math.max(...zs)
|
|
3131
|
-
};
|
|
3132
|
-
}, [tiles]);
|
|
3133
|
-
const cameraTarget = useMemo(() => {
|
|
3134
|
-
return [
|
|
3135
|
-
(gridBounds.minX + gridBounds.maxX) / 2,
|
|
3136
|
-
0,
|
|
3137
|
-
(gridBounds.minZ + gridBounds.maxZ) / 2
|
|
3138
|
-
];
|
|
3139
|
-
}, [gridBounds]);
|
|
3140
|
-
const gridConfig = useMemo(
|
|
3141
|
-
() => ({
|
|
3142
|
-
...DEFAULT_GRID_CONFIG,
|
|
3143
|
-
offsetX: -(gridBounds.maxX - gridBounds.minX) / 2,
|
|
3144
|
-
offsetZ: -(gridBounds.maxZ - gridBounds.minZ) / 2
|
|
3145
|
-
}),
|
|
3146
|
-
[gridBounds]
|
|
3147
|
-
);
|
|
3148
|
-
const gridToWorld = useCallback(
|
|
3149
|
-
(x, z, y = 0) => {
|
|
3150
|
-
const worldX = (x - gridBounds.minX) * gridConfig.cellSize;
|
|
3151
|
-
const worldZ = (z - gridBounds.minZ) * gridConfig.cellSize;
|
|
3152
|
-
return [worldX, y * gridConfig.cellSize, worldZ];
|
|
3153
|
-
},
|
|
3154
|
-
[gridBounds, gridConfig]
|
|
3155
|
-
);
|
|
3156
|
-
useImperativeHandle(ref, () => ({
|
|
3157
|
-
getCameraPosition: () => {
|
|
3158
|
-
if (controlsRef.current) {
|
|
3159
|
-
const pos = controlsRef.current.object.position;
|
|
3160
|
-
return new THREE.Vector3(pos.x, pos.y, pos.z);
|
|
3161
|
-
}
|
|
3162
|
-
return null;
|
|
3163
|
-
},
|
|
3164
|
-
setCameraPosition: (x, y, z) => {
|
|
3165
|
-
if (controlsRef.current) {
|
|
3166
|
-
controlsRef.current.object.position.set(x, y, z);
|
|
3167
|
-
controlsRef.current.update();
|
|
3168
|
-
}
|
|
3169
|
-
},
|
|
3170
|
-
lookAt: (x, y, z) => {
|
|
3171
|
-
if (controlsRef.current) {
|
|
3172
|
-
controlsRef.current.target.set(x, y, z);
|
|
3173
|
-
controlsRef.current.update();
|
|
3174
|
-
}
|
|
3175
|
-
},
|
|
3176
|
-
resetCamera: () => {
|
|
3177
|
-
if (controlsRef.current) {
|
|
3178
|
-
controlsRef.current.reset();
|
|
3179
|
-
}
|
|
3180
|
-
},
|
|
3181
|
-
screenshot: () => {
|
|
3182
|
-
const canvas = containerRef.current?.querySelector("canvas");
|
|
3183
|
-
if (canvas) {
|
|
3184
|
-
return canvas.toDataURL("image/png");
|
|
3185
|
-
}
|
|
3186
|
-
return null;
|
|
3187
|
-
},
|
|
3188
|
-
export: () => ({
|
|
3189
|
-
tiles,
|
|
3190
|
-
units,
|
|
3191
|
-
features
|
|
3192
|
-
})
|
|
3193
|
-
}));
|
|
3194
|
-
const handleTileClick = useCallback(
|
|
3195
|
-
(tile, event) => {
|
|
3196
|
-
eventHandlers.handleTileClick(tile, event);
|
|
3197
|
-
},
|
|
3198
|
-
[eventHandlers]
|
|
3199
|
-
);
|
|
3200
|
-
const handleUnitClick = useCallback(
|
|
3201
|
-
(unit, event) => {
|
|
3202
|
-
eventHandlers.handleUnitClick(unit, event);
|
|
3203
|
-
},
|
|
3204
|
-
[eventHandlers]
|
|
3205
|
-
);
|
|
3206
|
-
const handleFeatureClick = useCallback(
|
|
3207
|
-
(feature, event) => {
|
|
3208
|
-
if (event) {
|
|
3209
|
-
eventHandlers.handleFeatureClick(feature, event);
|
|
3210
|
-
}
|
|
3211
|
-
},
|
|
3212
|
-
[eventHandlers]
|
|
3213
|
-
);
|
|
3214
|
-
const handleTileHover = useCallback(
|
|
3215
|
-
(tile, event) => {
|
|
3216
|
-
setHoveredTile(tile);
|
|
3217
|
-
if (event) {
|
|
3218
|
-
eventHandlers.handleTileHover(tile, event);
|
|
3219
|
-
}
|
|
3220
|
-
},
|
|
3221
|
-
[eventHandlers]
|
|
3222
|
-
);
|
|
3223
|
-
const cameraConfig = useMemo(() => {
|
|
3224
|
-
const size = Math.max(
|
|
3225
|
-
gridBounds.maxX - gridBounds.minX,
|
|
3226
|
-
gridBounds.maxZ - gridBounds.minZ
|
|
3227
|
-
);
|
|
3228
|
-
const distance = size * 1.5;
|
|
3229
|
-
switch (cameraMode) {
|
|
3230
|
-
case "isometric":
|
|
3231
|
-
return {
|
|
3232
|
-
position: [distance, distance * 0.8, distance],
|
|
3233
|
-
fov: 45
|
|
3234
|
-
};
|
|
3235
|
-
case "top-down":
|
|
3236
|
-
return {
|
|
3237
|
-
position: [0, distance * 2, 0],
|
|
3238
|
-
fov: 45
|
|
3239
|
-
};
|
|
3240
|
-
case "perspective":
|
|
3241
|
-
default:
|
|
3242
|
-
return {
|
|
3243
|
-
position: [distance, distance, distance],
|
|
3244
|
-
fov: 45
|
|
3245
|
-
};
|
|
3246
|
-
}
|
|
3247
|
-
}, [cameraMode, gridBounds]);
|
|
3248
|
-
const DefaultTileRenderer = useCallback(
|
|
3249
|
-
({ tile, position }) => {
|
|
3250
|
-
const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
|
|
3251
|
-
const isHovered = hoveredTile?.id === tile.id;
|
|
3252
|
-
const isValidMove = validMoves.some(
|
|
3253
|
-
(m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
|
|
3254
|
-
);
|
|
3255
|
-
const isAttackTarget = attackTargets.some(
|
|
3256
|
-
(m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
|
|
3257
|
-
);
|
|
3258
|
-
let color = 8421504;
|
|
3259
|
-
if (tile.type === "water") color = 4491468;
|
|
3260
|
-
else if (tile.type === "grass") color = 4500036;
|
|
3261
|
-
else if (tile.type === "sand") color = 14535816;
|
|
3262
|
-
else if (tile.type === "rock") color = 8947848;
|
|
3263
|
-
else if (tile.type === "snow") color = 15658734;
|
|
3264
|
-
let emissive = 0;
|
|
3265
|
-
if (isSelected) emissive = 4473924;
|
|
3266
|
-
else if (isAttackTarget) emissive = 4456448;
|
|
3267
|
-
else if (isValidMove) emissive = 17408;
|
|
3268
|
-
else if (isHovered) emissive = 2236962;
|
|
3269
|
-
return /* @__PURE__ */ jsxs(
|
|
3270
|
-
"mesh",
|
|
3271
|
-
{
|
|
3272
|
-
position,
|
|
3273
|
-
onClick: (e) => handleTileClick(tile, e),
|
|
3274
|
-
onPointerEnter: (e) => handleTileHover(tile, e),
|
|
3275
|
-
onPointerLeave: (e) => handleTileHover(null, e),
|
|
3276
|
-
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
3277
|
-
children: [
|
|
3278
|
-
/* @__PURE__ */ jsx("boxGeometry", { args: [0.95, 0.2, 0.95] }),
|
|
3279
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color, emissive })
|
|
3280
|
-
]
|
|
3281
|
-
}
|
|
3282
|
-
);
|
|
3283
|
-
},
|
|
3284
|
-
[selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
|
|
3285
|
-
);
|
|
3286
|
-
const DefaultUnitRenderer = useCallback(
|
|
3287
|
-
({ unit, position }) => {
|
|
3288
|
-
const isSelected = selectedUnitId === unit.id;
|
|
3289
|
-
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
3290
|
-
return /* @__PURE__ */ jsxs(
|
|
3291
|
-
"group",
|
|
3292
|
-
{
|
|
3293
|
-
position,
|
|
3294
|
-
onClick: (e) => handleUnitClick(unit, e),
|
|
3295
|
-
userData: { type: "unit", unitId: unit.id },
|
|
3296
|
-
children: [
|
|
3297
|
-
isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.05, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
3298
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
|
|
3299
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
|
|
3300
|
-
] }),
|
|
3301
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
|
|
3302
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
|
|
3303
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
3304
|
-
] }),
|
|
3305
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
|
|
3306
|
-
/* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
|
|
3307
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
3308
|
-
] }),
|
|
3309
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
|
|
3310
|
-
/* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
|
|
3311
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
3312
|
-
] }),
|
|
3313
|
-
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxs("group", { position: [0, 1.2, 0], children: [
|
|
3314
|
-
/* @__PURE__ */ jsxs("mesh", { position: [-0.25, 0, 0], children: [
|
|
3315
|
-
/* @__PURE__ */ jsx("planeGeometry", { args: [0.5, 0.05] }),
|
|
3316
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: 3355443 })
|
|
3317
|
-
] }),
|
|
3318
|
-
/* @__PURE__ */ jsxs(
|
|
3319
|
-
"mesh",
|
|
3320
|
-
{
|
|
3321
|
-
position: [
|
|
3322
|
-
-0.25 + 0.5 * (unit.health / unit.maxHealth) / 2,
|
|
3323
|
-
0,
|
|
3324
|
-
0.01
|
|
3325
|
-
],
|
|
3326
|
-
children: [
|
|
3327
|
-
/* @__PURE__ */ jsx("planeGeometry", { args: [0.5 * (unit.health / unit.maxHealth), 0.05] }),
|
|
3328
|
-
/* @__PURE__ */ jsx(
|
|
3329
|
-
"meshBasicMaterial",
|
|
3330
|
-
{
|
|
3331
|
-
color: unit.health / unit.maxHealth > 0.5 ? 4500036 : unit.health / unit.maxHealth > 0.25 ? 11184708 : 16729156
|
|
3332
|
-
}
|
|
3333
|
-
)
|
|
3334
|
-
]
|
|
3335
|
-
}
|
|
3336
|
-
)
|
|
3337
|
-
] })
|
|
3338
|
-
]
|
|
3339
|
-
}
|
|
3340
|
-
);
|
|
3341
|
-
},
|
|
3342
|
-
[selectedUnitId, handleUnitClick]
|
|
3343
|
-
);
|
|
3344
|
-
const DefaultFeatureRenderer = useCallback(
|
|
3345
|
-
({
|
|
3346
|
-
feature,
|
|
3347
|
-
position
|
|
3348
|
-
}) => {
|
|
3349
|
-
if (feature.assetUrl) {
|
|
3350
|
-
return /* @__PURE__ */ jsx(
|
|
3351
|
-
ModelLoader,
|
|
3352
|
-
{
|
|
3353
|
-
url: feature.assetUrl,
|
|
3354
|
-
position,
|
|
3355
|
-
scale: 0.5,
|
|
3356
|
-
rotation: [0, feature.rotation ?? 0, 0],
|
|
3357
|
-
onClick: () => handleFeatureClick(feature, null),
|
|
3358
|
-
fallbackGeometry: "box"
|
|
3359
|
-
},
|
|
3360
|
-
feature.id
|
|
3361
|
-
);
|
|
3362
|
-
}
|
|
3363
|
-
if (feature.type === "tree") {
|
|
3364
|
-
return /* @__PURE__ */ jsxs(
|
|
3365
|
-
"group",
|
|
3366
|
-
{
|
|
3367
|
-
position,
|
|
3368
|
-
onClick: (e) => handleFeatureClick(feature, e),
|
|
3369
|
-
userData: { type: "feature", featureId: feature.id },
|
|
3370
|
-
children: [
|
|
3371
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.4, 0], children: [
|
|
3372
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.1, 0.15, 0.8, 6] }),
|
|
3373
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 9127187 })
|
|
3374
|
-
] }),
|
|
3375
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
|
|
3376
|
-
/* @__PURE__ */ jsx("coneGeometry", { args: [0.5, 0.8, 8] }),
|
|
3377
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 2263842 })
|
|
3378
|
-
] })
|
|
3379
|
-
]
|
|
3380
|
-
}
|
|
3381
|
-
);
|
|
3382
|
-
}
|
|
3383
|
-
if (feature.type === "rock") {
|
|
3384
|
-
return /* @__PURE__ */ jsxs(
|
|
3385
|
-
"mesh",
|
|
3386
|
-
{
|
|
3387
|
-
position: [position[0], position[1] + 0.3, position[2]],
|
|
3388
|
-
onClick: (e) => handleFeatureClick(feature, e),
|
|
3389
|
-
userData: { type: "feature", featureId: feature.id },
|
|
3390
|
-
children: [
|
|
3391
|
-
/* @__PURE__ */ jsx("dodecahedronGeometry", { args: [0.3, 0] }),
|
|
3392
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 8421504 })
|
|
3393
|
-
]
|
|
3394
|
-
}
|
|
3395
|
-
);
|
|
3396
|
-
}
|
|
3397
|
-
return null;
|
|
3398
|
-
},
|
|
3399
|
-
[handleFeatureClick]
|
|
3400
|
-
);
|
|
3401
|
-
if (externalLoading || assetsLoading && preloadAssets.length > 0) {
|
|
3402
|
-
return /* @__PURE__ */ jsx(
|
|
3403
|
-
Canvas3DLoadingState,
|
|
3404
|
-
{
|
|
3405
|
-
progress,
|
|
3406
|
-
loaded,
|
|
3407
|
-
total,
|
|
3408
|
-
message: loadingMessage,
|
|
3409
|
-
className
|
|
3410
|
-
}
|
|
3411
|
-
);
|
|
3412
|
-
}
|
|
3413
|
-
const displayError = externalError || internalError;
|
|
3414
|
-
if (displayError) {
|
|
3415
|
-
return /* @__PURE__ */ jsx(Canvas3DErrorBoundary, { children: /* @__PURE__ */ jsx("div", { className: "game-canvas-3d game-canvas-3d--error", children: /* @__PURE__ */ jsxs("div", { className: "game-canvas-3d__error", children: [
|
|
3416
|
-
"Error: ",
|
|
3417
|
-
displayError
|
|
3418
|
-
] }) }) });
|
|
3419
|
-
}
|
|
3420
|
-
return /* @__PURE__ */ jsx(
|
|
3421
|
-
Canvas3DErrorBoundary,
|
|
3422
|
-
{
|
|
3423
|
-
onError: (err) => setInternalError(err.message),
|
|
3424
|
-
onReset: () => setInternalError(null),
|
|
3425
|
-
children: /* @__PURE__ */ jsxs(
|
|
3426
|
-
"div",
|
|
3427
|
-
{
|
|
3428
|
-
ref: containerRef,
|
|
3429
|
-
className: `game-canvas-3d ${className || ""}`,
|
|
3430
|
-
"data-orientation": orientation,
|
|
3431
|
-
"data-camera-mode": cameraMode,
|
|
3432
|
-
"data-overlay": overlay,
|
|
3433
|
-
children: [
|
|
3434
|
-
/* @__PURE__ */ jsxs(
|
|
3435
|
-
Canvas,
|
|
3436
|
-
{
|
|
3437
|
-
shadows,
|
|
3438
|
-
camera: {
|
|
3439
|
-
position: cameraConfig.position,
|
|
3440
|
-
fov: cameraConfig.fov,
|
|
3441
|
-
near: 0.1,
|
|
3442
|
-
far: 1e3
|
|
3443
|
-
},
|
|
3444
|
-
style: { background: backgroundColor },
|
|
3445
|
-
onClick: (e) => {
|
|
3446
|
-
if (e.target === e.currentTarget) {
|
|
3447
|
-
eventHandlers.handleCanvasClick(e);
|
|
3448
|
-
}
|
|
3449
|
-
},
|
|
3450
|
-
children: [
|
|
3451
|
-
/* @__PURE__ */ jsx(CameraController, { onCameraChange: eventHandlers.handleCameraChange }),
|
|
3452
|
-
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.6 }),
|
|
3453
|
-
/* @__PURE__ */ jsx(
|
|
3454
|
-
"directionalLight",
|
|
3455
|
-
{
|
|
3456
|
-
position: [10, 20, 10],
|
|
3457
|
-
intensity: 0.8,
|
|
3458
|
-
castShadow: shadows,
|
|
3459
|
-
"shadow-mapSize": [2048, 2048]
|
|
3460
|
-
}
|
|
3461
|
-
),
|
|
3462
|
-
/* @__PURE__ */ jsx("hemisphereLight", { intensity: 0.3, color: "#87ceeb", groundColor: "#362d1d" }),
|
|
3463
|
-
showGrid && /* @__PURE__ */ jsx(
|
|
3464
|
-
Grid,
|
|
3465
|
-
{
|
|
3466
|
-
args: [
|
|
3467
|
-
Math.max(gridBounds.maxX - gridBounds.minX + 2, 10),
|
|
3468
|
-
Math.max(gridBounds.maxZ - gridBounds.minZ + 2, 10)
|
|
3469
|
-
],
|
|
3470
|
-
position: [
|
|
3471
|
-
(gridBounds.maxX - gridBounds.minX) / 2 - 0.5,
|
|
3472
|
-
0,
|
|
3473
|
-
(gridBounds.maxZ - gridBounds.minZ) / 2 - 0.5
|
|
3474
|
-
],
|
|
3475
|
-
cellSize: 1,
|
|
3476
|
-
cellThickness: 1,
|
|
3477
|
-
cellColor: "#444444",
|
|
3478
|
-
sectionSize: 5,
|
|
3479
|
-
sectionThickness: 1.5,
|
|
3480
|
-
sectionColor: "#666666",
|
|
3481
|
-
fadeDistance: 50,
|
|
3482
|
-
fadeStrength: 1
|
|
3483
|
-
}
|
|
3484
|
-
),
|
|
3485
|
-
tiles.map((tile, index) => {
|
|
3486
|
-
const position = gridToWorld(
|
|
3487
|
-
tile.x,
|
|
3488
|
-
tile.z ?? tile.y ?? 0,
|
|
3489
|
-
tile.elevation ?? 0
|
|
3490
|
-
);
|
|
3491
|
-
const Renderer = CustomTileRenderer || DefaultTileRenderer;
|
|
3492
|
-
return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
|
|
3493
|
-
}),
|
|
3494
|
-
features.map((feature, index) => {
|
|
3495
|
-
const position = gridToWorld(
|
|
3496
|
-
feature.x,
|
|
3497
|
-
feature.z ?? feature.y ?? 0,
|
|
3498
|
-
(feature.elevation ?? 0) + 0.5
|
|
3499
|
-
);
|
|
3500
|
-
const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
|
|
3501
|
-
return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
|
|
3502
|
-
}),
|
|
3503
|
-
units.map((unit) => {
|
|
3504
|
-
const position = gridToWorld(
|
|
3505
|
-
unit.x ?? 0,
|
|
3506
|
-
unit.z ?? unit.y ?? 0,
|
|
3507
|
-
(unit.elevation ?? 0) + 0.5
|
|
3508
|
-
);
|
|
3509
|
-
const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
|
|
3510
|
-
return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
|
|
3511
|
-
}),
|
|
3512
|
-
children,
|
|
3513
|
-
/* @__PURE__ */ jsx(
|
|
3514
|
-
OrbitControls,
|
|
3515
|
-
{
|
|
3516
|
-
ref: controlsRef,
|
|
3517
|
-
target: cameraTarget,
|
|
3518
|
-
enableDamping: true,
|
|
3519
|
-
dampingFactor: 0.05,
|
|
3520
|
-
minDistance: 2,
|
|
3521
|
-
maxDistance: 100,
|
|
3522
|
-
maxPolarAngle: Math.PI / 2 - 0.1
|
|
3523
|
-
}
|
|
3524
|
-
)
|
|
3525
|
-
]
|
|
3526
|
-
}
|
|
3527
|
-
),
|
|
3528
|
-
showCoordinates && hoveredTile && /* @__PURE__ */ jsxs("div", { className: "game-canvas-3d__coordinates", children: [
|
|
3529
|
-
"X: ",
|
|
3530
|
-
hoveredTile.x,
|
|
3531
|
-
", Z: ",
|
|
3532
|
-
hoveredTile.z ?? hoveredTile.y ?? 0
|
|
3533
|
-
] }),
|
|
3534
|
-
showTileInfo && hoveredTile && /* @__PURE__ */ jsxs("div", { className: "game-canvas-3d__tile-info", children: [
|
|
3535
|
-
/* @__PURE__ */ jsx("div", { className: "tile-info__type", children: hoveredTile.type }),
|
|
3536
|
-
hoveredTile.terrain && /* @__PURE__ */ jsx("div", { className: "tile-info__terrain", children: hoveredTile.terrain })
|
|
3537
|
-
] })
|
|
3538
|
-
]
|
|
3539
|
-
}
|
|
3540
|
-
)
|
|
3541
|
-
}
|
|
3542
|
-
);
|
|
3543
|
-
}
|
|
3544
|
-
);
|
|
3545
|
-
GameCanvas3D.displayName = "GameCanvas3D";
|
|
3546
2149
|
|
|
3547
2150
|
// lib/traitRegistry.ts
|
|
3548
2151
|
var traits = /* @__PURE__ */ new Map();
|
|
@@ -3566,6 +2169,35 @@ function unregisterTrait(id) {
|
|
|
3566
2169
|
traits.delete(id);
|
|
3567
2170
|
notifyListeners2();
|
|
3568
2171
|
}
|
|
2172
|
+
|
|
2173
|
+
// components/organisms/component-registry.generated.ts
|
|
2174
|
+
function lazyThree(name, loader) {
|
|
2175
|
+
const Lazy = React110__default.lazy(() => loader().then((m) => ({ default: m[name] })));
|
|
2176
|
+
function ThreeWrapper(props) {
|
|
2177
|
+
return React110__default.createElement(
|
|
2178
|
+
React110__default.Suspense,
|
|
2179
|
+
{ fallback: null },
|
|
2180
|
+
React110__default.createElement(Lazy, props)
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
ThreeWrapper.displayName = `Lazy(${name})`;
|
|
2184
|
+
return ThreeWrapper;
|
|
2185
|
+
}
|
|
2186
|
+
lazyThree("Camera3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2187
|
+
lazyThree("Canvas3DErrorBoundary", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2188
|
+
lazyThree("Canvas3DLoadingState", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2189
|
+
lazyThree("FeatureRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2190
|
+
lazyThree("FeatureRenderer3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2191
|
+
lazyThree("GameCanvas3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2192
|
+
lazyThree("GameCanvas3DBattleTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2193
|
+
lazyThree("GameCanvas3DCastleTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2194
|
+
lazyThree("GameCanvas3DWorldMapTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2195
|
+
lazyThree("Lighting3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2196
|
+
lazyThree("ModelLoader", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2197
|
+
lazyThree("PhysicsObject3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2198
|
+
lazyThree("Scene3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2199
|
+
lazyThree("TileRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
2200
|
+
lazyThree("UnitRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3569
2201
|
createContext({ enabled: false });
|
|
3570
2202
|
createContext(false);
|
|
3571
2203
|
createContext(null);
|