@almadar/ui 5.141.0 → 5.142.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +1236 -1213
- package/dist/avl/index.js +263 -240
- package/dist/{avl-schema-parser-B8Onmfsu.d.cts → avl-schema-parser-DAs12kxP.d.ts} +229 -2
- package/dist/{avl-schema-parser-B8Onmfsu.d.ts → avl-schema-parser-wOkfbwAh.d.cts} +229 -2
- package/dist/components/index.cjs +1220 -1197
- package/dist/components/index.d.cts +10 -3
- package/dist/components/index.d.ts +10 -3
- package/dist/components/index.js +254 -231
- package/dist/lib/drawable/three/index.cjs +187 -22
- package/dist/lib/drawable/three/index.d.cts +14 -173
- package/dist/lib/drawable/three/index.d.ts +14 -173
- package/dist/lib/drawable/three/index.js +188 -23
- package/dist/providers/index.cjs +1119 -1096
- package/dist/providers/index.js +238 -215
- package/dist/runtime/index.cjs +1097 -1074
- package/dist/runtime/index.js +243 -220
- package/package.json +3 -3
|
@@ -1,179 +1,12 @@
|
|
|
1
|
+
import { C as CanvasPointLightConfig, I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-DAs12kxP.js';
|
|
2
|
+
export { d as Canvas3DHost, e as Canvas3DHostHandle, f as Canvas3DHostProps, d as GameCanvas3D, U as UnitAnimationState } from '../../../avl-schema-parser-DAs12kxP.js';
|
|
1
3
|
import * as React$1 from 'react';
|
|
2
4
|
import React__default, { Component, ReactNode, ErrorInfo } from 'react';
|
|
3
|
-
import { ScenePos, EventEmit, JsonObject, OrbitalSchema } from '@almadar/core';
|
|
4
5
|
import * as THREE from 'three';
|
|
5
6
|
import { QuadraticBezierCurve3 } from 'three';
|
|
6
|
-
import { D as DrawableNode } from '../../../paintDispatch-BQn5Lyx1.js';
|
|
7
7
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Canvas3DHost — the thin 3D draw-host: the `canvas` host's 3D painter backend
|
|
13
|
-
* (the R3F "vessel" behind the neutral drawables), the exact 3D analogue of the
|
|
14
|
-
* 2D `Painter2D` seam. Reached only via the lazy `@almadar/ui/.../game/three`
|
|
15
|
-
* subpath so three.js never enters a 2D bundle.
|
|
16
|
-
*
|
|
17
|
-
* The 3D twin of Canvas2D: the board authors a `drawables` list (the neutral
|
|
18
|
-
* `draw-*` children) and this host maps each descriptor through `Drawable3D` to a
|
|
19
|
-
* three.js mesh (a raw descriptor NEVER reaches `<group>{children}` — R3F throws).
|
|
20
|
-
* It owns NO game data — tiles, units, features, selection, health bars and labels
|
|
21
|
-
* are all `draw-*` children composed in `.lolo`, not props here. Only view state
|
|
22
|
-
* (camera, error boundary) is local.
|
|
23
|
-
*
|
|
24
|
-
* Camera: `isometric`/`perspective`/`top-down` frame the scene bounds (derived from
|
|
25
|
-
* the drawn descriptors); `follow`/`chase` track the neutral core `Camera.target`
|
|
26
|
-
* (forwarded as `followTarget`), falling back to the scene centre.
|
|
27
|
-
*
|
|
28
|
-
* Interaction: keyboard maps to semantic events (device-agnostic input). Pointer
|
|
29
|
-
* click/hover on neutral drawables needs a per-entity id + a scene-space raycast
|
|
30
|
-
* the descriptors don't yet carry — that hit-test is a tracked fork
|
|
31
|
-
* (docs/Almadar_Std_Game_V2_PLAN.md); the click/hover event props are accepted but
|
|
32
|
-
* not yet emitted from a raycast.
|
|
33
|
-
*
|
|
34
|
-
* @packageDocumentation
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/** Camera mode for 3D view.
|
|
38
|
-
* - `follow` tracks `followTarget` (the neutral `Camera.target`) from a fixed offset.
|
|
39
|
-
* - `chase` sits behind + above the target. */
|
|
40
|
-
type CameraMode$2 = 'isometric' | 'perspective' | 'top-down' | 'follow' | 'chase';
|
|
41
|
-
/** Map orientation */
|
|
42
|
-
type MapOrientation = 'standard' | 'rotated';
|
|
43
|
-
/** Overlay control */
|
|
44
|
-
type OverlayControl = 'default' | 'hidden' | 'minimap';
|
|
45
|
-
/** Props for GameCanvas3D component */
|
|
46
|
-
interface Canvas3DHostProps {
|
|
47
|
-
/** Additional CSS classes */
|
|
48
|
-
className?: string;
|
|
49
|
-
/** Children to render inside the 3D canvas (e.g., physics objects, custom meshes) */
|
|
50
|
-
children?: React__default.ReactNode;
|
|
51
|
-
/** Neutral drawable descriptors — the same `children` vocabulary as Canvas2D. The
|
|
52
|
-
* host maps each through `Drawable3D` to a mesh. */
|
|
53
|
-
drawables?: DrawableNode[];
|
|
54
|
-
/** Loading state indicator */
|
|
55
|
-
isLoading?: boolean;
|
|
56
|
-
/** Error state */
|
|
57
|
-
error?: string | null;
|
|
58
|
-
/** Fog of war data (accepted for API parity; presentation-only). */
|
|
59
|
-
fogOfWar?: boolean[][];
|
|
60
|
-
/** Map orientation (data attribute). */
|
|
61
|
-
orientation?: MapOrientation;
|
|
62
|
-
/** Camera mode */
|
|
63
|
-
cameraMode?: CameraMode$2;
|
|
64
|
-
/** Follow-camera target in scene space (the neutral core `Camera.target`). */
|
|
65
|
-
followTarget?: ScenePos;
|
|
66
|
-
/** Show grid */
|
|
67
|
-
showGrid?: boolean;
|
|
68
|
-
/** Show coordinates overlay (accepted for API parity). */
|
|
69
|
-
showCoordinates?: boolean;
|
|
70
|
-
/** Show tile information (accepted for API parity). */
|
|
71
|
-
showTileInfo?: boolean;
|
|
72
|
-
/** Overlay control mode (data attribute). */
|
|
73
|
-
overlay?: OverlayControl;
|
|
74
|
-
/** Enable shadows */
|
|
75
|
-
shadows?: boolean;
|
|
76
|
-
/** Background color */
|
|
77
|
-
backgroundColor?: string;
|
|
78
|
-
/** Declarative event: tile click. Emitted from a ground-plane raycast → scene cell
|
|
79
|
-
* `{ x, z }` (the FSM validates the cell). `tileId` is optional — the neutral host
|
|
80
|
-
* has no per-tile id, and the board FSMs key off the coordinate. */
|
|
81
|
-
tileClickEvent?: EventEmit<{
|
|
82
|
-
x: number;
|
|
83
|
-
z: number;
|
|
84
|
-
tileId?: string;
|
|
85
|
-
type?: string;
|
|
86
|
-
terrain?: string;
|
|
87
|
-
elevation?: number;
|
|
88
|
-
}>;
|
|
89
|
-
/** Declarative event: unit click. Emitted `{ unitId, x, z }` when the raycast lands on a
|
|
90
|
-
* cell whose descriptor carries an `id` (a tagged unit sprite). */
|
|
91
|
-
unitClickEvent?: EventEmit<{
|
|
92
|
-
unitId: string;
|
|
93
|
-
x: number;
|
|
94
|
-
z: number;
|
|
95
|
-
unitType?: string;
|
|
96
|
-
name?: string;
|
|
97
|
-
team?: string;
|
|
98
|
-
faction?: string;
|
|
99
|
-
health?: number;
|
|
100
|
-
maxHealth?: number;
|
|
101
|
-
}>;
|
|
102
|
-
/** Declarative event: feature click. Accepted; not yet emitted (see `tileClickEvent`). */
|
|
103
|
-
featureClickEvent?: EventEmit<{
|
|
104
|
-
featureId: string;
|
|
105
|
-
x: number;
|
|
106
|
-
z: number;
|
|
107
|
-
type?: string;
|
|
108
|
-
elevation?: number;
|
|
109
|
-
}>;
|
|
110
|
-
/** Declarative event: canvas (background) click. */
|
|
111
|
-
canvasClickEvent?: EventEmit<{
|
|
112
|
-
clientX: number;
|
|
113
|
-
clientY: number;
|
|
114
|
-
button: number;
|
|
115
|
-
}>;
|
|
116
|
-
/** Declarative event: tile hover. Accepted; not yet emitted (see `tileClickEvent`). */
|
|
117
|
-
tileHoverEvent?: EventEmit<{
|
|
118
|
-
tileId: string;
|
|
119
|
-
x: number;
|
|
120
|
-
z: number;
|
|
121
|
-
type?: string;
|
|
122
|
-
}>;
|
|
123
|
-
/** Declarative event: tile leave. */
|
|
124
|
-
tileLeaveEvent?: EventEmit<Record<string, never>>;
|
|
125
|
-
/** Declarative event: unit animation. */
|
|
126
|
-
unitAnimationEvent?: EventEmit<{
|
|
127
|
-
unitId: string;
|
|
128
|
-
state: string;
|
|
129
|
-
timestamp: number;
|
|
130
|
-
}>;
|
|
131
|
-
/** Declarative event: camera change. */
|
|
132
|
-
cameraChangeEvent?: EventEmit<{
|
|
133
|
-
position: {
|
|
134
|
-
x: number;
|
|
135
|
-
y: number;
|
|
136
|
-
z: number;
|
|
137
|
-
};
|
|
138
|
-
timestamp: number;
|
|
139
|
-
}>;
|
|
140
|
-
/** Loading message */
|
|
141
|
-
loadingMessage?: string;
|
|
142
|
-
/** Unit draw-size multiplier (accepted for API parity; sizing is drawable-authored). */
|
|
143
|
-
unitScale?: number;
|
|
144
|
-
/** Board zoom (accepted for API parity; 3D zoom is camera-driven, not group-scaled). */
|
|
145
|
-
scale?: number;
|
|
146
|
-
/** Maps a keydown `e.code` → the board's SEMANTIC event (device-agnostic input). */
|
|
147
|
-
keyMap?: Record<string, string>;
|
|
148
|
-
/** Maps a keyup `e.code` → the board's SEMANTIC event. */
|
|
149
|
-
keyUpMap?: Record<string, string>;
|
|
150
|
-
/** Side-view world size in pixels (accepted for API parity). */
|
|
151
|
-
worldWidth?: number;
|
|
152
|
-
/** Side-view world size in pixels (accepted for API parity). */
|
|
153
|
-
worldHeight?: number;
|
|
154
|
-
/** Pixel→world-unit divisor for pixel-authored (side-view) scenes: world size =
|
|
155
|
-
* scene size ÷ `pixelsPerUnit`. Omitted → 1 world unit per scene unit (grid boards). */
|
|
156
|
-
pixelsPerUnit?: number;
|
|
157
|
-
/** Perspective field of view in degrees — the neutral `Camera.fov`. Default 45. */
|
|
158
|
-
fov?: number;
|
|
159
|
-
}
|
|
160
|
-
/** Imperative handle for GameCanvas3D */
|
|
161
|
-
interface Canvas3DHostHandle {
|
|
162
|
-
/** Get current camera position */
|
|
163
|
-
getCameraPosition: () => THREE.Vector3 | null;
|
|
164
|
-
/** Set camera position */
|
|
165
|
-
setCameraPosition: (x: number, y: number, z: number) => void;
|
|
166
|
-
/** Look at a specific point */
|
|
167
|
-
lookAt: (x: number, y: number, z: number) => void;
|
|
168
|
-
/** Reset camera to default position */
|
|
169
|
-
resetCamera: () => void;
|
|
170
|
-
/** Take a screenshot */
|
|
171
|
-
screenshot: () => string | null;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Canvas3DHost — thin 3D draw-host. Walks `drawables` through `Drawable3D`.
|
|
175
|
-
*/
|
|
176
|
-
declare const Canvas3DHost: React__default.ForwardRefExoticComponent<Canvas3DHostProps & React__default.RefAttributes<Canvas3DHostHandle>>;
|
|
8
|
+
import { JsonObject, EventEmit, OrbitalSchema } from '@almadar/core';
|
|
9
|
+
import '../../../paintDispatch-BQn5Lyx1.js';
|
|
177
10
|
|
|
178
11
|
/**
|
|
179
12
|
* Scene3D
|
|
@@ -291,6 +124,14 @@ interface Lighting3DProps {
|
|
|
291
124
|
directionalColor?: string;
|
|
292
125
|
/** Directional light position */
|
|
293
126
|
directionalPosition?: [number, number, number];
|
|
127
|
+
/** Hemisphere (sky/ground) light intensity */
|
|
128
|
+
hemisphereIntensity?: number;
|
|
129
|
+
/** Hemisphere sky color */
|
|
130
|
+
hemisphereColor?: string;
|
|
131
|
+
/** Hemisphere ground color */
|
|
132
|
+
hemisphereGroundColor?: string;
|
|
133
|
+
/** Additional point lights, authored as data */
|
|
134
|
+
points?: CanvasPointLightConfig[];
|
|
294
135
|
/** Enable shadows */
|
|
295
136
|
shadows?: boolean;
|
|
296
137
|
/** Shadow map size */
|
|
@@ -324,7 +165,7 @@ interface Lighting3DProps {
|
|
|
324
165
|
* </Canvas>
|
|
325
166
|
* ```
|
|
326
167
|
*/
|
|
327
|
-
declare function Lighting3D({ ambientIntensity, ambientColor, directionalIntensity, directionalColor, directionalPosition, shadows, shadowMapSize, shadowCameraSize, shadowBias, shadowNormalBias, shadowCameraNear, shadowCameraFar, showHelpers, }: Lighting3DProps): React__default.JSX.Element;
|
|
168
|
+
declare function Lighting3D({ ambientIntensity, ambientColor, directionalIntensity, directionalColor, directionalPosition, hemisphereIntensity, hemisphereColor, hemisphereGroundColor, points, shadows, shadowMapSize, shadowCameraSize, shadowBias, shadowNormalBias, shadowCameraNear, shadowCameraFar, showHelpers, }: Lighting3DProps): React__default.JSX.Element;
|
|
328
169
|
|
|
329
170
|
/**
|
|
330
171
|
* Canvas3DLoadingState
|
|
@@ -1485,4 +1326,4 @@ declare const CAMERA_POSITIONS: {
|
|
|
1485
1326
|
};
|
|
1486
1327
|
};
|
|
1487
1328
|
|
|
1488
|
-
export { AVL_3D_COLORS, AssetLoader, type AssetLoadingState, Avl3DApplicationScene, type Avl3DApplicationSceneProps, type Avl3DConfig, Avl3DContext, Avl3DEffects, type Avl3DEffectsProps, type Avl3DModelOverrides, Avl3DOrbitalScene, type Avl3DOrbitalSceneProps, Avl3DTraitScene, type Avl3DTraitSceneProps, Avl3DTransitionScene, type Avl3DTransitionSceneProps, Avl3DViewer, type Avl3DViewerProps, CAMERA_POSITIONS, Camera3D, type Camera3DHandle, type Camera3DProps, type CameraMode$1 as CameraMode, Canvas3DErrorBoundary, type Canvas3DErrorBoundaryProps, type Canvas3DErrorBoundaryState,
|
|
1329
|
+
export { AVL_3D_COLORS, AssetLoader, type AssetLoadingState, Avl3DApplicationScene, type Avl3DApplicationSceneProps, type Avl3DConfig, Avl3DContext, Avl3DEffects, type Avl3DEffectsProps, type Avl3DModelOverrides, Avl3DOrbitalScene, type Avl3DOrbitalSceneProps, Avl3DTraitScene, type Avl3DTraitSceneProps, Avl3DTransitionScene, type Avl3DTransitionSceneProps, Avl3DViewer, type Avl3DViewerProps, CAMERA_POSITIONS, Camera3D, type Camera3DHandle, type Camera3DProps, type CameraMode$1 as CameraMode, Canvas3DErrorBoundary, type Canvas3DErrorBoundaryProps, type Canvas3DErrorBoundaryState, Canvas3DLoadingState, type Canvas3DLoadingStateProps, type CullingOptions, type GameCanvas3DEventConfig, type Grid3DConfig, type GridCoordinate, type GridHit, type LODConfig, type LODLevel, Lighting3D, type Lighting3DProps, type LoadedModel, ModelLoader, type ModelLoaderProps, type NodeType, type Position3D, type RaycastHit, Scene3D, type Scene3DProps, type SceneGraphNode, SpatialHashGrid, type UseAssetLoaderOptions, type UseAssetLoaderReturn, type UseGameCanvas3DEventsOptions, type UseGameCanvas3DEventsReturn, type UseRaycasterOptions, type UseRaycasterReturn, type UseSceneGraphReturn, type UseThreeOptions, type UseThreeReturn, arcCurve3D, assetLoader, calculateLODLevel, createGridHighlight, cullInstancedMesh, fibonacciSpherePositions, filterByFrustum, getCellsInRadius, getNeighbors, getVisibleIndices, goldenSpiralPositions, gridDistance, gridManhattanDistance, gridToWorld, isInBounds, isInFrustum, normalizeMouseCoordinates, orbitRingPositions, raycastToObjects, raycastToPlane, selfLoopCurve3D, treeLayout3D, updateInstanceLOD, useAssetLoader, useAvl3DConfig, useGameCanvas3DEvents, useRaycaster, useSceneGraph, useThree, worldToGrid };
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React3, { forwardRef, useRef, useState,
|
|
1
|
+
import React3, { forwardRef, useRef, useState, useMemo, useEffect, useImperativeHandle, useCallback, createContext, useContext, Component, useReducer } from 'react';
|
|
2
2
|
import { EventBusContext, useTraitScopeChain } from '@almadar/ui/providers';
|
|
3
3
|
import { createLogger } from '@almadar/logger';
|
|
4
4
|
import { Canvas, useThree, useFrame } from '@react-three/fiber';
|
|
5
5
|
import * as THREE10 from 'three';
|
|
6
6
|
import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
|
|
7
|
+
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
|
|
7
8
|
import { Grid, OrbitControls, Billboard, Text, Stars, Sparkles, Html, RoundedBox } from '@react-three/drei';
|
|
8
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
+
import { Bloom, Vignette, EffectComposer, DepthOfField } from '@react-three/postprocessing';
|
|
9
11
|
import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
10
12
|
import { clone } from 'three/examples/jsm/utils/SkeletonUtils';
|
|
11
13
|
import { clsx } from 'clsx';
|
|
@@ -13,7 +15,6 @@ import { twMerge } from 'tailwind-merge';
|
|
|
13
15
|
import { OrbitControls as OrbitControls$1 } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
14
16
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
15
17
|
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
|
|
16
|
-
import { EffectComposer, Bloom, DepthOfField, Vignette } from '@react-three/postprocessing';
|
|
17
18
|
import { useTranslate } from '@almadar/ui/hooks';
|
|
18
19
|
|
|
19
20
|
var __defProp = Object.defineProperty;
|
|
@@ -450,6 +451,10 @@ function Lighting3D({
|
|
|
450
451
|
directionalIntensity = 0.8,
|
|
451
452
|
directionalColor = "#ffffff",
|
|
452
453
|
directionalPosition = [10, 20, 10],
|
|
454
|
+
hemisphereIntensity = 0.3,
|
|
455
|
+
hemisphereColor = "#87ceeb",
|
|
456
|
+
hemisphereGroundColor = "#362d1d",
|
|
457
|
+
points,
|
|
453
458
|
shadows = true,
|
|
454
459
|
shadowMapSize = 2048,
|
|
455
460
|
shadowCameraSize = 20,
|
|
@@ -482,11 +487,22 @@ function Lighting3D({
|
|
|
482
487
|
/* @__PURE__ */ jsx(
|
|
483
488
|
"hemisphereLight",
|
|
484
489
|
{
|
|
485
|
-
intensity:
|
|
486
|
-
color:
|
|
487
|
-
groundColor:
|
|
490
|
+
intensity: hemisphereIntensity,
|
|
491
|
+
color: hemisphereColor,
|
|
492
|
+
groundColor: hemisphereGroundColor
|
|
488
493
|
}
|
|
489
494
|
),
|
|
495
|
+
points?.map((p, i) => /* @__PURE__ */ jsx(
|
|
496
|
+
"pointLight",
|
|
497
|
+
{
|
|
498
|
+
position: p.position,
|
|
499
|
+
intensity: p.intensity,
|
|
500
|
+
color: p.color,
|
|
501
|
+
distance: p.distance,
|
|
502
|
+
decay: p.decay
|
|
503
|
+
},
|
|
504
|
+
i
|
|
505
|
+
)),
|
|
490
506
|
showHelpers && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
|
|
491
507
|
"directionalLightHelper",
|
|
492
508
|
{
|
|
@@ -498,6 +514,36 @@ function Lighting3D({
|
|
|
498
514
|
) })
|
|
499
515
|
] });
|
|
500
516
|
}
|
|
517
|
+
function Effects3D({ post }) {
|
|
518
|
+
if (!post || !post.bloom && !post.vignette) return null;
|
|
519
|
+
const passes = [];
|
|
520
|
+
if (post.bloom) {
|
|
521
|
+
passes.push(
|
|
522
|
+
/* @__PURE__ */ jsx(
|
|
523
|
+
Bloom,
|
|
524
|
+
{
|
|
525
|
+
intensity: post.bloom.intensity ?? 1,
|
|
526
|
+
luminanceThreshold: post.bloom.threshold ?? 0.9,
|
|
527
|
+
luminanceSmoothing: post.bloom.smoothing ?? 0.3
|
|
528
|
+
},
|
|
529
|
+
"bloom"
|
|
530
|
+
)
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
if (post.vignette) {
|
|
534
|
+
passes.push(
|
|
535
|
+
/* @__PURE__ */ jsx(
|
|
536
|
+
Vignette,
|
|
537
|
+
{
|
|
538
|
+
offset: post.vignette.offset ?? 0.3,
|
|
539
|
+
darkness: post.vignette.darkness ?? 0.6
|
|
540
|
+
},
|
|
541
|
+
"vignette"
|
|
542
|
+
)
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
return /* @__PURE__ */ jsx(EffectComposer, { children: passes });
|
|
546
|
+
}
|
|
501
547
|
function CameraController3D({
|
|
502
548
|
onCameraChange
|
|
503
549
|
}) {
|
|
@@ -540,6 +586,77 @@ function create3DProjector(opts = {}) {
|
|
|
540
586
|
toWorld: (pos) => [pos.x * cellSize + offsetX, pos.z ?? 0, pos.y * cellSize + offsetZ]
|
|
541
587
|
};
|
|
542
588
|
}
|
|
589
|
+
var NUMERIC_TRACKS = [
|
|
590
|
+
"offsetX",
|
|
591
|
+
"offsetY",
|
|
592
|
+
"rotate",
|
|
593
|
+
"opacity",
|
|
594
|
+
"radiusX",
|
|
595
|
+
"radiusY",
|
|
596
|
+
"width",
|
|
597
|
+
"height",
|
|
598
|
+
"strokeWidth",
|
|
599
|
+
"strokeDashOffset",
|
|
600
|
+
"blur"
|
|
601
|
+
];
|
|
602
|
+
function isAnimatedShape(node) {
|
|
603
|
+
return Boolean(node.animation && node.animation.durationMs > 0 && node.animation.keyframes.length > 0);
|
|
604
|
+
}
|
|
605
|
+
var lerp = (a, b, k) => a + (b - a) * k;
|
|
606
|
+
function applyShapeAnimation(node, timeMs) {
|
|
607
|
+
const anim = node.animation;
|
|
608
|
+
if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return node;
|
|
609
|
+
const frames = [...anim.keyframes].sort((a, b) => a.at - b.at);
|
|
610
|
+
const cycle = timeMs / anim.durationMs;
|
|
611
|
+
const t = anim.loop === false ? Math.min(cycle, 1) : cycle - Math.floor(cycle);
|
|
612
|
+
const out = { ...node };
|
|
613
|
+
const trackValue = (key) => {
|
|
614
|
+
const defined = frames.filter((f) => f[key] !== void 0);
|
|
615
|
+
if (defined.length === 0) return void 0;
|
|
616
|
+
let prev;
|
|
617
|
+
let next;
|
|
618
|
+
for (const f of defined) {
|
|
619
|
+
if (f.at <= t) prev = f;
|
|
620
|
+
else if (!next) next = f;
|
|
621
|
+
}
|
|
622
|
+
if (!prev) return defined[0][key];
|
|
623
|
+
if (!next) return prev[key];
|
|
624
|
+
const span = next.at - prev.at;
|
|
625
|
+
const k = span > 0 ? (t - prev.at) / span : 1;
|
|
626
|
+
const a = prev[key];
|
|
627
|
+
const b = next[key];
|
|
628
|
+
if (typeof a === "number" && typeof b === "number") return lerp(a, b, k);
|
|
629
|
+
return a;
|
|
630
|
+
};
|
|
631
|
+
for (const key of NUMERIC_TRACKS) {
|
|
632
|
+
const v = trackValue(key);
|
|
633
|
+
if (v !== void 0) out[key] = v;
|
|
634
|
+
}
|
|
635
|
+
const fill = trackValue("fill");
|
|
636
|
+
if (fill !== void 0) out.fill = fill;
|
|
637
|
+
const stroke = trackValue("stroke");
|
|
638
|
+
if (stroke !== void 0) out.stroke = stroke;
|
|
639
|
+
const shadowFrames = frames.filter((f) => f.shadow !== void 0);
|
|
640
|
+
if (shadowFrames.length > 0) {
|
|
641
|
+
const sh = trackValue("shadow");
|
|
642
|
+
if (sh !== void 0) {
|
|
643
|
+
let prevSh;
|
|
644
|
+
let nextSh;
|
|
645
|
+
for (const f of shadowFrames) {
|
|
646
|
+
if (f.at <= t) prevSh = f;
|
|
647
|
+
else if (!nextSh) nextSh = f;
|
|
648
|
+
}
|
|
649
|
+
if (prevSh?.shadow && nextSh?.shadow) {
|
|
650
|
+
const span = nextSh.at - prevSh.at;
|
|
651
|
+
const k = span > 0 ? (t - prevSh.at) / span : 1;
|
|
652
|
+
out.shadow = { color: prevSh.shadow.color, blur: lerp(prevSh.shadow.blur, nextSh.shadow.blur, k) };
|
|
653
|
+
} else {
|
|
654
|
+
out.shadow = sh;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return out;
|
|
659
|
+
}
|
|
543
660
|
|
|
544
661
|
// lib/atlasSlice.ts
|
|
545
662
|
var atlasCache = /* @__PURE__ */ new Map();
|
|
@@ -941,8 +1058,27 @@ function Sprite3D({ node, projector, groupOpacity = 1 }) {
|
|
|
941
1058
|
return /* @__PURE__ */ jsx(SpriteBillboard, { node, world: projector.toWorld(node.position), cellSize: projector.cellSize, groupOpacity });
|
|
942
1059
|
}
|
|
943
1060
|
function Shape3D({ node, projector, groupOpacity = 1 }) {
|
|
944
|
-
|
|
945
|
-
const
|
|
1061
|
+
const groupRef = React3.useRef(null);
|
|
1062
|
+
const materialRef = React3.useRef(null);
|
|
1063
|
+
const animated = isAnimatedShape(node);
|
|
1064
|
+
const validPos = isValidScenePos(node.position);
|
|
1065
|
+
const world = validPos ? projector.toWorld(node.position) : [0, 0, 0];
|
|
1066
|
+
useFrame(({ clock }) => {
|
|
1067
|
+
if (!animated || !groupRef.current) return;
|
|
1068
|
+
const view = applyShapeAnimation(node, clock.elapsedTime * 1e3);
|
|
1069
|
+
groupRef.current.position.set(
|
|
1070
|
+
world[0] + (view.offsetX ?? 0) * projector.cellSize,
|
|
1071
|
+
world[1] + 0.02,
|
|
1072
|
+
world[2] + (view.offsetY ?? 0) * projector.cellSize
|
|
1073
|
+
);
|
|
1074
|
+
groupRef.current.rotation.y = -(view.rotate ?? 0);
|
|
1075
|
+
const mat = materialRef.current;
|
|
1076
|
+
if (mat) {
|
|
1077
|
+
mat.opacity = (view.opacity ?? node.opacity ?? 1) * groupOpacity;
|
|
1078
|
+
if (view.fill) mat.color.set(view.fill);
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
if (!validPos) return null;
|
|
946
1082
|
const color = node.fill ?? node.stroke ?? "#ffffff";
|
|
947
1083
|
let geometry;
|
|
948
1084
|
switch (node.shape) {
|
|
@@ -976,12 +1112,12 @@ function Shape3D({ node, projector, groupOpacity = 1 }) {
|
|
|
976
1112
|
default:
|
|
977
1113
|
return null;
|
|
978
1114
|
}
|
|
979
|
-
return /* @__PURE__ */
|
|
1115
|
+
return /* @__PURE__ */ jsx("group", { ref: groupRef, position: [world[0], world[1] + 0.02, world[2]], children: /* @__PURE__ */ jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], children: [
|
|
980
1116
|
geometry,
|
|
981
|
-
/* @__PURE__ */ jsx("meshBasicMaterial", { color, transparent: true, opacity: (node.opacity ?? 1) * groupOpacity, side: THREE10.DoubleSide })
|
|
982
|
-
] });
|
|
1117
|
+
/* @__PURE__ */ jsx("meshBasicMaterial", { ref: materialRef, color, transparent: true, opacity: (node.opacity ?? 1) * groupOpacity, side: THREE10.DoubleSide })
|
|
1118
|
+
] }) });
|
|
983
1119
|
}
|
|
984
|
-
function Text3D({ node, projector }) {
|
|
1120
|
+
function Text3D({ node, projector, groupOpacity = 1 }) {
|
|
985
1121
|
if (!isValidScenePos(node.position)) return null;
|
|
986
1122
|
const world = projector.toWorld(node.position);
|
|
987
1123
|
return /* @__PURE__ */ jsx(Billboard, { position: [world[0], world[1] + 1.2, world[2]], children: /* @__PURE__ */ jsx(
|
|
@@ -993,6 +1129,8 @@ function Text3D({ node, projector }) {
|
|
|
993
1129
|
anchorY: "middle",
|
|
994
1130
|
outlineWidth: 0.02,
|
|
995
1131
|
outlineColor: "#000000",
|
|
1132
|
+
fillOpacity: groupOpacity,
|
|
1133
|
+
outlineOpacity: groupOpacity,
|
|
996
1134
|
children: node.text
|
|
997
1135
|
}
|
|
998
1136
|
) });
|
|
@@ -1005,8 +1143,8 @@ function clampSegments(segments) {
|
|
|
1005
1143
|
function isAnimatedMesh(node) {
|
|
1006
1144
|
return Boolean(node.animation && node.animation.durationMs > 0 && node.animation.keyframes.length > 0);
|
|
1007
1145
|
}
|
|
1008
|
-
var
|
|
1009
|
-
var
|
|
1146
|
+
var lerp2 = (a, b, k) => a + (b - a) * k;
|
|
1147
|
+
var NUMERIC_TRACKS2 = [
|
|
1010
1148
|
"offsetX",
|
|
1011
1149
|
"offsetY",
|
|
1012
1150
|
"offsetZ",
|
|
@@ -1038,11 +1176,11 @@ function applyMeshAnimation(node, timeMs) {
|
|
|
1038
1176
|
const k = span > 0 ? (t - prev.at) / span : 1;
|
|
1039
1177
|
const a = prev[key];
|
|
1040
1178
|
const b = next[key];
|
|
1041
|
-
if (typeof a === "number" && typeof b === "number") return
|
|
1179
|
+
if (typeof a === "number" && typeof b === "number") return lerp2(a, b, k);
|
|
1042
1180
|
return a;
|
|
1043
1181
|
};
|
|
1044
1182
|
const num = {};
|
|
1045
|
-
for (const key of
|
|
1183
|
+
for (const key of NUMERIC_TRACKS2) {
|
|
1046
1184
|
const v = trackValue(key);
|
|
1047
1185
|
if (v !== void 0) num[key] = v;
|
|
1048
1186
|
}
|
|
@@ -1216,7 +1354,7 @@ function Drawable3D({ node, projector, groupOpacity = 1 }) {
|
|
|
1216
1354
|
case "draw-shape":
|
|
1217
1355
|
return /* @__PURE__ */ jsx(Shape3D, { node, projector, groupOpacity });
|
|
1218
1356
|
case "draw-text":
|
|
1219
|
-
return /* @__PURE__ */ jsx(Text3D, { node, projector });
|
|
1357
|
+
return /* @__PURE__ */ jsx(Text3D, { node, projector, groupOpacity });
|
|
1220
1358
|
case "draw-mesh":
|
|
1221
1359
|
return /* @__PURE__ */ jsx(Mesh3D, { node, projector, groupOpacity });
|
|
1222
1360
|
case "draw-sprite-layer":
|
|
@@ -1224,7 +1362,7 @@ function Drawable3D({ node, projector, groupOpacity = 1 }) {
|
|
|
1224
1362
|
case "draw-shape-layer":
|
|
1225
1363
|
return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Shape3D, { node: item, projector, groupOpacity }, i)) });
|
|
1226
1364
|
case "draw-text-layer":
|
|
1227
|
-
return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Text3D, { node: item, projector }, i)) });
|
|
1365
|
+
return /* @__PURE__ */ jsx(Fragment, { children: node.items.map((item, i) => /* @__PURE__ */ jsx(Text3D, { node: item, projector, groupOpacity }, i)) });
|
|
1228
1366
|
case "draw-group": {
|
|
1229
1367
|
if (!isValidScenePos(node.position) || !Array.isArray(node.items)) return null;
|
|
1230
1368
|
if (node.clip) warnUnsupported3d("draw-group:clip");
|
|
@@ -1248,6 +1386,20 @@ function cn(...inputs) {
|
|
|
1248
1386
|
}
|
|
1249
1387
|
var DEFAULT_GRID_CONFIG = {
|
|
1250
1388
|
cellSize: 1};
|
|
1389
|
+
function RoomEnvironment3D() {
|
|
1390
|
+
const { gl, scene } = useThree(({ gl: gl2, scene: scene2 }) => ({ gl: gl2, scene: scene2 }));
|
|
1391
|
+
useEffect(() => {
|
|
1392
|
+
const pmremGenerator = new THREE10.PMREMGenerator(gl);
|
|
1393
|
+
const envTexture = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;
|
|
1394
|
+
scene.environment = envTexture;
|
|
1395
|
+
return () => {
|
|
1396
|
+
scene.environment = null;
|
|
1397
|
+
envTexture.dispose();
|
|
1398
|
+
pmremGenerator.dispose();
|
|
1399
|
+
};
|
|
1400
|
+
}, [gl, scene]);
|
|
1401
|
+
return null;
|
|
1402
|
+
}
|
|
1251
1403
|
var Canvas3DHost = forwardRef(
|
|
1252
1404
|
({
|
|
1253
1405
|
cameraMode = "isometric",
|
|
@@ -1273,6 +1425,8 @@ var Canvas3DHost = forwardRef(
|
|
|
1273
1425
|
keyUpMap,
|
|
1274
1426
|
pixelsPerUnit,
|
|
1275
1427
|
fov,
|
|
1428
|
+
lighting,
|
|
1429
|
+
post,
|
|
1276
1430
|
children,
|
|
1277
1431
|
drawables
|
|
1278
1432
|
}, ref) => {
|
|
@@ -1281,6 +1435,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1281
1435
|
const [internalError, setInternalError] = useState(null);
|
|
1282
1436
|
const eventBus = useEventBus();
|
|
1283
1437
|
const keysRef = useRef(/* @__PURE__ */ new Set());
|
|
1438
|
+
const allDrawables = useMemo(() => drawables ?? [], [drawables]);
|
|
1284
1439
|
useEffect(() => {
|
|
1285
1440
|
if (!keyMap && !keyUpMap) return;
|
|
1286
1441
|
const down = (e) => {
|
|
@@ -1314,7 +1469,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1314
1469
|
unitAnimationEvent,
|
|
1315
1470
|
cameraChangeEvent
|
|
1316
1471
|
});
|
|
1317
|
-
const drawnItems = useMemo(() => collectDrawnItems(
|
|
1472
|
+
const drawnItems = useMemo(() => collectDrawnItems(allDrawables), [allDrawables]);
|
|
1318
1473
|
const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
|
|
1319
1474
|
const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
|
|
1320
1475
|
const gridBounds = useMemo(() => {
|
|
@@ -1496,9 +1651,19 @@ var Canvas3DHost = forwardRef(
|
|
|
1496
1651
|
shadowNormalBias: 0.04,
|
|
1497
1652
|
shadowCameraSize: 5,
|
|
1498
1653
|
shadowCameraNear: 0.5,
|
|
1499
|
-
shadowCameraFar: 500
|
|
1654
|
+
shadowCameraFar: 500,
|
|
1655
|
+
ambientIntensity: lighting?.ambient?.intensity,
|
|
1656
|
+
ambientColor: lighting?.ambient?.color,
|
|
1657
|
+
directionalIntensity: lighting?.directional?.intensity,
|
|
1658
|
+
directionalColor: lighting?.directional?.color,
|
|
1659
|
+
directionalPosition: lighting?.directional?.position,
|
|
1660
|
+
hemisphereIntensity: lighting?.hemisphere?.intensity,
|
|
1661
|
+
hemisphereColor: lighting?.hemisphere?.color,
|
|
1662
|
+
hemisphereGroundColor: lighting?.hemisphere?.groundColor,
|
|
1663
|
+
points: lighting?.points
|
|
1500
1664
|
}
|
|
1501
1665
|
),
|
|
1666
|
+
lighting?.environment === "room" && /* @__PURE__ */ jsx(RoomEnvironment3D, {}),
|
|
1502
1667
|
showGrid && /* @__PURE__ */ jsx(
|
|
1503
1668
|
Grid,
|
|
1504
1669
|
{
|
|
@@ -1521,7 +1686,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1521
1686
|
fadeStrength: 1
|
|
1522
1687
|
}
|
|
1523
1688
|
),
|
|
1524
|
-
|
|
1689
|
+
allDrawables.length > 0 && /* @__PURE__ */ jsx("group", { children: allDrawables.map((node, i) => /* @__PURE__ */ jsx(Drawable3D, { node, projector: drawableProjector }, i)) }),
|
|
1525
1690
|
(tileClickEvent || unitClickEvent) && /* @__PURE__ */ jsxs(
|
|
1526
1691
|
"mesh",
|
|
1527
1692
|
{
|
|
@@ -1546,7 +1711,7 @@ var Canvas3DHost = forwardRef(
|
|
|
1546
1711
|
]
|
|
1547
1712
|
}
|
|
1548
1713
|
),
|
|
1549
|
-
|
|
1714
|
+
post && (post.bloom || post.vignette) ? /* @__PURE__ */ jsx(Effects3D, { post }) : null,
|
|
1550
1715
|
/* @__PURE__ */ jsx(
|
|
1551
1716
|
OrbitControls,
|
|
1552
1717
|
{
|
|
@@ -1896,7 +2061,7 @@ var DEFAULT_OPTIONS = {
|
|
|
1896
2061
|
gridSize: 20,
|
|
1897
2062
|
assetLoader: new AssetLoader()
|
|
1898
2063
|
};
|
|
1899
|
-
function
|
|
2064
|
+
function useThree5(options = {}) {
|
|
1900
2065
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1901
2066
|
const containerRef = useRef(null);
|
|
1902
2067
|
const canvasRef = useRef(null);
|
|
@@ -5710,4 +5875,4 @@ var Avl3DViewer = ({
|
|
|
5710
5875
|
};
|
|
5711
5876
|
Avl3DViewer.displayName = "Avl3DViewer";
|
|
5712
5877
|
|
|
5713
|
-
export { AVL_3D_COLORS, AssetLoader, Avl3DApplicationScene, Avl3DContext, Avl3DEffects, Avl3DOrbitalScene, Avl3DTraitScene, Avl3DTransitionScene, Avl3DViewer, CAMERA_POSITIONS, Camera3D, Canvas3DErrorBoundary, Canvas3DHost, Canvas3DLoadingState, Canvas3DHost as GameCanvas3D, Lighting3D, ModelLoader, Scene3D, SpatialHashGrid, arcCurve3D, assetLoader, calculateLODLevel, createGridHighlight, cullInstancedMesh, fibonacciSpherePositions, filterByFrustum, getCellsInRadius, getNeighbors, getVisibleIndices, goldenSpiralPositions, gridDistance, gridManhattanDistance, gridToWorld, isInBounds, isInFrustum, normalizeMouseCoordinates, orbitRingPositions, raycastToObjects, raycastToPlane, selfLoopCurve3D, treeLayout3D, updateInstanceLOD, useAssetLoader, useAvl3DConfig, useGameCanvas3DEvents, useRaycaster, useSceneGraph,
|
|
5878
|
+
export { AVL_3D_COLORS, AssetLoader, Avl3DApplicationScene, Avl3DContext, Avl3DEffects, Avl3DOrbitalScene, Avl3DTraitScene, Avl3DTransitionScene, Avl3DViewer, CAMERA_POSITIONS, Camera3D, Canvas3DErrorBoundary, Canvas3DHost, Canvas3DLoadingState, Canvas3DHost as GameCanvas3D, Lighting3D, ModelLoader, Scene3D, SpatialHashGrid, arcCurve3D, assetLoader, calculateLODLevel, createGridHighlight, cullInstancedMesh, fibonacciSpherePositions, filterByFrustum, getCellsInRadius, getNeighbors, getVisibleIndices, goldenSpiralPositions, gridDistance, gridManhattanDistance, gridToWorld, isInBounds, isInFrustum, normalizeMouseCoordinates, orbitRingPositions, raycastToObjects, raycastToPlane, selfLoopCurve3D, treeLayout3D, updateInstanceLOD, useAssetLoader, useAvl3DConfig, useGameCanvas3DEvents, useRaycaster, useSceneGraph, useThree5 as useThree, worldToGrid };
|