@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/providers/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 'react-dom';
|
|
5
5
|
import '@almadar/ui/context';
|
|
@@ -19,12 +19,6 @@ import remarkMath from 'remark-math';
|
|
|
19
19
|
import rehypeKatex from 'rehype-katex';
|
|
20
20
|
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism';
|
|
21
21
|
import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus';
|
|
22
|
-
import { useThree, useFrame, Canvas } from '@react-three/fiber';
|
|
23
|
-
import { OrbitControls, Grid } from '@react-three/drei';
|
|
24
|
-
import * as THREE from 'three';
|
|
25
|
-
import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
26
|
-
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
27
|
-
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
|
|
28
22
|
|
|
29
23
|
var __defProp = Object.defineProperty;
|
|
30
24
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -334,15 +328,6 @@ function useEventBus() {
|
|
|
334
328
|
const context = useContext(EventBusContext);
|
|
335
329
|
return context ?? getGlobalEventBus() ?? fallbackEventBus;
|
|
336
330
|
}
|
|
337
|
-
function useEmitEvent() {
|
|
338
|
-
const eventBus = useEventBus();
|
|
339
|
-
return useCallback(
|
|
340
|
-
(type, payload) => {
|
|
341
|
-
eventBus.emit(type, payload);
|
|
342
|
-
},
|
|
343
|
-
[eventBus]
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
331
|
var EventBusContext = createContext(null);
|
|
347
332
|
function EventBusProvider({ children, debug: debug2 = false }) {
|
|
348
333
|
const listenersRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -708,7 +693,7 @@ function EntityDataProvider({
|
|
|
708
693
|
adapter,
|
|
709
694
|
children
|
|
710
695
|
}) {
|
|
711
|
-
return
|
|
696
|
+
return React110__default.createElement(
|
|
712
697
|
EntityDataContext.Provider,
|
|
713
698
|
{ value: adapter },
|
|
714
699
|
children
|
|
@@ -854,7 +839,7 @@ var positionStyles = {
|
|
|
854
839
|
fixed: "fixed",
|
|
855
840
|
sticky: "sticky"
|
|
856
841
|
};
|
|
857
|
-
var Box =
|
|
842
|
+
var Box = React110__default.forwardRef(
|
|
858
843
|
({
|
|
859
844
|
padding,
|
|
860
845
|
paddingX,
|
|
@@ -873,7 +858,7 @@ var Box = React113__default.forwardRef(
|
|
|
873
858
|
position,
|
|
874
859
|
className,
|
|
875
860
|
children,
|
|
876
|
-
as:
|
|
861
|
+
as: Component = "div",
|
|
877
862
|
action,
|
|
878
863
|
actionPayload,
|
|
879
864
|
hoverEvent,
|
|
@@ -903,7 +888,7 @@ var Box = React113__default.forwardRef(
|
|
|
903
888
|
onMouseLeave?.(e);
|
|
904
889
|
}, [hoverEvent, eventBus, onMouseLeave]);
|
|
905
890
|
const isClickable = action || onClick;
|
|
906
|
-
const Comp =
|
|
891
|
+
const Comp = Component;
|
|
907
892
|
return /* @__PURE__ */ jsx(
|
|
908
893
|
Comp,
|
|
909
894
|
{
|
|
@@ -1033,8 +1018,8 @@ var Typography = ({
|
|
|
1033
1018
|
children
|
|
1034
1019
|
}) => {
|
|
1035
1020
|
const variant = variantProp ?? (level ? `h${level}` : "body1");
|
|
1036
|
-
const
|
|
1037
|
-
const Comp =
|
|
1021
|
+
const Component = as || defaultElements[variant];
|
|
1022
|
+
const Comp = Component;
|
|
1038
1023
|
return /* @__PURE__ */ jsx(
|
|
1039
1024
|
Comp,
|
|
1040
1025
|
{
|
|
@@ -1124,7 +1109,7 @@ function resolveIconProp(value, sizeClass) {
|
|
|
1124
1109
|
const IconComp = value;
|
|
1125
1110
|
return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
|
|
1126
1111
|
}
|
|
1127
|
-
if (
|
|
1112
|
+
if (React110__default.isValidElement(value)) {
|
|
1128
1113
|
return value;
|
|
1129
1114
|
}
|
|
1130
1115
|
if (typeof value === "object" && value !== null && "render" in value) {
|
|
@@ -1133,7 +1118,7 @@ function resolveIconProp(value, sizeClass) {
|
|
|
1133
1118
|
}
|
|
1134
1119
|
return value;
|
|
1135
1120
|
}
|
|
1136
|
-
var Button =
|
|
1121
|
+
var Button = React110__default.forwardRef(
|
|
1137
1122
|
({
|
|
1138
1123
|
className,
|
|
1139
1124
|
variant = "primary",
|
|
@@ -1228,7 +1213,7 @@ var sizeStyles3 = {
|
|
|
1228
1213
|
md: "px-2.5 py-1 text-sm",
|
|
1229
1214
|
lg: "px-3 py-1.5 text-base"
|
|
1230
1215
|
};
|
|
1231
|
-
var Badge =
|
|
1216
|
+
var Badge = React110__default.forwardRef(
|
|
1232
1217
|
({ className, variant = "default", size = "sm", amount, label, icon, children, ...props }, ref) => {
|
|
1233
1218
|
const iconSizes2 = { sm: "w-3 h-3", md: "w-3.5 h-3.5", lg: "w-4 h-4" };
|
|
1234
1219
|
const resolvedIcon = typeof icon === "string" ? (() => {
|
|
@@ -1255,7 +1240,7 @@ var Badge = React113__default.forwardRef(
|
|
|
1255
1240
|
}
|
|
1256
1241
|
);
|
|
1257
1242
|
Badge.displayName = "Badge";
|
|
1258
|
-
var Input =
|
|
1243
|
+
var Input = React110__default.forwardRef(
|
|
1259
1244
|
({
|
|
1260
1245
|
className,
|
|
1261
1246
|
inputType,
|
|
@@ -1367,7 +1352,7 @@ var Input = React113__default.forwardRef(
|
|
|
1367
1352
|
}
|
|
1368
1353
|
);
|
|
1369
1354
|
Input.displayName = "Input";
|
|
1370
|
-
var Label =
|
|
1355
|
+
var Label = React110__default.forwardRef(
|
|
1371
1356
|
({ className, required, children, ...props }, ref) => {
|
|
1372
1357
|
return /* @__PURE__ */ jsxs(
|
|
1373
1358
|
"label",
|
|
@@ -1387,7 +1372,7 @@ var Label = React113__default.forwardRef(
|
|
|
1387
1372
|
}
|
|
1388
1373
|
);
|
|
1389
1374
|
Label.displayName = "Label";
|
|
1390
|
-
var Textarea =
|
|
1375
|
+
var Textarea = React110__default.forwardRef(
|
|
1391
1376
|
({ className, error, ...props }, ref) => {
|
|
1392
1377
|
return /* @__PURE__ */ jsx(
|
|
1393
1378
|
"textarea",
|
|
@@ -1410,7 +1395,7 @@ var Textarea = React113__default.forwardRef(
|
|
|
1410
1395
|
}
|
|
1411
1396
|
);
|
|
1412
1397
|
Textarea.displayName = "Textarea";
|
|
1413
|
-
var Select =
|
|
1398
|
+
var Select = React110__default.forwardRef(
|
|
1414
1399
|
({ className, options, placeholder, error, ...props }, ref) => {
|
|
1415
1400
|
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
1416
1401
|
/* @__PURE__ */ jsxs(
|
|
@@ -1446,7 +1431,7 @@ var Select = React113__default.forwardRef(
|
|
|
1446
1431
|
}
|
|
1447
1432
|
);
|
|
1448
1433
|
Select.displayName = "Select";
|
|
1449
|
-
var Checkbox =
|
|
1434
|
+
var Checkbox = React110__default.forwardRef(
|
|
1450
1435
|
({ className, label, id, ...props }, ref) => {
|
|
1451
1436
|
const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
1452
1437
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
@@ -1520,7 +1505,7 @@ var shadowStyles2 = {
|
|
|
1520
1505
|
md: "shadow-[var(--shadow-main)]",
|
|
1521
1506
|
lg: "shadow-[var(--shadow-lg)]"
|
|
1522
1507
|
};
|
|
1523
|
-
var Card =
|
|
1508
|
+
var Card = React110__default.forwardRef(
|
|
1524
1509
|
({
|
|
1525
1510
|
className,
|
|
1526
1511
|
variant = "bordered",
|
|
@@ -1556,9 +1541,9 @@ var Card = React113__default.forwardRef(
|
|
|
1556
1541
|
}
|
|
1557
1542
|
);
|
|
1558
1543
|
Card.displayName = "Card";
|
|
1559
|
-
var CardHeader =
|
|
1544
|
+
var CardHeader = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
|
|
1560
1545
|
CardHeader.displayName = "CardHeader";
|
|
1561
|
-
var CardTitle =
|
|
1546
|
+
var CardTitle = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1562
1547
|
"h3",
|
|
1563
1548
|
{
|
|
1564
1549
|
ref,
|
|
@@ -1571,11 +1556,11 @@ var CardTitle = React113__default.forwardRef(({ className, ...props }, ref) => /
|
|
|
1571
1556
|
}
|
|
1572
1557
|
));
|
|
1573
1558
|
CardTitle.displayName = "CardTitle";
|
|
1574
|
-
var CardContent =
|
|
1559
|
+
var CardContent = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
|
|
1575
1560
|
CardContent.displayName = "CardContent";
|
|
1576
1561
|
var CardBody = CardContent;
|
|
1577
1562
|
CardBody.displayName = "CardBody";
|
|
1578
|
-
var CardFooter =
|
|
1563
|
+
var CardFooter = React110__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1579
1564
|
"div",
|
|
1580
1565
|
{
|
|
1581
1566
|
ref,
|
|
@@ -1590,7 +1575,7 @@ var sizeStyles4 = {
|
|
|
1590
1575
|
md: "h-6 w-6",
|
|
1591
1576
|
lg: "h-8 w-8"
|
|
1592
1577
|
};
|
|
1593
|
-
var Spinner =
|
|
1578
|
+
var Spinner = React110__default.forwardRef(
|
|
1594
1579
|
({ className, size = "md", ...props }, ref) => {
|
|
1595
1580
|
return /* @__PURE__ */ jsx(
|
|
1596
1581
|
"div",
|
|
@@ -1604,7 +1589,7 @@ var Spinner = React113__default.forwardRef(
|
|
|
1604
1589
|
}
|
|
1605
1590
|
);
|
|
1606
1591
|
Spinner.displayName = "Spinner";
|
|
1607
|
-
var Radio =
|
|
1592
|
+
var Radio = React110__default.forwardRef(
|
|
1608
1593
|
({
|
|
1609
1594
|
label,
|
|
1610
1595
|
helperText,
|
|
@@ -1708,7 +1693,7 @@ var Radio = React113__default.forwardRef(
|
|
|
1708
1693
|
}
|
|
1709
1694
|
);
|
|
1710
1695
|
Radio.displayName = "Radio";
|
|
1711
|
-
var Switch =
|
|
1696
|
+
var Switch = React110.forwardRef(
|
|
1712
1697
|
({
|
|
1713
1698
|
checked,
|
|
1714
1699
|
defaultChecked = false,
|
|
@@ -1719,10 +1704,10 @@ var Switch = React113.forwardRef(
|
|
|
1719
1704
|
name,
|
|
1720
1705
|
className
|
|
1721
1706
|
}, ref) => {
|
|
1722
|
-
const [isChecked, setIsChecked] =
|
|
1707
|
+
const [isChecked, setIsChecked] = React110.useState(
|
|
1723
1708
|
checked !== void 0 ? checked : defaultChecked
|
|
1724
1709
|
);
|
|
1725
|
-
|
|
1710
|
+
React110.useEffect(() => {
|
|
1726
1711
|
if (checked !== void 0) {
|
|
1727
1712
|
setIsChecked(checked);
|
|
1728
1713
|
}
|
|
@@ -1816,7 +1801,7 @@ var Stack = ({
|
|
|
1816
1801
|
className,
|
|
1817
1802
|
style,
|
|
1818
1803
|
children,
|
|
1819
|
-
as:
|
|
1804
|
+
as: Component = "div",
|
|
1820
1805
|
onClick,
|
|
1821
1806
|
onKeyDown,
|
|
1822
1807
|
role,
|
|
@@ -1834,7 +1819,7 @@ var Stack = ({
|
|
|
1834
1819
|
};
|
|
1835
1820
|
const isHorizontal = direction === "horizontal";
|
|
1836
1821
|
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";
|
|
1837
|
-
const Comp =
|
|
1822
|
+
const Comp = Component;
|
|
1838
1823
|
return /* @__PURE__ */ jsx(
|
|
1839
1824
|
Comp,
|
|
1840
1825
|
{
|
|
@@ -1880,7 +1865,7 @@ var sizeStyles5 = {
|
|
|
1880
1865
|
md: "w-2.5 h-2.5",
|
|
1881
1866
|
lg: "w-3 h-3"
|
|
1882
1867
|
};
|
|
1883
|
-
var StatusDot =
|
|
1868
|
+
var StatusDot = React110__default.forwardRef(
|
|
1884
1869
|
({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
|
|
1885
1870
|
return /* @__PURE__ */ jsx(
|
|
1886
1871
|
"span",
|
|
@@ -1927,7 +1912,7 @@ var iconMap2 = {
|
|
|
1927
1912
|
down: TrendingDown,
|
|
1928
1913
|
flat: ArrowRight
|
|
1929
1914
|
};
|
|
1930
|
-
var TrendIndicator =
|
|
1915
|
+
var TrendIndicator = React110__default.forwardRef(
|
|
1931
1916
|
({
|
|
1932
1917
|
className,
|
|
1933
1918
|
value,
|
|
@@ -1986,7 +1971,7 @@ var thumbSizes = {
|
|
|
1986
1971
|
md: "w-4 h-4",
|
|
1987
1972
|
lg: "w-5 h-5"
|
|
1988
1973
|
};
|
|
1989
|
-
var RangeSlider =
|
|
1974
|
+
var RangeSlider = React110__default.forwardRef(
|
|
1990
1975
|
({
|
|
1991
1976
|
className,
|
|
1992
1977
|
min = 0,
|
|
@@ -2189,7 +2174,7 @@ var paddingClasses = {
|
|
|
2189
2174
|
md: "py-16",
|
|
2190
2175
|
lg: "py-24"
|
|
2191
2176
|
};
|
|
2192
|
-
var ContentSection =
|
|
2177
|
+
var ContentSection = React110__default.forwardRef(
|
|
2193
2178
|
({ children, background = "default", padding = "lg", id, className }, ref) => {
|
|
2194
2179
|
return /* @__PURE__ */ jsx(
|
|
2195
2180
|
Box,
|
|
@@ -2363,7 +2348,7 @@ var ErrorState = ({
|
|
|
2363
2348
|
);
|
|
2364
2349
|
};
|
|
2365
2350
|
ErrorState.displayName = "ErrorState";
|
|
2366
|
-
var ErrorBoundary = class extends
|
|
2351
|
+
var ErrorBoundary = class extends React110__default.Component {
|
|
2367
2352
|
constructor(props) {
|
|
2368
2353
|
super(props);
|
|
2369
2354
|
__publicField(this, "reset", () => {
|
|
@@ -2943,7 +2928,7 @@ function bindTraitStateGetter(getter) {
|
|
|
2943
2928
|
}
|
|
2944
2929
|
}
|
|
2945
2930
|
exposeOnWindow();
|
|
2946
|
-
var MarkdownContent =
|
|
2931
|
+
var MarkdownContent = React110__default.memo(
|
|
2947
2932
|
({ content, direction, className }) => {
|
|
2948
2933
|
const { t: _t } = useTranslate();
|
|
2949
2934
|
return /* @__PURE__ */ jsx(
|
|
@@ -3044,7 +3029,7 @@ var MarkdownContent = React113__default.memo(
|
|
|
3044
3029
|
(prev, next) => prev.content === next.content && prev.className === next.className && prev.direction === next.direction
|
|
3045
3030
|
);
|
|
3046
3031
|
MarkdownContent.displayName = "MarkdownContent";
|
|
3047
|
-
var CodeBlock =
|
|
3032
|
+
var CodeBlock = React110__default.memo(
|
|
3048
3033
|
({
|
|
3049
3034
|
code,
|
|
3050
3035
|
language = "text",
|
|
@@ -3151,1401 +3136,48 @@ var CodeBlock = React113__default.memo(
|
|
|
3151
3136
|
(prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight
|
|
3152
3137
|
);
|
|
3153
3138
|
CodeBlock.displayName = "CodeBlock";
|
|
3154
|
-
var Camera3D = forwardRef(
|
|
3155
|
-
({
|
|
3156
|
-
mode = "isometric",
|
|
3157
|
-
position = [10, 10, 10],
|
|
3158
|
-
target = [0, 0, 0],
|
|
3159
|
-
zoom = 1,
|
|
3160
|
-
fov = 45,
|
|
3161
|
-
enableOrbit = true,
|
|
3162
|
-
minDistance = 2,
|
|
3163
|
-
maxDistance = 100,
|
|
3164
|
-
onChange
|
|
3165
|
-
}, ref) => {
|
|
3166
|
-
const { camera, set, viewport } = useThree();
|
|
3167
|
-
const controlsRef = useRef(null);
|
|
3168
|
-
const initialPosition = useRef(new THREE.Vector3(...position));
|
|
3169
|
-
const initialTarget = useRef(new THREE.Vector3(...target));
|
|
3170
|
-
useEffect(() => {
|
|
3171
|
-
let newCamera;
|
|
3172
|
-
if (mode === "isometric") {
|
|
3173
|
-
const aspect = viewport.aspect;
|
|
3174
|
-
const size = 10 / zoom;
|
|
3175
|
-
newCamera = new THREE.OrthographicCamera(
|
|
3176
|
-
-size * aspect,
|
|
3177
|
-
size * aspect,
|
|
3178
|
-
size,
|
|
3179
|
-
-size,
|
|
3180
|
-
0.1,
|
|
3181
|
-
1e3
|
|
3182
|
-
);
|
|
3183
|
-
} else {
|
|
3184
|
-
newCamera = new THREE.PerspectiveCamera(fov, viewport.aspect, 0.1, 1e3);
|
|
3185
|
-
}
|
|
3186
|
-
newCamera.position.copy(initialPosition.current);
|
|
3187
|
-
newCamera.lookAt(initialTarget.current);
|
|
3188
|
-
set({ camera: newCamera });
|
|
3189
|
-
if (mode === "top-down") {
|
|
3190
|
-
newCamera.position.set(0, 20 / zoom, 0);
|
|
3191
|
-
newCamera.lookAt(0, 0, 0);
|
|
3192
|
-
}
|
|
3193
|
-
return () => {
|
|
3194
|
-
};
|
|
3195
|
-
}, [mode, fov, zoom, viewport.aspect, set]);
|
|
3196
|
-
useFrame(() => {
|
|
3197
|
-
if (onChange) {
|
|
3198
|
-
onChange(camera);
|
|
3199
|
-
}
|
|
3200
|
-
});
|
|
3201
|
-
useImperativeHandle(ref, () => ({
|
|
3202
|
-
getCamera: () => camera,
|
|
3203
|
-
setPosition: (x, y, z) => {
|
|
3204
|
-
camera.position.set(x, y, z);
|
|
3205
|
-
if (controlsRef.current) {
|
|
3206
|
-
controlsRef.current.update();
|
|
3207
|
-
}
|
|
3208
|
-
},
|
|
3209
|
-
lookAt: (x, y, z) => {
|
|
3210
|
-
camera.lookAt(x, y, z);
|
|
3211
|
-
if (controlsRef.current) {
|
|
3212
|
-
controlsRef.current.target.set(x, y, z);
|
|
3213
|
-
controlsRef.current.update();
|
|
3214
|
-
}
|
|
3215
|
-
},
|
|
3216
|
-
reset: () => {
|
|
3217
|
-
camera.position.copy(initialPosition.current);
|
|
3218
|
-
camera.lookAt(initialTarget.current);
|
|
3219
|
-
if (controlsRef.current) {
|
|
3220
|
-
controlsRef.current.target.copy(initialTarget.current);
|
|
3221
|
-
controlsRef.current.update();
|
|
3222
|
-
}
|
|
3223
|
-
},
|
|
3224
|
-
getViewBounds: () => {
|
|
3225
|
-
const min = new THREE.Vector3(-10, -10, -10);
|
|
3226
|
-
const max = new THREE.Vector3(10, 10, 10);
|
|
3227
|
-
return { min, max };
|
|
3228
|
-
}
|
|
3229
|
-
}));
|
|
3230
|
-
const maxPolarAngle = mode === "top-down" ? 0.1 : Math.PI / 2 - 0.1;
|
|
3231
|
-
return /* @__PURE__ */ jsx(
|
|
3232
|
-
OrbitControls,
|
|
3233
|
-
{
|
|
3234
|
-
ref: controlsRef,
|
|
3235
|
-
camera,
|
|
3236
|
-
enabled: enableOrbit,
|
|
3237
|
-
target: initialTarget.current,
|
|
3238
|
-
minDistance,
|
|
3239
|
-
maxDistance,
|
|
3240
|
-
maxPolarAngle,
|
|
3241
|
-
enableDamping: true,
|
|
3242
|
-
dampingFactor: 0.05
|
|
3243
|
-
}
|
|
3244
|
-
);
|
|
3245
|
-
}
|
|
3246
|
-
);
|
|
3247
|
-
Camera3D.displayName = "Camera3D";
|
|
3248
|
-
var Canvas3DErrorBoundary = class extends Component {
|
|
3249
|
-
constructor(props) {
|
|
3250
|
-
super(props);
|
|
3251
|
-
__publicField(this, "handleReset", () => {
|
|
3252
|
-
this.setState({
|
|
3253
|
-
hasError: false,
|
|
3254
|
-
error: null,
|
|
3255
|
-
errorInfo: null
|
|
3256
|
-
});
|
|
3257
|
-
this.props.onReset?.();
|
|
3258
|
-
});
|
|
3259
|
-
this.state = {
|
|
3260
|
-
hasError: false,
|
|
3261
|
-
error: null,
|
|
3262
|
-
errorInfo: null
|
|
3263
|
-
};
|
|
3264
|
-
}
|
|
3265
|
-
static getDerivedStateFromError(error) {
|
|
3266
|
-
return {
|
|
3267
|
-
hasError: true,
|
|
3268
|
-
error,
|
|
3269
|
-
errorInfo: null
|
|
3270
|
-
};
|
|
3271
|
-
}
|
|
3272
|
-
componentDidCatch(error, errorInfo) {
|
|
3273
|
-
this.setState({ errorInfo });
|
|
3274
|
-
this.props.onError?.(error, errorInfo);
|
|
3275
|
-
console.error("[Canvas3DErrorBoundary] Error caught:", error);
|
|
3276
|
-
console.error("[Canvas3DErrorBoundary] Component stack:", errorInfo.componentStack);
|
|
3277
|
-
}
|
|
3278
|
-
render() {
|
|
3279
|
-
if (this.state.hasError) {
|
|
3280
|
-
if (this.props.fallback) {
|
|
3281
|
-
return this.props.fallback;
|
|
3282
|
-
}
|
|
3283
|
-
return /* @__PURE__ */ jsx("div", { className: "canvas-3d-error", children: /* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__content", children: [
|
|
3284
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-error__icon", children: "\u26A0\uFE0F" }),
|
|
3285
|
-
/* @__PURE__ */ jsx("h2", { className: "canvas-3d-error__title", children: "3D Scene Error" }),
|
|
3286
|
-
/* @__PURE__ */ jsx("p", { className: "canvas-3d-error__message", children: "Something went wrong while rendering the 3D scene." }),
|
|
3287
|
-
this.state.error && /* @__PURE__ */ jsxs("details", { className: "canvas-3d-error__details", children: [
|
|
3288
|
-
/* @__PURE__ */ jsx("summary", { children: "Error Details" }),
|
|
3289
|
-
/* @__PURE__ */ jsxs("pre", { className: "error__stack", children: [
|
|
3290
|
-
this.state.error.message,
|
|
3291
|
-
"\n",
|
|
3292
|
-
this.state.error.stack
|
|
3293
|
-
] }),
|
|
3294
|
-
this.state.errorInfo && /* @__PURE__ */ jsx("pre", { className: "error__component-stack", children: this.state.errorInfo.componentStack })
|
|
3295
|
-
] }),
|
|
3296
|
-
/* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__actions", children: [
|
|
3297
|
-
/* @__PURE__ */ jsx(
|
|
3298
|
-
"button",
|
|
3299
|
-
{
|
|
3300
|
-
className: "error__button error__button--primary",
|
|
3301
|
-
onClick: this.handleReset,
|
|
3302
|
-
children: "Try Again"
|
|
3303
|
-
}
|
|
3304
|
-
),
|
|
3305
|
-
/* @__PURE__ */ jsx(
|
|
3306
|
-
"button",
|
|
3307
|
-
{
|
|
3308
|
-
className: "error__button error__button--secondary",
|
|
3309
|
-
onClick: () => window.location.reload(),
|
|
3310
|
-
children: "Reload Page"
|
|
3311
|
-
}
|
|
3312
|
-
)
|
|
3313
|
-
] })
|
|
3314
|
-
] }) });
|
|
3315
|
-
}
|
|
3316
|
-
return this.props.children;
|
|
3317
|
-
}
|
|
3318
|
-
};
|
|
3319
|
-
function Canvas3DLoadingState({
|
|
3320
|
-
progress = 0,
|
|
3321
|
-
loaded = 0,
|
|
3322
|
-
total = 0,
|
|
3323
|
-
message = "Loading 3D Scene...",
|
|
3324
|
-
details,
|
|
3325
|
-
showSpinner = true,
|
|
3326
|
-
className
|
|
3327
|
-
}) {
|
|
3328
|
-
const clampedProgress = Math.max(0, Math.min(100, progress));
|
|
3329
|
-
const hasProgress = total > 0;
|
|
3330
|
-
return /* @__PURE__ */ jsxs("div", { className: `canvas-3d-loading ${className || ""}`, children: [
|
|
3331
|
-
/* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__content", children: [
|
|
3332
|
-
showSpinner && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__spinner", children: [
|
|
3333
|
-
/* @__PURE__ */ jsx("div", { className: "spinner__ring" }),
|
|
3334
|
-
/* @__PURE__ */ jsx("div", { className: "spinner__ring spinner__ring--secondary" })
|
|
3335
|
-
] }),
|
|
3336
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__message", children: message }),
|
|
3337
|
-
details && /* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__details", children: details }),
|
|
3338
|
-
hasProgress && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__progress", children: [
|
|
3339
|
-
/* @__PURE__ */ jsx("div", { className: "progress__bar", children: /* @__PURE__ */ jsx(
|
|
3340
|
-
"div",
|
|
3341
|
-
{
|
|
3342
|
-
className: "progress__fill",
|
|
3343
|
-
style: { width: `${clampedProgress}%` }
|
|
3344
|
-
}
|
|
3345
|
-
) }),
|
|
3346
|
-
/* @__PURE__ */ jsxs("div", { className: "progress__text", children: [
|
|
3347
|
-
/* @__PURE__ */ jsxs("span", { className: "progress__percentage", children: [
|
|
3348
|
-
clampedProgress,
|
|
3349
|
-
"%"
|
|
3350
|
-
] }),
|
|
3351
|
-
/* @__PURE__ */ jsxs("span", { className: "progress__count", children: [
|
|
3352
|
-
"(",
|
|
3353
|
-
loaded,
|
|
3354
|
-
"/",
|
|
3355
|
-
total,
|
|
3356
|
-
")"
|
|
3357
|
-
] })
|
|
3358
|
-
] })
|
|
3359
|
-
] })
|
|
3360
|
-
] }),
|
|
3361
|
-
/* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__background", children: /* @__PURE__ */ jsx("div", { className: "bg__grid" }) })
|
|
3362
|
-
] });
|
|
3363
|
-
}
|
|
3364
3139
|
|
|
3365
3140
|
// lib/debug.ts
|
|
3366
3141
|
typeof window !== "undefined" && (localStorage.getItem("debug") === "true" || process.env.NODE_ENV === "development");
|
|
3367
3142
|
lazy(() => import('react-markdown'));
|
|
3368
3143
|
var GameAudioContext = createContext(null);
|
|
3369
3144
|
GameAudioContext.displayName = "GameAudioContext";
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
loader.setResourcePath(detectAssetRoot2(url));
|
|
3380
|
-
return loader;
|
|
3381
|
-
}
|
|
3382
|
-
var AssetLoader = class {
|
|
3383
|
-
constructor() {
|
|
3384
|
-
__publicField(this, "objLoader");
|
|
3385
|
-
__publicField(this, "textureLoader");
|
|
3386
|
-
__publicField(this, "modelCache");
|
|
3387
|
-
__publicField(this, "textureCache");
|
|
3388
|
-
__publicField(this, "loadingPromises");
|
|
3389
|
-
this.objLoader = new OBJLoader();
|
|
3390
|
-
this.textureLoader = new THREE.TextureLoader();
|
|
3391
|
-
this.modelCache = /* @__PURE__ */ new Map();
|
|
3392
|
-
this.textureCache = /* @__PURE__ */ new Map();
|
|
3393
|
-
this.loadingPromises = /* @__PURE__ */ new Map();
|
|
3394
|
-
}
|
|
3395
|
-
/**
|
|
3396
|
-
* Load a GLB/GLTF model
|
|
3397
|
-
* @param url - URL to the .glb or .gltf file
|
|
3398
|
-
* @returns Promise with loaded model scene and animations
|
|
3399
|
-
*/
|
|
3400
|
-
async loadModel(url) {
|
|
3401
|
-
if (this.modelCache.has(url)) {
|
|
3402
|
-
return this.modelCache.get(url);
|
|
3403
|
-
}
|
|
3404
|
-
if (this.loadingPromises.has(url)) {
|
|
3405
|
-
return this.loadingPromises.get(url);
|
|
3406
|
-
}
|
|
3407
|
-
const loader = createGLTFLoaderForUrl(url);
|
|
3408
|
-
const loadPromise = loader.loadAsync(url).then((gltf) => {
|
|
3409
|
-
const result = {
|
|
3410
|
-
scene: gltf.scene,
|
|
3411
|
-
animations: gltf.animations || []
|
|
3412
|
-
};
|
|
3413
|
-
this.modelCache.set(url, result);
|
|
3414
|
-
this.loadingPromises.delete(url);
|
|
3415
|
-
return result;
|
|
3416
|
-
}).catch((error) => {
|
|
3417
|
-
this.loadingPromises.delete(url);
|
|
3418
|
-
throw new Error(`Failed to load model ${url}: ${error.message}`);
|
|
3419
|
-
});
|
|
3420
|
-
this.loadingPromises.set(url, loadPromise);
|
|
3421
|
-
return loadPromise;
|
|
3422
|
-
}
|
|
3423
|
-
/**
|
|
3424
|
-
* Load an OBJ model (fallback for non-GLB assets)
|
|
3425
|
-
* @param url - URL to the .obj file
|
|
3426
|
-
* @returns Promise with loaded object group
|
|
3427
|
-
*/
|
|
3428
|
-
async loadOBJ(url) {
|
|
3429
|
-
if (this.modelCache.has(url)) {
|
|
3430
|
-
return this.modelCache.get(url).scene;
|
|
3431
|
-
}
|
|
3432
|
-
if (this.loadingPromises.has(url)) {
|
|
3433
|
-
const result = await this.loadingPromises.get(url);
|
|
3434
|
-
return result.scene;
|
|
3435
|
-
}
|
|
3436
|
-
const loadPromise = this.objLoader.loadAsync(url).then((group) => {
|
|
3437
|
-
const result = {
|
|
3438
|
-
scene: group,
|
|
3439
|
-
animations: []
|
|
3440
|
-
};
|
|
3441
|
-
this.modelCache.set(url, result);
|
|
3442
|
-
this.loadingPromises.delete(url);
|
|
3443
|
-
return result;
|
|
3444
|
-
}).catch((error) => {
|
|
3445
|
-
this.loadingPromises.delete(url);
|
|
3446
|
-
throw new Error(`Failed to load OBJ ${url}: ${error.message}`);
|
|
3447
|
-
});
|
|
3448
|
-
this.loadingPromises.set(url, loadPromise);
|
|
3449
|
-
return (await loadPromise).scene;
|
|
3450
|
-
}
|
|
3451
|
-
/**
|
|
3452
|
-
* Load a texture
|
|
3453
|
-
* @param url - URL to the texture image
|
|
3454
|
-
* @returns Promise with loaded texture
|
|
3455
|
-
*/
|
|
3456
|
-
async loadTexture(url) {
|
|
3457
|
-
if (this.textureCache.has(url)) {
|
|
3458
|
-
return this.textureCache.get(url);
|
|
3459
|
-
}
|
|
3460
|
-
if (this.loadingPromises.has(`texture:${url}`)) {
|
|
3461
|
-
return this.loadingPromises.get(`texture:${url}`);
|
|
3462
|
-
}
|
|
3463
|
-
const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
|
|
3464
|
-
texture.colorSpace = THREE.SRGBColorSpace;
|
|
3465
|
-
this.textureCache.set(url, texture);
|
|
3466
|
-
this.loadingPromises.delete(`texture:${url}`);
|
|
3467
|
-
return texture;
|
|
3468
|
-
}).catch((error) => {
|
|
3469
|
-
this.loadingPromises.delete(`texture:${url}`);
|
|
3470
|
-
throw new Error(`Failed to load texture ${url}: ${error.message}`);
|
|
3471
|
-
});
|
|
3472
|
-
this.loadingPromises.set(`texture:${url}`, loadPromise);
|
|
3473
|
-
return loadPromise;
|
|
3474
|
-
}
|
|
3475
|
-
/**
|
|
3476
|
-
* Preload multiple assets
|
|
3477
|
-
* @param urls - Array of asset URLs to preload
|
|
3478
|
-
* @returns Promise that resolves when all assets are loaded
|
|
3479
|
-
*/
|
|
3480
|
-
async preload(urls) {
|
|
3481
|
-
const promises = urls.map((url) => {
|
|
3482
|
-
if (url.endsWith(".glb") || url.endsWith(".gltf")) {
|
|
3483
|
-
return this.loadModel(url).catch(() => null);
|
|
3484
|
-
} else if (url.endsWith(".obj")) {
|
|
3485
|
-
return this.loadOBJ(url).catch(() => null);
|
|
3486
|
-
} else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
|
|
3487
|
-
return this.loadTexture(url).catch(() => null);
|
|
3488
|
-
}
|
|
3489
|
-
return Promise.resolve(null);
|
|
3490
|
-
});
|
|
3491
|
-
await Promise.all(promises);
|
|
3492
|
-
}
|
|
3493
|
-
/**
|
|
3494
|
-
* Check if a model is cached
|
|
3495
|
-
* @param url - Model URL
|
|
3496
|
-
*/
|
|
3497
|
-
hasModel(url) {
|
|
3498
|
-
return this.modelCache.has(url);
|
|
3499
|
-
}
|
|
3500
|
-
/**
|
|
3501
|
-
* Check if a texture is cached
|
|
3502
|
-
* @param url - Texture URL
|
|
3503
|
-
*/
|
|
3504
|
-
hasTexture(url) {
|
|
3505
|
-
return this.textureCache.has(url);
|
|
3506
|
-
}
|
|
3507
|
-
/**
|
|
3508
|
-
* Get cached model (throws if not cached)
|
|
3509
|
-
* @param url - Model URL
|
|
3510
|
-
*/
|
|
3511
|
-
getModel(url) {
|
|
3512
|
-
const model = this.modelCache.get(url);
|
|
3513
|
-
if (!model) {
|
|
3514
|
-
throw new Error(`Model ${url} not in cache`);
|
|
3515
|
-
}
|
|
3516
|
-
return model;
|
|
3517
|
-
}
|
|
3518
|
-
/**
|
|
3519
|
-
* Get cached texture (throws if not cached)
|
|
3520
|
-
* @param url - Texture URL
|
|
3521
|
-
*/
|
|
3522
|
-
getTexture(url) {
|
|
3523
|
-
const texture = this.textureCache.get(url);
|
|
3524
|
-
if (!texture) {
|
|
3525
|
-
throw new Error(`Texture ${url} not in cache`);
|
|
3526
|
-
}
|
|
3527
|
-
return texture;
|
|
3528
|
-
}
|
|
3529
|
-
/**
|
|
3530
|
-
* Clear all caches
|
|
3531
|
-
*/
|
|
3532
|
-
clearCache() {
|
|
3533
|
-
this.textureCache.forEach((texture) => {
|
|
3534
|
-
texture.dispose();
|
|
3535
|
-
});
|
|
3536
|
-
this.modelCache.forEach((model) => {
|
|
3537
|
-
model.scene.traverse((child) => {
|
|
3538
|
-
if (child instanceof THREE.Mesh) {
|
|
3539
|
-
child.geometry.dispose();
|
|
3540
|
-
if (Array.isArray(child.material)) {
|
|
3541
|
-
child.material.forEach((m) => m.dispose());
|
|
3542
|
-
} else {
|
|
3543
|
-
child.material.dispose();
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3546
|
-
});
|
|
3547
|
-
});
|
|
3548
|
-
this.modelCache.clear();
|
|
3549
|
-
this.textureCache.clear();
|
|
3550
|
-
this.loadingPromises.clear();
|
|
3551
|
-
}
|
|
3552
|
-
/**
|
|
3553
|
-
* Get cache statistics
|
|
3554
|
-
*/
|
|
3555
|
-
getStats() {
|
|
3556
|
-
return {
|
|
3557
|
-
models: this.modelCache.size,
|
|
3558
|
-
textures: this.textureCache.size,
|
|
3559
|
-
loading: this.loadingPromises.size
|
|
3560
|
-
};
|
|
3561
|
-
}
|
|
3562
|
-
};
|
|
3563
|
-
new AssetLoader();
|
|
3564
|
-
function useAssetLoader(options = {}) {
|
|
3565
|
-
const { preloadUrls = [], loader: customLoader } = options;
|
|
3566
|
-
const loaderRef = useRef(customLoader || new AssetLoader());
|
|
3567
|
-
const [state, setState] = useState({
|
|
3568
|
-
isLoading: false,
|
|
3569
|
-
progress: 0,
|
|
3570
|
-
loaded: 0,
|
|
3571
|
-
total: 0,
|
|
3572
|
-
errors: []
|
|
3573
|
-
});
|
|
3574
|
-
useEffect(() => {
|
|
3575
|
-
if (preloadUrls.length > 0) {
|
|
3576
|
-
preload(preloadUrls);
|
|
3577
|
-
}
|
|
3578
|
-
}, []);
|
|
3579
|
-
const updateProgress = useCallback((loaded, total) => {
|
|
3580
|
-
setState((prev) => ({
|
|
3581
|
-
...prev,
|
|
3582
|
-
loaded,
|
|
3583
|
-
total,
|
|
3584
|
-
progress: total > 0 ? Math.round(loaded / total * 100) : 0
|
|
3585
|
-
}));
|
|
3586
|
-
}, []);
|
|
3587
|
-
const loadModel = useCallback(
|
|
3588
|
-
async (url) => {
|
|
3589
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
3590
|
-
try {
|
|
3591
|
-
const model = await loaderRef.current.loadModel(url);
|
|
3592
|
-
setState((prev) => ({
|
|
3593
|
-
...prev,
|
|
3594
|
-
isLoading: false,
|
|
3595
|
-
loaded: prev.loaded + 1
|
|
3596
|
-
}));
|
|
3597
|
-
return model;
|
|
3598
|
-
} catch (error) {
|
|
3599
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3600
|
-
setState((prev) => ({
|
|
3601
|
-
...prev,
|
|
3602
|
-
isLoading: false,
|
|
3603
|
-
errors: [...prev.errors, errorMsg]
|
|
3604
|
-
}));
|
|
3605
|
-
throw error;
|
|
3606
|
-
}
|
|
3607
|
-
},
|
|
3608
|
-
[]
|
|
3609
|
-
);
|
|
3610
|
-
const loadOBJ = useCallback(
|
|
3611
|
-
async (url) => {
|
|
3612
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
3613
|
-
try {
|
|
3614
|
-
const model = await loaderRef.current.loadOBJ(url);
|
|
3615
|
-
setState((prev) => ({
|
|
3616
|
-
...prev,
|
|
3617
|
-
isLoading: false,
|
|
3618
|
-
loaded: prev.loaded + 1
|
|
3619
|
-
}));
|
|
3620
|
-
return model;
|
|
3621
|
-
} catch (error) {
|
|
3622
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3623
|
-
setState((prev) => ({
|
|
3624
|
-
...prev,
|
|
3625
|
-
isLoading: false,
|
|
3626
|
-
errors: [...prev.errors, errorMsg]
|
|
3627
|
-
}));
|
|
3628
|
-
throw error;
|
|
3629
|
-
}
|
|
3630
|
-
},
|
|
3631
|
-
[]
|
|
3632
|
-
);
|
|
3633
|
-
const loadTexture = useCallback(
|
|
3634
|
-
async (url) => {
|
|
3635
|
-
setState((prev) => ({ ...prev, isLoading: true }));
|
|
3636
|
-
try {
|
|
3637
|
-
const texture = await loaderRef.current.loadTexture(url);
|
|
3638
|
-
setState((prev) => ({
|
|
3639
|
-
...prev,
|
|
3640
|
-
isLoading: false,
|
|
3641
|
-
loaded: prev.loaded + 1
|
|
3642
|
-
}));
|
|
3643
|
-
return texture;
|
|
3644
|
-
} catch (error) {
|
|
3645
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3646
|
-
setState((prev) => ({
|
|
3647
|
-
...prev,
|
|
3648
|
-
isLoading: false,
|
|
3649
|
-
errors: [...prev.errors, errorMsg]
|
|
3650
|
-
}));
|
|
3651
|
-
throw error;
|
|
3652
|
-
}
|
|
3653
|
-
},
|
|
3654
|
-
[]
|
|
3655
|
-
);
|
|
3656
|
-
const preload = useCallback(
|
|
3657
|
-
async (urls) => {
|
|
3658
|
-
setState((prev) => ({
|
|
3659
|
-
...prev,
|
|
3660
|
-
isLoading: true,
|
|
3661
|
-
total: urls.length,
|
|
3662
|
-
loaded: 0,
|
|
3663
|
-
errors: []
|
|
3664
|
-
}));
|
|
3665
|
-
let completed = 0;
|
|
3666
|
-
const errors = [];
|
|
3667
|
-
await Promise.all(
|
|
3668
|
-
urls.map(async (url) => {
|
|
3669
|
-
try {
|
|
3670
|
-
if (url.endsWith(".glb") || url.endsWith(".gltf")) {
|
|
3671
|
-
await loaderRef.current.loadModel(url);
|
|
3672
|
-
} else if (url.endsWith(".obj")) {
|
|
3673
|
-
await loaderRef.current.loadOBJ(url);
|
|
3674
|
-
} else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
|
|
3675
|
-
await loaderRef.current.loadTexture(url);
|
|
3676
|
-
}
|
|
3677
|
-
completed++;
|
|
3678
|
-
updateProgress(completed, urls.length);
|
|
3679
|
-
} catch (error) {
|
|
3680
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
3681
|
-
errors.push(`${url}: ${errorMsg}`);
|
|
3682
|
-
completed++;
|
|
3683
|
-
updateProgress(completed, urls.length);
|
|
3684
|
-
}
|
|
3685
|
-
})
|
|
3686
|
-
);
|
|
3687
|
-
setState((prev) => ({
|
|
3688
|
-
...prev,
|
|
3689
|
-
isLoading: false,
|
|
3690
|
-
errors
|
|
3691
|
-
}));
|
|
3692
|
-
},
|
|
3693
|
-
[updateProgress]
|
|
3694
|
-
);
|
|
3695
|
-
const hasModel = useCallback((url) => {
|
|
3696
|
-
return loaderRef.current.hasModel(url);
|
|
3697
|
-
}, []);
|
|
3698
|
-
const hasTexture = useCallback((url) => {
|
|
3699
|
-
return loaderRef.current.hasTexture(url);
|
|
3700
|
-
}, []);
|
|
3701
|
-
const getModel = useCallback((url) => {
|
|
3702
|
-
try {
|
|
3703
|
-
return loaderRef.current.getModel(url);
|
|
3704
|
-
} catch {
|
|
3705
|
-
return void 0;
|
|
3706
|
-
}
|
|
3707
|
-
}, []);
|
|
3708
|
-
const getTexture = useCallback((url) => {
|
|
3709
|
-
try {
|
|
3710
|
-
return loaderRef.current.getTexture(url);
|
|
3711
|
-
} catch {
|
|
3712
|
-
return void 0;
|
|
3713
|
-
}
|
|
3714
|
-
}, []);
|
|
3715
|
-
const clearCache = useCallback(() => {
|
|
3716
|
-
loaderRef.current.clearCache();
|
|
3717
|
-
setState({
|
|
3718
|
-
isLoading: false,
|
|
3719
|
-
progress: 0,
|
|
3720
|
-
loaded: 0,
|
|
3721
|
-
total: 0,
|
|
3722
|
-
errors: []
|
|
3723
|
-
});
|
|
3724
|
-
}, []);
|
|
3725
|
-
return {
|
|
3726
|
-
...state,
|
|
3727
|
-
loadModel,
|
|
3728
|
-
loadOBJ,
|
|
3729
|
-
loadTexture,
|
|
3730
|
-
preload,
|
|
3731
|
-
hasModel,
|
|
3732
|
-
hasTexture,
|
|
3733
|
-
getModel,
|
|
3734
|
-
getTexture,
|
|
3735
|
-
clearCache
|
|
3736
|
-
};
|
|
3737
|
-
}
|
|
3738
|
-
function useGameCanvas3DEvents(options) {
|
|
3739
|
-
const {
|
|
3740
|
-
tileClickEvent,
|
|
3741
|
-
unitClickEvent,
|
|
3742
|
-
featureClickEvent,
|
|
3743
|
-
canvasClickEvent,
|
|
3744
|
-
tileHoverEvent,
|
|
3745
|
-
tileLeaveEvent,
|
|
3746
|
-
unitAnimationEvent,
|
|
3747
|
-
cameraChangeEvent,
|
|
3748
|
-
onTileClick,
|
|
3749
|
-
onUnitClick,
|
|
3750
|
-
onFeatureClick,
|
|
3751
|
-
onCanvasClick,
|
|
3752
|
-
onTileHover,
|
|
3753
|
-
onUnitAnimation
|
|
3754
|
-
} = options;
|
|
3755
|
-
const emit = useEmitEvent();
|
|
3756
|
-
const optionsRef = useRef(options);
|
|
3757
|
-
optionsRef.current = options;
|
|
3758
|
-
const handleTileClick = useCallback(
|
|
3759
|
-
(tile, event) => {
|
|
3760
|
-
if (tileClickEvent) {
|
|
3761
|
-
emit(tileClickEvent, {
|
|
3762
|
-
tileId: tile.id,
|
|
3763
|
-
x: tile.x,
|
|
3764
|
-
z: tile.z ?? tile.y ?? 0,
|
|
3765
|
-
type: tile.type,
|
|
3766
|
-
terrain: tile.terrain,
|
|
3767
|
-
elevation: tile.elevation
|
|
3768
|
-
});
|
|
3769
|
-
}
|
|
3770
|
-
optionsRef.current.onTileClick?.(tile, event);
|
|
3771
|
-
},
|
|
3772
|
-
[tileClickEvent, emit]
|
|
3773
|
-
);
|
|
3774
|
-
const handleUnitClick = useCallback(
|
|
3775
|
-
(unit, event) => {
|
|
3776
|
-
if (unitClickEvent) {
|
|
3777
|
-
emit(unitClickEvent, {
|
|
3778
|
-
unitId: unit.id,
|
|
3779
|
-
x: unit.x,
|
|
3780
|
-
z: unit.z ?? unit.y ?? 0,
|
|
3781
|
-
unitType: unit.unitType,
|
|
3782
|
-
name: unit.name,
|
|
3783
|
-
team: unit.team,
|
|
3784
|
-
faction: unit.faction,
|
|
3785
|
-
health: unit.health,
|
|
3786
|
-
maxHealth: unit.maxHealth
|
|
3787
|
-
});
|
|
3788
|
-
}
|
|
3789
|
-
optionsRef.current.onUnitClick?.(unit, event);
|
|
3790
|
-
},
|
|
3791
|
-
[unitClickEvent, emit]
|
|
3792
|
-
);
|
|
3793
|
-
const handleFeatureClick = useCallback(
|
|
3794
|
-
(feature, event) => {
|
|
3795
|
-
if (featureClickEvent) {
|
|
3796
|
-
emit(featureClickEvent, {
|
|
3797
|
-
featureId: feature.id,
|
|
3798
|
-
x: feature.x,
|
|
3799
|
-
z: feature.z ?? feature.y ?? 0,
|
|
3800
|
-
type: feature.type,
|
|
3801
|
-
elevation: feature.elevation
|
|
3802
|
-
});
|
|
3803
|
-
}
|
|
3804
|
-
optionsRef.current.onFeatureClick?.(feature, event);
|
|
3805
|
-
},
|
|
3806
|
-
[featureClickEvent, emit]
|
|
3807
|
-
);
|
|
3808
|
-
const handleCanvasClick = useCallback(
|
|
3809
|
-
(event) => {
|
|
3810
|
-
if (canvasClickEvent) {
|
|
3811
|
-
emit(canvasClickEvent, {
|
|
3812
|
-
clientX: event.clientX,
|
|
3813
|
-
clientY: event.clientY,
|
|
3814
|
-
button: event.button
|
|
3815
|
-
});
|
|
3816
|
-
}
|
|
3817
|
-
optionsRef.current.onCanvasClick?.(event);
|
|
3818
|
-
},
|
|
3819
|
-
[canvasClickEvent, emit]
|
|
3820
|
-
);
|
|
3821
|
-
const handleTileHover = useCallback(
|
|
3822
|
-
(tile, event) => {
|
|
3823
|
-
if (tile) {
|
|
3824
|
-
if (tileHoverEvent) {
|
|
3825
|
-
emit(tileHoverEvent, {
|
|
3826
|
-
tileId: tile.id,
|
|
3827
|
-
x: tile.x,
|
|
3828
|
-
z: tile.z ?? tile.y ?? 0,
|
|
3829
|
-
type: tile.type
|
|
3830
|
-
});
|
|
3831
|
-
}
|
|
3832
|
-
} else {
|
|
3833
|
-
if (tileLeaveEvent) {
|
|
3834
|
-
emit(tileLeaveEvent, {});
|
|
3835
|
-
}
|
|
3836
|
-
}
|
|
3837
|
-
optionsRef.current.onTileHover?.(tile, event);
|
|
3838
|
-
},
|
|
3839
|
-
[tileHoverEvent, tileLeaveEvent, emit]
|
|
3840
|
-
);
|
|
3841
|
-
const handleUnitAnimation = useCallback(
|
|
3842
|
-
(unitId, state) => {
|
|
3843
|
-
if (unitAnimationEvent) {
|
|
3844
|
-
emit(unitAnimationEvent, {
|
|
3845
|
-
unitId,
|
|
3846
|
-
state,
|
|
3847
|
-
timestamp: Date.now()
|
|
3848
|
-
});
|
|
3849
|
-
}
|
|
3850
|
-
optionsRef.current.onUnitAnimation?.(unitId, state);
|
|
3851
|
-
},
|
|
3852
|
-
[unitAnimationEvent, emit]
|
|
3853
|
-
);
|
|
3854
|
-
const handleCameraChange = useCallback(
|
|
3855
|
-
(position) => {
|
|
3856
|
-
if (cameraChangeEvent) {
|
|
3857
|
-
emit(cameraChangeEvent, {
|
|
3858
|
-
position,
|
|
3859
|
-
timestamp: Date.now()
|
|
3860
|
-
});
|
|
3861
|
-
}
|
|
3862
|
-
},
|
|
3863
|
-
[cameraChangeEvent, emit]
|
|
3864
|
-
);
|
|
3865
|
-
return {
|
|
3866
|
-
handleTileClick,
|
|
3867
|
-
handleUnitClick,
|
|
3868
|
-
handleFeatureClick,
|
|
3869
|
-
handleCanvasClick,
|
|
3870
|
-
handleTileHover,
|
|
3871
|
-
handleUnitAnimation,
|
|
3872
|
-
handleCameraChange
|
|
3873
|
-
};
|
|
3874
|
-
}
|
|
3875
|
-
function detectAssetRoot3(modelUrl) {
|
|
3876
|
-
const idx = modelUrl.indexOf("/3d/");
|
|
3877
|
-
if (idx !== -1) {
|
|
3878
|
-
return modelUrl.substring(0, idx + 4);
|
|
3879
|
-
}
|
|
3880
|
-
return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
|
|
3881
|
-
}
|
|
3882
|
-
function useGLTFModel2(url, resourceBasePath) {
|
|
3883
|
-
const [state, setState] = useState({
|
|
3884
|
-
model: null,
|
|
3885
|
-
isLoading: false,
|
|
3886
|
-
error: null
|
|
3887
|
-
});
|
|
3888
|
-
useEffect(() => {
|
|
3889
|
-
if (!url) {
|
|
3890
|
-
setState({ model: null, isLoading: false, error: null });
|
|
3891
|
-
return;
|
|
3892
|
-
}
|
|
3893
|
-
console.log("[ModelLoader] Loading:", url);
|
|
3894
|
-
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
3895
|
-
const assetRoot = resourceBasePath || detectAssetRoot3(url);
|
|
3896
|
-
const loader = new GLTFLoader$1();
|
|
3897
|
-
loader.setResourcePath(assetRoot);
|
|
3898
|
-
loader.load(
|
|
3899
|
-
url,
|
|
3900
|
-
(gltf) => {
|
|
3901
|
-
console.log("[ModelLoader] Loaded:", url);
|
|
3902
|
-
setState({
|
|
3903
|
-
model: gltf.scene,
|
|
3904
|
-
isLoading: false,
|
|
3905
|
-
error: null
|
|
3906
|
-
});
|
|
3907
|
-
},
|
|
3908
|
-
void 0,
|
|
3909
|
-
(err) => {
|
|
3910
|
-
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
3911
|
-
console.warn("[ModelLoader] Failed:", url, errorMsg);
|
|
3912
|
-
setState({
|
|
3913
|
-
model: null,
|
|
3914
|
-
isLoading: false,
|
|
3915
|
-
error: err instanceof Error ? err : new Error(String(err))
|
|
3916
|
-
});
|
|
3917
|
-
}
|
|
3145
|
+
|
|
3146
|
+
// components/organisms/component-registry.generated.ts
|
|
3147
|
+
function lazyThree(name, loader) {
|
|
3148
|
+
const Lazy = React110__default.lazy(() => loader().then((m) => ({ default: m[name] })));
|
|
3149
|
+
function ThreeWrapper(props) {
|
|
3150
|
+
return React110__default.createElement(
|
|
3151
|
+
React110__default.Suspense,
|
|
3152
|
+
{ fallback: null },
|
|
3153
|
+
React110__default.createElement(Lazy, props)
|
|
3918
3154
|
);
|
|
3919
|
-
}, [url, resourceBasePath]);
|
|
3920
|
-
return state;
|
|
3921
|
-
}
|
|
3922
|
-
function ModelLoader({
|
|
3923
|
-
url,
|
|
3924
|
-
position = [0, 0, 0],
|
|
3925
|
-
scale = 1,
|
|
3926
|
-
rotation = [0, 0, 0],
|
|
3927
|
-
isSelected = false,
|
|
3928
|
-
isHovered = false,
|
|
3929
|
-
onClick,
|
|
3930
|
-
onHover,
|
|
3931
|
-
fallbackGeometry = "box",
|
|
3932
|
-
castShadow = true,
|
|
3933
|
-
receiveShadow = true,
|
|
3934
|
-
resourceBasePath
|
|
3935
|
-
}) {
|
|
3936
|
-
const { model: loadedModel, isLoading, error } = useGLTFModel2(url, resourceBasePath);
|
|
3937
|
-
const model = useMemo(() => {
|
|
3938
|
-
if (!loadedModel) return null;
|
|
3939
|
-
const cloned = loadedModel.clone();
|
|
3940
|
-
cloned.traverse((child) => {
|
|
3941
|
-
if (child instanceof THREE.Mesh) {
|
|
3942
|
-
child.castShadow = castShadow;
|
|
3943
|
-
child.receiveShadow = receiveShadow;
|
|
3944
|
-
}
|
|
3945
|
-
});
|
|
3946
|
-
return cloned;
|
|
3947
|
-
}, [loadedModel, castShadow, receiveShadow]);
|
|
3948
|
-
const scaleArray = useMemo(() => {
|
|
3949
|
-
if (typeof scale === "number") {
|
|
3950
|
-
return [scale, scale, scale];
|
|
3951
|
-
}
|
|
3952
|
-
return scale;
|
|
3953
|
-
}, [scale]);
|
|
3954
|
-
const rotationRad = useMemo(() => {
|
|
3955
|
-
return [
|
|
3956
|
-
rotation[0] * Math.PI / 180,
|
|
3957
|
-
rotation[1] * Math.PI / 180,
|
|
3958
|
-
rotation[2] * Math.PI / 180
|
|
3959
|
-
];
|
|
3960
|
-
}, [rotation]);
|
|
3961
|
-
if (isLoading) {
|
|
3962
|
-
return /* @__PURE__ */ jsx("group", { position, children: /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
|
|
3963
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.3, 0.35, 16] }),
|
|
3964
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: "#4a90d9", transparent: true, opacity: 0.8 })
|
|
3965
|
-
] }) });
|
|
3966
|
-
}
|
|
3967
|
-
if (error || !model) {
|
|
3968
|
-
if (fallbackGeometry === "none") {
|
|
3969
|
-
return /* @__PURE__ */ jsx("group", { position });
|
|
3970
|
-
}
|
|
3971
|
-
const fallbackProps = {
|
|
3972
|
-
onClick,
|
|
3973
|
-
onPointerOver: () => onHover?.(true),
|
|
3974
|
-
onPointerOut: () => onHover?.(false)
|
|
3975
|
-
};
|
|
3976
|
-
return /* @__PURE__ */ jsxs("group", { position, children: [
|
|
3977
|
-
(isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
3978
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
|
|
3979
|
-
/* @__PURE__ */ jsx(
|
|
3980
|
-
"meshBasicMaterial",
|
|
3981
|
-
{
|
|
3982
|
-
color: isSelected ? 16755200 : 16777215,
|
|
3983
|
-
transparent: true,
|
|
3984
|
-
opacity: 0.5
|
|
3985
|
-
}
|
|
3986
|
-
)
|
|
3987
|
-
] }),
|
|
3988
|
-
fallbackGeometry === "box" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
3989
|
-
/* @__PURE__ */ jsx("boxGeometry", { args: [0.8, 0.8, 0.8] }),
|
|
3990
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
3991
|
-
] }),
|
|
3992
|
-
fallbackGeometry === "sphere" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
3993
|
-
/* @__PURE__ */ jsx("sphereGeometry", { args: [0.4, 16, 16] }),
|
|
3994
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
3995
|
-
] }),
|
|
3996
|
-
fallbackGeometry === "cylinder" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
|
|
3997
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.8, 16] }),
|
|
3998
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
|
|
3999
|
-
] })
|
|
4000
|
-
] });
|
|
4001
3155
|
}
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
{
|
|
4005
|
-
position,
|
|
4006
|
-
rotation: rotationRad,
|
|
4007
|
-
onClick,
|
|
4008
|
-
onPointerOver: () => onHover?.(true),
|
|
4009
|
-
onPointerOut: () => onHover?.(false),
|
|
4010
|
-
children: [
|
|
4011
|
-
(isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
4012
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
|
|
4013
|
-
/* @__PURE__ */ jsx(
|
|
4014
|
-
"meshBasicMaterial",
|
|
4015
|
-
{
|
|
4016
|
-
color: isSelected ? 16755200 : 16777215,
|
|
4017
|
-
transparent: true,
|
|
4018
|
-
opacity: 0.5
|
|
4019
|
-
}
|
|
4020
|
-
)
|
|
4021
|
-
] }),
|
|
4022
|
-
/* @__PURE__ */ jsx("primitive", { object: model, scale: scaleArray })
|
|
4023
|
-
]
|
|
4024
|
-
}
|
|
4025
|
-
);
|
|
4026
|
-
}
|
|
4027
|
-
var DEFAULT_GRID_CONFIG = {
|
|
4028
|
-
cellSize: 1,
|
|
4029
|
-
offsetX: 0,
|
|
4030
|
-
offsetZ: 0
|
|
4031
|
-
};
|
|
4032
|
-
function CameraController({
|
|
4033
|
-
onCameraChange
|
|
4034
|
-
}) {
|
|
4035
|
-
const { camera } = useThree();
|
|
4036
|
-
useEffect(() => {
|
|
4037
|
-
if (onCameraChange) {
|
|
4038
|
-
onCameraChange({
|
|
4039
|
-
x: camera.position.x,
|
|
4040
|
-
y: camera.position.y,
|
|
4041
|
-
z: camera.position.z
|
|
4042
|
-
});
|
|
4043
|
-
}
|
|
4044
|
-
}, [camera.position, onCameraChange]);
|
|
4045
|
-
return null;
|
|
3156
|
+
ThreeWrapper.displayName = `Lazy(${name})`;
|
|
3157
|
+
return ThreeWrapper;
|
|
4046
3158
|
}
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
onUnitClick,
|
|
4063
|
-
onFeatureClick,
|
|
4064
|
-
onCanvasClick,
|
|
4065
|
-
onTileHover,
|
|
4066
|
-
onUnitAnimation,
|
|
4067
|
-
assetLoader: customAssetLoader,
|
|
4068
|
-
tileRenderer: CustomTileRenderer,
|
|
4069
|
-
unitRenderer: CustomUnitRenderer,
|
|
4070
|
-
featureRenderer: CustomFeatureRenderer,
|
|
4071
|
-
className,
|
|
4072
|
-
isLoading: externalLoading,
|
|
4073
|
-
error: externalError,
|
|
4074
|
-
entity,
|
|
4075
|
-
preloadAssets = [],
|
|
4076
|
-
tileClickEvent,
|
|
4077
|
-
unitClickEvent,
|
|
4078
|
-
featureClickEvent,
|
|
4079
|
-
canvasClickEvent,
|
|
4080
|
-
tileHoverEvent,
|
|
4081
|
-
tileLeaveEvent,
|
|
4082
|
-
unitAnimationEvent,
|
|
4083
|
-
cameraChangeEvent,
|
|
4084
|
-
loadingMessage = "Loading 3D Scene...",
|
|
4085
|
-
useInstancing = true,
|
|
4086
|
-
validMoves = [],
|
|
4087
|
-
attackTargets = [],
|
|
4088
|
-
selectedTileIds = [],
|
|
4089
|
-
selectedUnitId = null,
|
|
4090
|
-
children
|
|
4091
|
-
}, ref) => {
|
|
4092
|
-
const containerRef = useRef(null);
|
|
4093
|
-
const controlsRef = useRef(null);
|
|
4094
|
-
const [hoveredTile, setHoveredTile] = useState(null);
|
|
4095
|
-
const [internalError, setInternalError] = useState(null);
|
|
4096
|
-
const { isLoading: assetsLoading, progress, loaded, total } = useAssetLoader({
|
|
4097
|
-
preloadUrls: preloadAssets,
|
|
4098
|
-
loader: customAssetLoader
|
|
4099
|
-
});
|
|
4100
|
-
const eventHandlers = useGameCanvas3DEvents({
|
|
4101
|
-
tileClickEvent,
|
|
4102
|
-
unitClickEvent,
|
|
4103
|
-
featureClickEvent,
|
|
4104
|
-
canvasClickEvent,
|
|
4105
|
-
tileHoverEvent,
|
|
4106
|
-
tileLeaveEvent,
|
|
4107
|
-
unitAnimationEvent,
|
|
4108
|
-
cameraChangeEvent,
|
|
4109
|
-
onTileClick,
|
|
4110
|
-
onUnitClick,
|
|
4111
|
-
onFeatureClick,
|
|
4112
|
-
onCanvasClick,
|
|
4113
|
-
onTileHover,
|
|
4114
|
-
onUnitAnimation
|
|
4115
|
-
});
|
|
4116
|
-
const gridBounds = useMemo(() => {
|
|
4117
|
-
if (tiles.length === 0) {
|
|
4118
|
-
return { minX: 0, maxX: 10, minZ: 0, maxZ: 10 };
|
|
4119
|
-
}
|
|
4120
|
-
const xs = tiles.map((t) => t.x);
|
|
4121
|
-
const zs = tiles.map((t) => t.z || t.y || 0);
|
|
4122
|
-
return {
|
|
4123
|
-
minX: Math.min(...xs),
|
|
4124
|
-
maxX: Math.max(...xs),
|
|
4125
|
-
minZ: Math.min(...zs),
|
|
4126
|
-
maxZ: Math.max(...zs)
|
|
4127
|
-
};
|
|
4128
|
-
}, [tiles]);
|
|
4129
|
-
const cameraTarget = useMemo(() => {
|
|
4130
|
-
return [
|
|
4131
|
-
(gridBounds.minX + gridBounds.maxX) / 2,
|
|
4132
|
-
0,
|
|
4133
|
-
(gridBounds.minZ + gridBounds.maxZ) / 2
|
|
4134
|
-
];
|
|
4135
|
-
}, [gridBounds]);
|
|
4136
|
-
const gridConfig = useMemo(
|
|
4137
|
-
() => ({
|
|
4138
|
-
...DEFAULT_GRID_CONFIG,
|
|
4139
|
-
offsetX: -(gridBounds.maxX - gridBounds.minX) / 2,
|
|
4140
|
-
offsetZ: -(gridBounds.maxZ - gridBounds.minZ) / 2
|
|
4141
|
-
}),
|
|
4142
|
-
[gridBounds]
|
|
4143
|
-
);
|
|
4144
|
-
const gridToWorld = useCallback(
|
|
4145
|
-
(x, z, y = 0) => {
|
|
4146
|
-
const worldX = (x - gridBounds.minX) * gridConfig.cellSize;
|
|
4147
|
-
const worldZ = (z - gridBounds.minZ) * gridConfig.cellSize;
|
|
4148
|
-
return [worldX, y * gridConfig.cellSize, worldZ];
|
|
4149
|
-
},
|
|
4150
|
-
[gridBounds, gridConfig]
|
|
4151
|
-
);
|
|
4152
|
-
useImperativeHandle(ref, () => ({
|
|
4153
|
-
getCameraPosition: () => {
|
|
4154
|
-
if (controlsRef.current) {
|
|
4155
|
-
const pos = controlsRef.current.object.position;
|
|
4156
|
-
return new THREE.Vector3(pos.x, pos.y, pos.z);
|
|
4157
|
-
}
|
|
4158
|
-
return null;
|
|
4159
|
-
},
|
|
4160
|
-
setCameraPosition: (x, y, z) => {
|
|
4161
|
-
if (controlsRef.current) {
|
|
4162
|
-
controlsRef.current.object.position.set(x, y, z);
|
|
4163
|
-
controlsRef.current.update();
|
|
4164
|
-
}
|
|
4165
|
-
},
|
|
4166
|
-
lookAt: (x, y, z) => {
|
|
4167
|
-
if (controlsRef.current) {
|
|
4168
|
-
controlsRef.current.target.set(x, y, z);
|
|
4169
|
-
controlsRef.current.update();
|
|
4170
|
-
}
|
|
4171
|
-
},
|
|
4172
|
-
resetCamera: () => {
|
|
4173
|
-
if (controlsRef.current) {
|
|
4174
|
-
controlsRef.current.reset();
|
|
4175
|
-
}
|
|
4176
|
-
},
|
|
4177
|
-
screenshot: () => {
|
|
4178
|
-
const canvas = containerRef.current?.querySelector("canvas");
|
|
4179
|
-
if (canvas) {
|
|
4180
|
-
return canvas.toDataURL("image/png");
|
|
4181
|
-
}
|
|
4182
|
-
return null;
|
|
4183
|
-
},
|
|
4184
|
-
export: () => ({
|
|
4185
|
-
tiles,
|
|
4186
|
-
units,
|
|
4187
|
-
features
|
|
4188
|
-
})
|
|
4189
|
-
}));
|
|
4190
|
-
const handleTileClick = useCallback(
|
|
4191
|
-
(tile, event) => {
|
|
4192
|
-
eventHandlers.handleTileClick(tile, event);
|
|
4193
|
-
},
|
|
4194
|
-
[eventHandlers]
|
|
4195
|
-
);
|
|
4196
|
-
const handleUnitClick = useCallback(
|
|
4197
|
-
(unit, event) => {
|
|
4198
|
-
eventHandlers.handleUnitClick(unit, event);
|
|
4199
|
-
},
|
|
4200
|
-
[eventHandlers]
|
|
4201
|
-
);
|
|
4202
|
-
const handleFeatureClick = useCallback(
|
|
4203
|
-
(feature, event) => {
|
|
4204
|
-
if (event) {
|
|
4205
|
-
eventHandlers.handleFeatureClick(feature, event);
|
|
4206
|
-
}
|
|
4207
|
-
},
|
|
4208
|
-
[eventHandlers]
|
|
4209
|
-
);
|
|
4210
|
-
const handleTileHover = useCallback(
|
|
4211
|
-
(tile, event) => {
|
|
4212
|
-
setHoveredTile(tile);
|
|
4213
|
-
if (event) {
|
|
4214
|
-
eventHandlers.handleTileHover(tile, event);
|
|
4215
|
-
}
|
|
4216
|
-
},
|
|
4217
|
-
[eventHandlers]
|
|
4218
|
-
);
|
|
4219
|
-
const cameraConfig = useMemo(() => {
|
|
4220
|
-
const size = Math.max(
|
|
4221
|
-
gridBounds.maxX - gridBounds.minX,
|
|
4222
|
-
gridBounds.maxZ - gridBounds.minZ
|
|
4223
|
-
);
|
|
4224
|
-
const distance = size * 1.5;
|
|
4225
|
-
switch (cameraMode) {
|
|
4226
|
-
case "isometric":
|
|
4227
|
-
return {
|
|
4228
|
-
position: [distance, distance * 0.8, distance],
|
|
4229
|
-
fov: 45
|
|
4230
|
-
};
|
|
4231
|
-
case "top-down":
|
|
4232
|
-
return {
|
|
4233
|
-
position: [0, distance * 2, 0],
|
|
4234
|
-
fov: 45
|
|
4235
|
-
};
|
|
4236
|
-
case "perspective":
|
|
4237
|
-
default:
|
|
4238
|
-
return {
|
|
4239
|
-
position: [distance, distance, distance],
|
|
4240
|
-
fov: 45
|
|
4241
|
-
};
|
|
4242
|
-
}
|
|
4243
|
-
}, [cameraMode, gridBounds]);
|
|
4244
|
-
const DefaultTileRenderer = useCallback(
|
|
4245
|
-
({ tile, position }) => {
|
|
4246
|
-
const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
|
|
4247
|
-
const isHovered = hoveredTile?.id === tile.id;
|
|
4248
|
-
const isValidMove = validMoves.some(
|
|
4249
|
-
(m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
|
|
4250
|
-
);
|
|
4251
|
-
const isAttackTarget = attackTargets.some(
|
|
4252
|
-
(m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
|
|
4253
|
-
);
|
|
4254
|
-
let color = 8421504;
|
|
4255
|
-
if (tile.type === "water") color = 4491468;
|
|
4256
|
-
else if (tile.type === "grass") color = 4500036;
|
|
4257
|
-
else if (tile.type === "sand") color = 14535816;
|
|
4258
|
-
else if (tile.type === "rock") color = 8947848;
|
|
4259
|
-
else if (tile.type === "snow") color = 15658734;
|
|
4260
|
-
let emissive = 0;
|
|
4261
|
-
if (isSelected) emissive = 4473924;
|
|
4262
|
-
else if (isAttackTarget) emissive = 4456448;
|
|
4263
|
-
else if (isValidMove) emissive = 17408;
|
|
4264
|
-
else if (isHovered) emissive = 2236962;
|
|
4265
|
-
return /* @__PURE__ */ jsxs(
|
|
4266
|
-
"mesh",
|
|
4267
|
-
{
|
|
4268
|
-
position,
|
|
4269
|
-
onClick: (e) => handleTileClick(tile, e),
|
|
4270
|
-
onPointerEnter: (e) => handleTileHover(tile, e),
|
|
4271
|
-
onPointerLeave: (e) => handleTileHover(null, e),
|
|
4272
|
-
userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
|
|
4273
|
-
children: [
|
|
4274
|
-
/* @__PURE__ */ jsx("boxGeometry", { args: [0.95, 0.2, 0.95] }),
|
|
4275
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color, emissive })
|
|
4276
|
-
]
|
|
4277
|
-
}
|
|
4278
|
-
);
|
|
4279
|
-
},
|
|
4280
|
-
[selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
|
|
4281
|
-
);
|
|
4282
|
-
const DefaultUnitRenderer = useCallback(
|
|
4283
|
-
({ unit, position }) => {
|
|
4284
|
-
const isSelected = selectedUnitId === unit.id;
|
|
4285
|
-
const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
|
|
4286
|
-
return /* @__PURE__ */ jsxs(
|
|
4287
|
-
"group",
|
|
4288
|
-
{
|
|
4289
|
-
position,
|
|
4290
|
-
onClick: (e) => handleUnitClick(unit, e),
|
|
4291
|
-
userData: { type: "unit", unitId: unit.id },
|
|
4292
|
-
children: [
|
|
4293
|
-
isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.05, 0], rotation: [-Math.PI / 2, 0, 0], children: [
|
|
4294
|
-
/* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
|
|
4295
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
|
|
4296
|
-
] }),
|
|
4297
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.3, 0], children: [
|
|
4298
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.1, 8] }),
|
|
4299
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
4300
|
-
] }),
|
|
4301
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.6, 0], children: [
|
|
4302
|
-
/* @__PURE__ */ jsx("capsuleGeometry", { args: [0.2, 0.4, 4, 8] }),
|
|
4303
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
4304
|
-
] }),
|
|
4305
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
|
|
4306
|
-
/* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
|
|
4307
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color })
|
|
4308
|
-
] }),
|
|
4309
|
-
unit.health !== void 0 && unit.maxHealth !== void 0 && /* @__PURE__ */ jsxs("group", { position: [0, 1.2, 0], children: [
|
|
4310
|
-
/* @__PURE__ */ jsxs("mesh", { position: [-0.25, 0, 0], children: [
|
|
4311
|
-
/* @__PURE__ */ jsx("planeGeometry", { args: [0.5, 0.05] }),
|
|
4312
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color: 3355443 })
|
|
4313
|
-
] }),
|
|
4314
|
-
/* @__PURE__ */ jsxs(
|
|
4315
|
-
"mesh",
|
|
4316
|
-
{
|
|
4317
|
-
position: [
|
|
4318
|
-
-0.25 + 0.5 * (unit.health / unit.maxHealth) / 2,
|
|
4319
|
-
0,
|
|
4320
|
-
0.01
|
|
4321
|
-
],
|
|
4322
|
-
children: [
|
|
4323
|
-
/* @__PURE__ */ jsx("planeGeometry", { args: [0.5 * (unit.health / unit.maxHealth), 0.05] }),
|
|
4324
|
-
/* @__PURE__ */ jsx(
|
|
4325
|
-
"meshBasicMaterial",
|
|
4326
|
-
{
|
|
4327
|
-
color: unit.health / unit.maxHealth > 0.5 ? 4500036 : unit.health / unit.maxHealth > 0.25 ? 11184708 : 16729156
|
|
4328
|
-
}
|
|
4329
|
-
)
|
|
4330
|
-
]
|
|
4331
|
-
}
|
|
4332
|
-
)
|
|
4333
|
-
] })
|
|
4334
|
-
]
|
|
4335
|
-
}
|
|
4336
|
-
);
|
|
4337
|
-
},
|
|
4338
|
-
[selectedUnitId, handleUnitClick]
|
|
4339
|
-
);
|
|
4340
|
-
const DefaultFeatureRenderer = useCallback(
|
|
4341
|
-
({
|
|
4342
|
-
feature,
|
|
4343
|
-
position
|
|
4344
|
-
}) => {
|
|
4345
|
-
if (feature.assetUrl) {
|
|
4346
|
-
return /* @__PURE__ */ jsx(
|
|
4347
|
-
ModelLoader,
|
|
4348
|
-
{
|
|
4349
|
-
url: feature.assetUrl,
|
|
4350
|
-
position,
|
|
4351
|
-
scale: 0.5,
|
|
4352
|
-
rotation: [0, feature.rotation ?? 0, 0],
|
|
4353
|
-
onClick: () => handleFeatureClick(feature, null),
|
|
4354
|
-
fallbackGeometry: "box"
|
|
4355
|
-
},
|
|
4356
|
-
feature.id
|
|
4357
|
-
);
|
|
4358
|
-
}
|
|
4359
|
-
if (feature.type === "tree") {
|
|
4360
|
-
return /* @__PURE__ */ jsxs(
|
|
4361
|
-
"group",
|
|
4362
|
-
{
|
|
4363
|
-
position,
|
|
4364
|
-
onClick: (e) => handleFeatureClick(feature, e),
|
|
4365
|
-
userData: { type: "feature", featureId: feature.id },
|
|
4366
|
-
children: [
|
|
4367
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.4, 0], children: [
|
|
4368
|
-
/* @__PURE__ */ jsx("cylinderGeometry", { args: [0.1, 0.15, 0.8, 6] }),
|
|
4369
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 9127187 })
|
|
4370
|
-
] }),
|
|
4371
|
-
/* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
|
|
4372
|
-
/* @__PURE__ */ jsx("coneGeometry", { args: [0.5, 0.8, 8] }),
|
|
4373
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 2263842 })
|
|
4374
|
-
] })
|
|
4375
|
-
]
|
|
4376
|
-
}
|
|
4377
|
-
);
|
|
4378
|
-
}
|
|
4379
|
-
if (feature.type === "rock") {
|
|
4380
|
-
return /* @__PURE__ */ jsxs(
|
|
4381
|
-
"mesh",
|
|
4382
|
-
{
|
|
4383
|
-
position: [position[0], position[1] + 0.3, position[2]],
|
|
4384
|
-
onClick: (e) => handleFeatureClick(feature, e),
|
|
4385
|
-
userData: { type: "feature", featureId: feature.id },
|
|
4386
|
-
children: [
|
|
4387
|
-
/* @__PURE__ */ jsx("dodecahedronGeometry", { args: [0.3, 0] }),
|
|
4388
|
-
/* @__PURE__ */ jsx("meshStandardMaterial", { color: 8421504 })
|
|
4389
|
-
]
|
|
4390
|
-
}
|
|
4391
|
-
);
|
|
4392
|
-
}
|
|
4393
|
-
return null;
|
|
4394
|
-
},
|
|
4395
|
-
[handleFeatureClick]
|
|
4396
|
-
);
|
|
4397
|
-
if (externalLoading || assetsLoading && preloadAssets.length > 0) {
|
|
4398
|
-
return /* @__PURE__ */ jsx(
|
|
4399
|
-
Canvas3DLoadingState,
|
|
4400
|
-
{
|
|
4401
|
-
progress,
|
|
4402
|
-
loaded,
|
|
4403
|
-
total,
|
|
4404
|
-
message: loadingMessage,
|
|
4405
|
-
className
|
|
4406
|
-
}
|
|
4407
|
-
);
|
|
4408
|
-
}
|
|
4409
|
-
const displayError = externalError || internalError;
|
|
4410
|
-
if (displayError) {
|
|
4411
|
-
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: [
|
|
4412
|
-
"Error: ",
|
|
4413
|
-
displayError
|
|
4414
|
-
] }) }) });
|
|
4415
|
-
}
|
|
4416
|
-
return /* @__PURE__ */ jsx(
|
|
4417
|
-
Canvas3DErrorBoundary,
|
|
4418
|
-
{
|
|
4419
|
-
onError: (err) => setInternalError(err.message),
|
|
4420
|
-
onReset: () => setInternalError(null),
|
|
4421
|
-
children: /* @__PURE__ */ jsxs(
|
|
4422
|
-
"div",
|
|
4423
|
-
{
|
|
4424
|
-
ref: containerRef,
|
|
4425
|
-
className: `game-canvas-3d ${className || ""}`,
|
|
4426
|
-
"data-orientation": orientation,
|
|
4427
|
-
"data-camera-mode": cameraMode,
|
|
4428
|
-
"data-overlay": overlay,
|
|
4429
|
-
children: [
|
|
4430
|
-
/* @__PURE__ */ jsxs(
|
|
4431
|
-
Canvas,
|
|
4432
|
-
{
|
|
4433
|
-
shadows,
|
|
4434
|
-
camera: {
|
|
4435
|
-
position: cameraConfig.position,
|
|
4436
|
-
fov: cameraConfig.fov,
|
|
4437
|
-
near: 0.1,
|
|
4438
|
-
far: 1e3
|
|
4439
|
-
},
|
|
4440
|
-
style: { background: backgroundColor },
|
|
4441
|
-
onClick: (e) => {
|
|
4442
|
-
if (e.target === e.currentTarget) {
|
|
4443
|
-
eventHandlers.handleCanvasClick(e);
|
|
4444
|
-
}
|
|
4445
|
-
},
|
|
4446
|
-
children: [
|
|
4447
|
-
/* @__PURE__ */ jsx(CameraController, { onCameraChange: eventHandlers.handleCameraChange }),
|
|
4448
|
-
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.6 }),
|
|
4449
|
-
/* @__PURE__ */ jsx(
|
|
4450
|
-
"directionalLight",
|
|
4451
|
-
{
|
|
4452
|
-
position: [10, 20, 10],
|
|
4453
|
-
intensity: 0.8,
|
|
4454
|
-
castShadow: shadows,
|
|
4455
|
-
"shadow-mapSize": [2048, 2048]
|
|
4456
|
-
}
|
|
4457
|
-
),
|
|
4458
|
-
/* @__PURE__ */ jsx("hemisphereLight", { intensity: 0.3, color: "#87ceeb", groundColor: "#362d1d" }),
|
|
4459
|
-
showGrid && /* @__PURE__ */ jsx(
|
|
4460
|
-
Grid,
|
|
4461
|
-
{
|
|
4462
|
-
args: [
|
|
4463
|
-
Math.max(gridBounds.maxX - gridBounds.minX + 2, 10),
|
|
4464
|
-
Math.max(gridBounds.maxZ - gridBounds.minZ + 2, 10)
|
|
4465
|
-
],
|
|
4466
|
-
position: [
|
|
4467
|
-
(gridBounds.maxX - gridBounds.minX) / 2 - 0.5,
|
|
4468
|
-
0,
|
|
4469
|
-
(gridBounds.maxZ - gridBounds.minZ) / 2 - 0.5
|
|
4470
|
-
],
|
|
4471
|
-
cellSize: 1,
|
|
4472
|
-
cellThickness: 1,
|
|
4473
|
-
cellColor: "#444444",
|
|
4474
|
-
sectionSize: 5,
|
|
4475
|
-
sectionThickness: 1.5,
|
|
4476
|
-
sectionColor: "#666666",
|
|
4477
|
-
fadeDistance: 50,
|
|
4478
|
-
fadeStrength: 1
|
|
4479
|
-
}
|
|
4480
|
-
),
|
|
4481
|
-
tiles.map((tile, index) => {
|
|
4482
|
-
const position = gridToWorld(
|
|
4483
|
-
tile.x,
|
|
4484
|
-
tile.z ?? tile.y ?? 0,
|
|
4485
|
-
tile.elevation ?? 0
|
|
4486
|
-
);
|
|
4487
|
-
const Renderer = CustomTileRenderer || DefaultTileRenderer;
|
|
4488
|
-
return /* @__PURE__ */ jsx(Renderer, { tile, position }, tile.id ?? `tile-${index}`);
|
|
4489
|
-
}),
|
|
4490
|
-
features.map((feature, index) => {
|
|
4491
|
-
const position = gridToWorld(
|
|
4492
|
-
feature.x,
|
|
4493
|
-
feature.z ?? feature.y ?? 0,
|
|
4494
|
-
(feature.elevation ?? 0) + 0.5
|
|
4495
|
-
);
|
|
4496
|
-
const Renderer = CustomFeatureRenderer || DefaultFeatureRenderer;
|
|
4497
|
-
return /* @__PURE__ */ jsx(Renderer, { feature, position }, feature.id ?? `feature-${index}`);
|
|
4498
|
-
}),
|
|
4499
|
-
units.map((unit) => {
|
|
4500
|
-
const position = gridToWorld(
|
|
4501
|
-
unit.x ?? 0,
|
|
4502
|
-
unit.z ?? unit.y ?? 0,
|
|
4503
|
-
(unit.elevation ?? 0) + 0.5
|
|
4504
|
-
);
|
|
4505
|
-
const Renderer = CustomUnitRenderer || DefaultUnitRenderer;
|
|
4506
|
-
return /* @__PURE__ */ jsx(Renderer, { unit, position }, unit.id);
|
|
4507
|
-
}),
|
|
4508
|
-
children,
|
|
4509
|
-
/* @__PURE__ */ jsx(
|
|
4510
|
-
OrbitControls,
|
|
4511
|
-
{
|
|
4512
|
-
ref: controlsRef,
|
|
4513
|
-
target: cameraTarget,
|
|
4514
|
-
enableDamping: true,
|
|
4515
|
-
dampingFactor: 0.05,
|
|
4516
|
-
minDistance: 2,
|
|
4517
|
-
maxDistance: 100,
|
|
4518
|
-
maxPolarAngle: Math.PI / 2 - 0.1
|
|
4519
|
-
}
|
|
4520
|
-
)
|
|
4521
|
-
]
|
|
4522
|
-
}
|
|
4523
|
-
),
|
|
4524
|
-
showCoordinates && hoveredTile && /* @__PURE__ */ jsxs("div", { className: "game-canvas-3d__coordinates", children: [
|
|
4525
|
-
"X: ",
|
|
4526
|
-
hoveredTile.x,
|
|
4527
|
-
", Z: ",
|
|
4528
|
-
hoveredTile.z ?? hoveredTile.y ?? 0
|
|
4529
|
-
] }),
|
|
4530
|
-
showTileInfo && hoveredTile && /* @__PURE__ */ jsxs("div", { className: "game-canvas-3d__tile-info", children: [
|
|
4531
|
-
/* @__PURE__ */ jsx("div", { className: "tile-info__type", children: hoveredTile.type }),
|
|
4532
|
-
hoveredTile.terrain && /* @__PURE__ */ jsx("div", { className: "tile-info__terrain", children: hoveredTile.terrain })
|
|
4533
|
-
] })
|
|
4534
|
-
]
|
|
4535
|
-
}
|
|
4536
|
-
)
|
|
4537
|
-
}
|
|
4538
|
-
);
|
|
4539
|
-
}
|
|
4540
|
-
);
|
|
4541
|
-
GameCanvas3D.displayName = "GameCanvas3D";
|
|
3159
|
+
lazyThree("Camera3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3160
|
+
lazyThree("Canvas3DErrorBoundary", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3161
|
+
lazyThree("Canvas3DLoadingState", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3162
|
+
lazyThree("FeatureRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3163
|
+
lazyThree("FeatureRenderer3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3164
|
+
lazyThree("GameCanvas3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3165
|
+
lazyThree("GameCanvas3DBattleTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3166
|
+
lazyThree("GameCanvas3DCastleTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3167
|
+
lazyThree("GameCanvas3DWorldMapTemplate", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3168
|
+
lazyThree("Lighting3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3169
|
+
lazyThree("ModelLoader", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3170
|
+
lazyThree("PhysicsObject3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3171
|
+
lazyThree("Scene3D", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3172
|
+
lazyThree("TileRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
3173
|
+
lazyThree("UnitRenderer", () => import('@almadar/ui/components/organisms/game/three'));
|
|
4542
3174
|
var SuspenseConfigContext = createContext({ enabled: false });
|
|
4543
3175
|
createContext(false);
|
|
4544
3176
|
function SuspenseConfigProvider({
|
|
4545
3177
|
config,
|
|
4546
3178
|
children
|
|
4547
3179
|
}) {
|
|
4548
|
-
return
|
|
3180
|
+
return React110__default.createElement(
|
|
4549
3181
|
SuspenseConfigContext.Provider,
|
|
4550
3182
|
{ value: config },
|
|
4551
3183
|
children
|