mbt-3d 0.3.8 → 0.4.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/README.md +48 -11
- package/dist/index.d.ts +51 -9
- package/dist/mbt-3d.cjs +1 -1
- package/dist/mbt-3d.cjs.map +1 -1
- package/dist/mbt-3d.js +710 -657
- package/dist/mbt-3d.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm install react react-dom three @react-three/fiber @react-three/drei
|
|
|
21
21
|
- @react-three/fiber >= 8.0.0
|
|
22
22
|
- @react-three/drei >= 9.0.0
|
|
23
23
|
|
|
24
|
-
## Local Development
|
|
24
|
+
## Local Development
|
|
25
25
|
|
|
26
26
|
For local development and testing with another project:
|
|
27
27
|
|
|
@@ -51,13 +51,50 @@ npm unlink
|
|
|
51
51
|
|
|
52
52
|
**Alternative: Use file: protocol**
|
|
53
53
|
```json
|
|
54
|
-
{
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"mbt-3d": "file:../path/to/mbt-3d"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
{
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"mbt-3d": "file:../path/to/mbt-3d"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Lighting and HDRI
|
|
62
|
+
|
|
63
|
+
`Scene3D` supports mixed lighting:
|
|
64
|
+
|
|
65
|
+
- `lights` and `environment` (HDRI) can be used together.
|
|
66
|
+
- `environment.intensity` controls scene environment intensity.
|
|
67
|
+
- `environment.blur` controls HDRI background blur when HDRI background is enabled.
|
|
68
|
+
- `renderer` accepts multiple parameters at once (`physicallyCorrectLights`, `outputColorSpace`, `toneMapping`, `toneMappingExposure`).
|
|
69
|
+
- Shadow-casting lights use `shadowMapSize: 2048` by default (override per light if needed).
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<Scene3D
|
|
73
|
+
lights={[
|
|
74
|
+
{ type: 'ambient', intensity: 0.4 },
|
|
75
|
+
{ type: 'spot', position: [5, 8, 5], intensity: 120, castShadow: true, shadowMapSize: 2048 }
|
|
76
|
+
]}
|
|
77
|
+
environment={{
|
|
78
|
+
files: '/hdri/studio.hdr',
|
|
79
|
+
intensity: 1.2,
|
|
80
|
+
blur: 0.15,
|
|
81
|
+
background: false
|
|
82
|
+
}}
|
|
83
|
+
renderer={{
|
|
84
|
+
physicallyCorrectLights: true,
|
|
85
|
+
outputColorSpace: 'srgb',
|
|
86
|
+
toneMapping: 'ACESFilmicToneMapping',
|
|
87
|
+
toneMappingExposure: 1
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</Scene3D>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Demo workflow
|
|
95
|
+
|
|
96
|
+
In `TextureUploadDemo`, designers can configure model/textures + HDRI + dynamic lights + renderer settings, then use `Copy Scene Settings` to export JSON preset for integration into the main app scene props.
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -185,6 +185,8 @@ export declare interface AnimatedModelProps extends Omit<ModelProps, 'onLoad'> {
|
|
|
185
185
|
children?: React.ReactNode;
|
|
186
186
|
/** Name of animation to play on load (auto-plays first if not specified) */
|
|
187
187
|
defaultAnimation?: string;
|
|
188
|
+
/** Controlled animation name. When changed, AnimatedModel switches to this animation */
|
|
189
|
+
animation?: string;
|
|
188
190
|
/** Morph target values as key-value pairs { targetName: value } where value is 0-1 */
|
|
189
191
|
morphTargets?: Record<string, number>;
|
|
190
192
|
/** Mesh visibility as key-value pairs { meshName: visible }. Example: { "Hairgirl1": true, "Hairgirl2": false } */
|
|
@@ -268,7 +270,7 @@ export declare interface BoneAttachmentProps {
|
|
|
268
270
|
*
|
|
269
271
|
* @example
|
|
270
272
|
* ```tsx
|
|
271
|
-
* { type: 'directional', position: [10, 20, 10], intensity: 40, castShadow: true }
|
|
273
|
+
* { type: 'directional', position: [10, 20, 10], intensity: 40, castShadow: true, shadowMapSize: 2048 }
|
|
272
274
|
* ```
|
|
273
275
|
*/
|
|
274
276
|
declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
@@ -277,11 +279,17 @@ declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
|
277
279
|
position?: [number, number, number];
|
|
278
280
|
/** Enable shadow casting. Default: true */
|
|
279
281
|
castShadow?: boolean;
|
|
282
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
283
|
+
shadowMapSize?: number;
|
|
280
284
|
}
|
|
281
285
|
|
|
282
286
|
/**
|
|
283
287
|
* Environment (HDRI) configuration for realistic lighting and reflections
|
|
284
288
|
*
|
|
289
|
+
* @remarks
|
|
290
|
+
* Works together with `lights` (they are not mutually exclusive).
|
|
291
|
+
* `intensity` and `blur` are applied to the active scene environment/background.
|
|
292
|
+
*
|
|
285
293
|
* @example
|
|
286
294
|
* ```tsx
|
|
287
295
|
* { files: '/scenes/studio.hdr', intensity: 1, background: false }
|
|
@@ -290,11 +298,11 @@ declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
|
290
298
|
declare interface EnvironmentConfig {
|
|
291
299
|
/** URL to HDRI file (.hdr or .exr) */
|
|
292
300
|
files: string;
|
|
293
|
-
/** Environment intensity multiplier. Default: 1 */
|
|
301
|
+
/** Environment intensity multiplier for scene environment. Default: 1 */
|
|
294
302
|
intensity?: number;
|
|
295
303
|
/** Use HDRI as scene background. Default: false */
|
|
296
304
|
background?: boolean;
|
|
297
|
-
/**
|
|
305
|
+
/** Background blur amount (0-1). Default: 0 */
|
|
298
306
|
blur?: number;
|
|
299
307
|
}
|
|
300
308
|
|
|
@@ -570,7 +578,7 @@ export declare interface MorphableModelProps extends ModelProps {
|
|
|
570
578
|
*
|
|
571
579
|
* @example
|
|
572
580
|
* ```tsx
|
|
573
|
-
* { type: 'point', position: [0, 5, 0], intensity: 20, color: '#ffaa00' }
|
|
581
|
+
* { type: 'point', position: [0, 5, 0], intensity: 20, color: '#ffaa00', castShadow: true, shadowMapSize: 2048 }
|
|
574
582
|
* ```
|
|
575
583
|
*/
|
|
576
584
|
declare interface PointLightConfig extends BaseLightConfig {
|
|
@@ -583,10 +591,30 @@ declare interface PointLightConfig extends BaseLightConfig {
|
|
|
583
591
|
decay?: number;
|
|
584
592
|
/** Enable shadow casting. Default: false */
|
|
585
593
|
castShadow?: boolean;
|
|
594
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
595
|
+
shadowMapSize?: number;
|
|
586
596
|
}
|
|
587
597
|
|
|
588
598
|
export declare function preloadModel(url: string): void;
|
|
589
599
|
|
|
600
|
+
/**
|
|
601
|
+
* WebGL renderer settings for light response and color mapping.
|
|
602
|
+
* Useful for physically based lighting tests.
|
|
603
|
+
*
|
|
604
|
+
* @remarks
|
|
605
|
+
* All fields can be provided together in one `renderer` object.
|
|
606
|
+
*/
|
|
607
|
+
export declare interface RendererConfig {
|
|
608
|
+
/** Toggle physically-correct light attenuation model */
|
|
609
|
+
physicallyCorrectLights?: boolean;
|
|
610
|
+
/** Output color space. Default: 'srgb' */
|
|
611
|
+
outputColorSpace?: 'srgb' | 'linear';
|
|
612
|
+
/** Tone mapping operator. Default: 'ACESFilmicToneMapping' */
|
|
613
|
+
toneMapping?: ToneMappingMode;
|
|
614
|
+
/** Tone mapping exposure. Default: 1 */
|
|
615
|
+
toneMappingExposure?: number;
|
|
616
|
+
}
|
|
617
|
+
|
|
590
618
|
/**
|
|
591
619
|
* Scene3D - Main 3D scene container with built-in canvas, lighting, and controls
|
|
592
620
|
*
|
|
@@ -607,6 +635,7 @@ export declare function preloadModel(url: string): void;
|
|
|
607
635
|
* @param controls.enablePan - Enable camera panning with middle mouse. Default: `true`
|
|
608
636
|
* @param controls.enableZoom - Enable camera zoom with scroll wheel. Default: `true`
|
|
609
637
|
* @param controls.enableRotate - Enable camera rotation with left mouse. Default: `true`
|
|
638
|
+
* @param controls.target - Orbit target point [x, y, z]. Camera looks at this point. Default: `[0, 0, 0]`
|
|
610
639
|
* @param controls.minDistance - Minimum zoom distance. Example: `2`
|
|
611
640
|
* @param controls.maxDistance - Maximum zoom distance. Example: `10`
|
|
612
641
|
* @param controls.minPolarAngle - Minimum vertical rotation angle in radians. Example: `Math.PI / 4`
|
|
@@ -615,7 +644,9 @@ export declare function preloadModel(url: string): void;
|
|
|
615
644
|
* @param controls.autoRotateSpeed - Auto-rotation speed. Default: `2`
|
|
616
645
|
* @param background - Background: image URL (e.g., `"/bg.jpg"`) or hex color (e.g., `"#1a1a2e"`)
|
|
617
646
|
* @param shadows - Enable shadow rendering. Default: `true`
|
|
618
|
-
* @param lights - Array of light configurations. Supports spot, point, directional, hemisphere, and ambient lights. Default: `[{ type: 'ambient', intensity: 0.5 }, { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true }]`
|
|
647
|
+
* @param lights - Array of light configurations. Supports spot, point, directional, hemisphere, and ambient lights. Shadow-casting lights support `shadowMapSize` (default: `2048`). Default: `[{ type: 'ambient', intensity: 0.5 }, { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true }]`
|
|
648
|
+
* @param environment - Optional HDRI environment config. Works together with `lights` (combined lighting), not as a replacement.
|
|
649
|
+
* @param renderer - Optional renderer tuning for tone mapping, exposure, output color space and physically-correct lights. All options can be set together in one object.
|
|
619
650
|
* @param contactShadows - Contact shadows configuration. Can be `true` for default settings or object with custom settings. Example: `{ position: [0, -1, 0], opacity: 0.5, blur: 2 }`
|
|
620
651
|
* @param contactShadows.position - Shadow position as [x, y, z]. Example: `[0, -1, 0]`. Default: `[0, -1, 0]`
|
|
621
652
|
* @param contactShadows.opacity - Shadow opacity (0-1). Example: `0.5`. Default: `0.5`
|
|
@@ -642,7 +673,7 @@ export declare function preloadModel(url: string): void;
|
|
|
642
673
|
* <Scene3D
|
|
643
674
|
* camera={{ position: [0, 2, 5], fov: 45 }}
|
|
644
675
|
* lights={[
|
|
645
|
-
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true },
|
|
676
|
+
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true, shadowMapSize: 2048 },
|
|
646
677
|
* { type: 'spot', position: [-5, 10, -5], intensity: 30, castShadow: false },
|
|
647
678
|
* { type: 'point', position: [0, 5, 0], intensity: 20 },
|
|
648
679
|
* { type: 'ambient', intensity: 0.3 }
|
|
@@ -666,7 +697,7 @@ export declare function preloadModel(url: string): void;
|
|
|
666
697
|
* </Scene3D>
|
|
667
698
|
* ```
|
|
668
699
|
*/
|
|
669
|
-
export declare function Scene3D({ children, camera, controls, background, shadows, lights, environment, contactShadows, showLoadingOverlay, style, className, }: Scene3DProps): JSX_2.Element;
|
|
700
|
+
export declare function Scene3D({ children, camera, controls, background, shadows, lights, environment, renderer, contactShadows, showLoadingOverlay, style, className, }: Scene3DProps): JSX_2.Element;
|
|
670
701
|
|
|
671
702
|
/**
|
|
672
703
|
* Props for Scene3D component
|
|
@@ -699,6 +730,8 @@ export declare interface Scene3DProps {
|
|
|
699
730
|
};
|
|
700
731
|
/** OrbitControls configuration for camera rotation */
|
|
701
732
|
controls?: {
|
|
733
|
+
/** Orbit target point [x, y, z]. Camera will look at this point. Default: [0, 0, 0] */
|
|
734
|
+
target?: [number, number, number];
|
|
702
735
|
/** Enable/disable all controls. Default: true */
|
|
703
736
|
enabled?: boolean;
|
|
704
737
|
/** Enable camera panning (middle mouse). Default: true */
|
|
@@ -726,8 +759,13 @@ export declare interface Scene3DProps {
|
|
|
726
759
|
shadows?: boolean;
|
|
727
760
|
/** Array of light configurations for multi-light setup */
|
|
728
761
|
lights?: LightConfigUnion[];
|
|
729
|
-
/**
|
|
762
|
+
/**
|
|
763
|
+
* Environment (HDRI) configuration for realistic lighting and reflections.
|
|
764
|
+
* Can be combined with `lights` for mixed lighting setups.
|
|
765
|
+
*/
|
|
730
766
|
environment?: EnvironmentConfig;
|
|
767
|
+
/** Optional renderer tuning (physically-correct lights, tone mapping, exposure, output color space). */
|
|
768
|
+
renderer?: RendererConfig;
|
|
731
769
|
/** Contact shadows configuration (ground shadows under models) */
|
|
732
770
|
contactShadows?: boolean | {
|
|
733
771
|
/** Shadow position [x, y, z]. Default: [0, -1, 0] */
|
|
@@ -750,7 +788,7 @@ export declare interface Scene3DProps {
|
|
|
750
788
|
*
|
|
751
789
|
* @example
|
|
752
790
|
* ```tsx
|
|
753
|
-
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true }
|
|
791
|
+
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true, shadowMapSize: 2048 }
|
|
754
792
|
* ```
|
|
755
793
|
*/
|
|
756
794
|
declare interface SpotLightConfig extends BaseLightConfig {
|
|
@@ -759,6 +797,8 @@ declare interface SpotLightConfig extends BaseLightConfig {
|
|
|
759
797
|
position?: [number, number, number];
|
|
760
798
|
/** Enable shadow casting. Default: true */
|
|
761
799
|
castShadow?: boolean;
|
|
800
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
801
|
+
shadowMapSize?: number;
|
|
762
802
|
/** Cone angle in radians. Default: Math.PI / 6 */
|
|
763
803
|
angle?: number;
|
|
764
804
|
/** Penumbra (soft edges) 0-1. Default: 0.5 */
|
|
@@ -769,6 +809,8 @@ declare interface SpotLightConfig extends BaseLightConfig {
|
|
|
769
809
|
distance?: number;
|
|
770
810
|
}
|
|
771
811
|
|
|
812
|
+
export declare type ToneMappingMode = 'NoToneMapping' | 'LinearToneMapping' | 'ReinhardToneMapping' | 'CineonToneMapping' | 'ACESFilmicToneMapping';
|
|
813
|
+
|
|
772
814
|
export declare function useAnimationController(animations: THREE.AnimationClip[], scene: THREE.Object3D, options?: UseAnimationControllerOptions): {
|
|
773
815
|
playAnimation: (name: string, opts?: {
|
|
774
816
|
loop?: boolean;
|
package/dist/mbt-3d.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),I=require("@react-three/drei"),ne=require("three"),ae=require("three/examples/jsm/utils/SkeletonUtils.js"),B=require("@react-three/fiber"),ie=require("three/examples/jsm/loaders/KTX2Loader.js"),M=require("react/jsx-runtime");function Q(t){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const a=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(r,o,a.get?a:{enumerable:!0,get:()=>t[o]})}}return r.default=t,Object.freeze(r)}const R=Q(ne),ee=Q(ae);function le({position:t,controlsConfig:r}){const{camera:o}=B.useThree(),a=e.useRef(null);return e.useEffect(()=>{t&&o&&(o.position.set(t[0],t[1],t[2]),o.updateProjectionMatrix(),a.current&&(a.current.target.set(0,0,0),a.current.update()))},[t,o]),M.jsx(I.OrbitControls,{ref:a,makeDefault:!0,enabled:r.enabled,enablePan:r.enablePan,enableZoom:r.enableZoom,enableRotate:r.enableRotate,minDistance:r.minDistance,maxDistance:r.maxDistance,minPolarAngle:r.minPolarAngle,maxPolarAngle:r.maxPolarAngle,autoRotate:r.autoRotate,autoRotateSpeed:r.autoRotateSpeed})}function ce({background:t}){const r=t==null?void 0:t.startsWith("#");return t?r?M.jsx("color",{attach:"background",args:[t]}):M.jsx(ue,{url:t}):null}function ue({url:t}){const r=I.useTexture(t);return e.useMemo(()=>{r.colorSpace=R.SRGBColorSpace},[r]),M.jsx("primitive",{attach:"background",object:r})}function fe({config:t}){return M.jsx(I.Environment,{files:t.files,background:t.background??!1,blur:t.blur??0,children:M.jsx("group",{scale:t.intensity??1,children:M.jsx("ambientLight",{intensity:0})})})}function me({config:t}){switch(t.type){case"spot":{const{position:r=[5,10,5],intensity:o=50,castShadow:a=!0,angle:c=Math.PI/6,penumbra:g=.5,decay:y=2,distance:T=0,color:h="#ffffff"}=t;return M.jsx("spotLight",{position:r,intensity:o,castShadow:a,angle:c,penumbra:g,decay:y,distance:T,color:h})}case"point":{const{position:r=[0,5,0],intensity:o=20,color:a="#ffffff",distance:c=0,decay:g=2,castShadow:y=!1}=t;return M.jsx("pointLight",{position:r,intensity:o,color:a,distance:c,decay:g,castShadow:y})}case"directional":{const{position:r=[10,20,10],intensity:o=40,color:a="#ffffff",castShadow:c=!0}=t;return M.jsx("directionalLight",{position:r,intensity:o,color:a,castShadow:c})}case"hemisphere":{const{skyColor:r="#ffffff",groundColor:o="#444444",intensity:a=.5,position:c=[0,10,0]}=t,g=e.useMemo(()=>new R.Color(r),[r]),y=e.useMemo(()=>new R.Color(o),[o]);return M.jsx("hemisphereLight",{args:[g,y,a],position:c})}case"ambient":{const{intensity:r=.5,color:o="#ffffff"}=t;return M.jsx("ambientLight",{intensity:r,color:o})}default:return null}}function pe({onChange:t}){const{active:r,progress:o}=I.useProgress();return e.useEffect(()=>{t(r,o)},[r,o,t]),null}function de({children:t,camera:r={},controls:o={},background:a,shadows:c=!0,lights:g=[{type:"ambient",intensity:.5},{type:"spot",position:[5,10,5],intensity:50,castShadow:!0}],environment:y,contactShadows:T=!0,showLoadingOverlay:h=!0,style:n,className:i}){const[u,m]=e.useState(!1),[b,s]=e.useState(0),l=e.useRef(null),f=e.useCallback((E,d)=>{if(E){l.current!==null&&(window.clearTimeout(l.current),l.current=null),m(!0),s(Math.max(0,Math.min(100,Math.round(d))));return}s(100),l.current=window.setTimeout(()=>{m(!1),s(0),l.current=null},200)},[]);e.useEffect(()=>()=>{l.current!==null&&window.clearTimeout(l.current)},[]);const S={position:r.position||[0,2,5],fov:r.fov||45},p={enabled:o.enabled??!0,enablePan:o.enablePan??!0,enableZoom:o.enableZoom??!0,enableRotate:o.enableRotate??!0,minDistance:o.minDistance,maxDistance:o.maxDistance,minPolarAngle:o.minPolarAngle,maxPolarAngle:o.maxPolarAngle,autoRotate:o.autoRotate??!1,autoRotateSpeed:o.autoRotateSpeed??2},A=typeof T=="object"?{position:T.position||[0,-1,0],opacity:T.opacity??.5,blur:T.blur??2}:T?{position:[0,-1,0],opacity:.5,blur:2}:null;return M.jsxs("div",{style:{...n||{},position:(n==null?void 0:n.position)??"relative"},className:i,children:[M.jsxs(B.Canvas,{shadows:c,camera:{position:S.position,fov:S.fov},style:{width:"100%",height:"100%"},children:[M.jsx(e.Suspense,{fallback:null,children:M.jsx(ce,{background:a})}),y&&M.jsx(e.Suspense,{fallback:null,children:M.jsx(fe,{config:y})}),g.map((E,d)=>M.jsx(me,{config:E},`${E.type}-${d}`)),M.jsx(e.Suspense,{fallback:null,children:t}),M.jsx(le,{position:S.position,controlsConfig:p}),A&&M.jsx(I.ContactShadows,{position:A.position,opacity:A.opacity,blur:A.blur}),M.jsx(pe,{onChange:f})]}),h&&u&&M.jsx("div",{style:{position:"absolute",inset:0,background:"rgba(8, 10, 16, 0.46)",display:"flex",alignItems:"center",justifyContent:"center",pointerEvents:"none",zIndex:10},children:M.jsxs("div",{style:{minWidth:220,padding:"16px 18px",borderRadius:14,border:"1px solid rgba(255,255,255,0.2)",background:"linear-gradient(180deg, rgba(18,24,36,0.9), rgba(13,17,27,0.9))",color:"#eef3ff",boxShadow:"0 10px 30px rgba(0,0,0,0.35)",fontFamily:"system-ui, -apple-system, Segoe UI, sans-serif",textAlign:"center"},children:[M.jsx("div",{style:{display:"flex",justifyContent:"center",marginBottom:10},children:M.jsxs("svg",{width:"34",height:"34",viewBox:"0 0 34 34","aria-hidden":"true",children:[M.jsx("circle",{cx:"17",cy:"17",r:"14",fill:"none",stroke:"rgba(255,255,255,0.2)",strokeWidth:"4"}),M.jsx("path",{d:"M31 17a14 14 0 0 1-14 14",fill:"none",stroke:"#67b4ff",strokeWidth:"4",strokeLinecap:"round",children:M.jsx("animateTransform",{attributeName:"transform",type:"rotate",from:"0 17 17",to:"360 17 17",dur:"0.9s",repeatCount:"indefinite"})})]})}),M.jsxs("div",{style:{fontSize:12,opacity:.82,marginTop:4},children:[b,"%"]})]})})]})}function K(t,r){const o=e.useRef(new Map),a=e.useRef({}),c=e.useRef({});e.useEffect(()=>{r&&(a.current={...r})},[r]),e.useEffect(()=>{if(!t)return;const h=new Map;t.traverse(n=>{if(n.isMesh){const i=n;i.name&&h.set(i.name,i)}}),o.current=h},[t]),B.useFrame(()=>{const h=o.current;if(h.size===0)return;const n={...a.current,...c.current};for(const[i,u]of Object.entries(n)){const m=h.get(i);m&&m.visible!==u&&(m.visible=u)}});const g=e.useCallback((h,n)=>{c.current[h]=n;const i=o.current.get(h);i&&(i.visible=n)},[]),y=e.useCallback(()=>Array.from(o.current.keys()).sort(),[]),T=e.useCallback(()=>{const h={};return o.current.forEach((n,i)=>{h[i]=n.visible}),h},[]);return{setMeshVisibility:g,getMeshNames:y,getMeshVisibility:T}}function G(t,r){const o=e.useRef(new Map),a=e.useRef(new Map);e.useEffect(()=>{if(!t)return;const n=new Map;t.traverse(i=>{if(i.isMesh){const u=i;(Array.isArray(u.material)?u.material:[u.material]).forEach(b=>{b.name&&!n.has(b.name)&&n.set(b.name,b)})}}),o.current=n,r&&Object.entries(r).forEach(([i,u])=>{const m=n.get(i);if(m&&!Array.isArray(m)){const b=c(u);m.color&&m.color.copy(b),a.current.set(i,b)}})},[t,r]),B.useFrame(()=>{a.current.forEach((n,i)=>{const u=o.current.get(i);if(u&&!Array.isArray(u)){const m=u;m.color&&!m.color.equals(n)&&(m.color.copy(n),m.needsUpdate=!0)}})});const c=n=>typeof n=="string"?new R.Color(n):new R.Color(n[0],n[1],n[2]),g=e.useCallback((n,i)=>{const u=c(i);a.current.set(n,u);const m=o.current.get(n);if(m&&!Array.isArray(m)){const b=m;b.color&&(b.color.copy(u),b.needsUpdate=!0)}},[]),y=e.useCallback(()=>Array.from(o.current.keys()).sort(),[]),T=e.useCallback(n=>{const i=o.current.get(n);if(i&&!Array.isArray(i)){const u=i;if(u.color)return"#"+u.color.getHexString()}return null},[]),h=e.useCallback(()=>{const n={};return o.current.forEach((i,u)=>{if(!Array.isArray(i)){const m=i;m.color&&(n[u]="#"+m.color.getHexString())}}),n},[]);return{setMaterialColor:g,getMaterialNames:y,getMaterialColor:T,getAllMaterialColors:h}}function H(t){const r=t.toLowerCase();if(r.endsWith(".ktx2"))return!0;try{const o=new URL(t,window.location.origin),a=decodeURIComponent(o.hash.replace(/^#/,"")).toLowerCase(),c=decodeURIComponent(o.search).toLowerCase(),g=decodeURIComponent(o.pathname).toLowerCase();return a.endsWith(".ktx2")||c.includes(".ktx2")||g.endsWith(".ktx2")}catch{return r.includes(".ktx2")}}function z(t,r){const{gl:o}=B.useThree(),a=e.useRef(new Map),c=e.useRef(new R.TextureLoader),g=e.useRef(null),y=e.useRef(new Map),T=e.useRef(new Set),h=e.useRef("");e.useEffect(()=>{if(!g.current)try{const s=typeof WebAssembly=="object"&&typeof WebAssembly.validate=="function";console.log("[useMaterialTexture] Browser features:"),console.log(` WebAssembly supported: ${s}`),console.log(` WebGL2: ${o.capabilities.isWebGL2}`);const l=new ie.KTX2Loader;l.setTranscoderPath("/basis/"),l.detectSupport(o),g.current=l,console.log("[useMaterialTexture] ✅ KTX2Loader initialized"),console.log("[useMaterialTexture] Transcoder path: /basis/"),fetch("/basis/basis_transcoder.wasm").then(f=>{f.ok?console.log("[useMaterialTexture] ✅ basis_transcoder.wasm is accessible"):console.error("[useMaterialTexture] ❌ basis_transcoder.wasm returned",f.status)}).catch(f=>{console.error("[useMaterialTexture] ❌ Failed to check basis_transcoder.wasm:",f)}),s||(console.warn("[useMaterialTexture] ⚠️ WebAssembly not supported! KTX2 will fallback to CPU decoding (slow)"),console.warn("[useMaterialTexture] ⚠️ Recommend using WebP instead of KTX2 for this browser"))}catch(s){console.error("[useMaterialTexture] ❌ Failed to initialize KTX2Loader:",s)}return()=>{g.current&&(g.current.dispose(),g.current=null)}},[o]),e.useEffect(()=>{if(!t)return;const s=new Map;t.traverse(l=>{if(l.isMesh){const f=l;(Array.isArray(f.material)?f.material:[f.material]).forEach(p=>{p.name&&!s.has(p.name)&&s.set(p.name,p)})}}),a.current=s},[t]);const n=e.useCallback(s=>H(s)?g.current?g.current:(console.warn("[useMaterialTexture] KTX2Loader not initialized, falling back to TextureLoader"),c.current):c.current,[]);e.useEffect(()=>{if(!r||!t)return;const s=a.current;if(s.size===0)return;const l=JSON.stringify(r);if(h.current===l){console.log("[useMaterialTexture] Textures unchanged, skipping reload");return}h.current=l;let f=!1;const S=new Map;Object.entries(r).forEach(([d,w])=>{S.set(d,typeof w=="string"?{map:w}:w)}),console.log("[useMaterialTexture] Starting texture load for",S.size,"materials");const p=[];S.forEach((d,w)=>{var v,L;const N=s.get(w);if(!N||!N.isMeshStandardMaterial){console.warn(`[useMaterialTexture] Material "${w}" not found or not MeshStandardMaterial`);return}const x=N;console.log(`[useMaterialTexture] 📋 Material "${w}" BEFORE reset:`),console.log(` - map: ${x.map?"EXISTS":"null"} ${x.map?`(uuid: ${x.map.uuid})`:""}`),console.log(` - normalMap: ${x.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${x.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${x.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${x.emissiveMap?"EXISTS":"null"}`),console.log(` - aoMap: ${x.aoMap?"EXISTS":"null"}`),console.log(` - color: ${(v=x.color)==null?void 0:v.getHexString()}`),console.log(` - emissive: ${(L=x.emissive)==null?void 0:L.getHexString()}`),console.log(` - material uuid: ${x.uuid}`),Object.entries(d).forEach(([$,j])=>{if(!j)return;const C=$,k=x[C];k&&(console.log(`[useMaterialTexture] 🗑️ Disposing old ${C} (uuid: ${k.uuid})`),k.dispose(),x[C]=null)}),d.emissiveMap&&(x.emissive=new R.Color(0),x.emissiveIntensity=0),x.needsUpdate=!0,x.color=new R.Color(16777215),console.log(`[useMaterialTexture] ✅ Material "${w}" AFTER reset: only specified maps cleared`),Object.entries(d).forEach(([$,j])=>{if(!j)return;const C=`${w}_${$}_${j}`,k=y.current.get(C);if(k){console.log(`[useMaterialTexture] Using cached texture: ${w}.${$}`),f||i(x,$,k);return}if(T.current.has(C)){console.log(`[useMaterialTexture] Skipping already loading: ${w}.${$}`);return}p.push({materialName:w,textureType:$,url:j,material:x})})}),console.log(`[useMaterialTexture] Queued ${p.length} textures to load`);let A=0;const E=()=>{if(f||A>=p.length){console.log("[useMaterialTexture] ✅ All textures loaded"),console.log("[useMaterialTexture] 📊 FINAL material states:"),s.forEach((v,L)=>{var j,C;const $=v;console.log(` Material "${L}":`),console.log(` - map: ${$.map?"EXISTS":"null"} ${$.map?`(colorSpace: ${$.map.colorSpace})`:""}`),console.log(` - normalMap: ${$.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${$.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${$.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${$.emissiveMap?"EXISTS":"null"}`),console.log(` - color: ${(j=$.color)==null?void 0:j.getHexString()}`),console.log(` - emissive: ${(C=$.emissive)==null?void 0:C.getHexString()}`),console.log(` - emissiveIntensity: ${$.emissiveIntensity}`),console.log(` - roughness: ${$.roughness}`),console.log(` - metalness: ${$.metalness}`)});return}const d=p[A++],w=`${d.materialName}_${d.textureType}_${d.url}`;console.log(`[useMaterialTexture] Loading (${A}/${p.length}): ${d.materialName}.${d.textureType} from ${d.url}`),T.current.add(w);const N=n(d.url),x=H(d.url)?"KTX2Loader":"TextureLoader";console.log(`[useMaterialTexture] Using ${x} for ${d.url}`),N.load(d.url,v=>{var C,k,D,P,O,W;if(T.current.delete(w),f){console.log(`[useMaterialTexture] Disposed, cleaning up texture: ${d.materialName}.${d.textureType}`),v.dispose();return}const L=((C=v.image)==null?void 0:C.width)||((D=(k=v.source)==null?void 0:k.data)==null?void 0:D.width)||"unknown",$=((P=v.image)==null?void 0:P.height)||((W=(O=v.source)==null?void 0:O.data)==null?void 0:W.height)||"unknown";console.log(`[useMaterialTexture] ✅ Loaded: ${d.materialName}.${d.textureType} (${L}x${$})`),v.colorSpace=d.textureType==="map"||d.textureType==="emissiveMap"?R.SRGBColorSpace:R.NoColorSpace,v.wrapS=R.RepeatWrapping,v.wrapT=R.RepeatWrapping,v.flipY=!1,y.current.set(w,v),i(d.material,d.textureType,v);const j=H(d.url)?500:150;console.log(`[useMaterialTexture] Waiting111111 ${j}ms before next texture...`),setTimeout(E,0)},v=>{if(v.lengthComputable){const L=Math.round(v.loaded/v.total*100);L%25===0&&console.log(`[useMaterialTexture] Progress ${d.materialName}.${d.textureType}: ${L}%`)}},v=>{T.current.delete(w),f||(console.error(`[useMaterialTexture] ❌ Failed to load ${d.materialName}.${d.textureType} from ${d.url}`),console.error("[useMaterialTexture] Error details:",v),console.error("[useMaterialTexture] Loader type:",x),H(d.url)&&(console.error("[useMaterialTexture] KTX2 error - file may not be in Basis Universal format!"),console.error("[useMaterialTexture] Make sure files are created with: gltf-transform etc1s input.png output.ktx2"))),setTimeout(E,100)})};return E(),()=>{console.log("[useMaterialTexture] Cleanup: disposed"),f=!0}},[t,r,n]);const i=(s,l,f)=>{var S,p;switch(console.log(`[useMaterialTexture] 🎨 Applying texture: ${s.name}.${l} (texture uuid: ${f.uuid})`),l){case"map":s.map=f;break;case"normalMap":s.normalMap=f;break;case"roughnessMap":s.roughnessMap=f;break;case"metalnessMap":s.metalnessMap=f;break;case"emissiveMap":s.emissiveMap=f,s.emissive=new R.Color(16777215),s.emissiveIntensity=1;break;case"alphaMap":console.log(`[useMaterialTexture] Skipping alphaMap for "${s.name}" to prevent disappearing`);break;case"aoMap":s.aoMap=f;break}s.needsUpdate=!0,console.log(`[useMaterialTexture] ✅ Applied ${l} to ${s.name}, needsUpdate=true`),console.log(`[useMaterialTexture] 📊 Material "${s.name}" FINAL state:`),console.log(` - map: ${s.map?"EXISTS":"null"} ${s.map?`(uuid: ${s.map.uuid}, colorSpace: ${s.map.colorSpace})`:""}`),console.log(` - normalMap: ${s.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${s.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${s.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${s.emissiveMap?"EXISTS":"null"}`),console.log(` - aoMap: ${s.aoMap?"EXISTS":"null"}`),console.log(` - color: ${(S=s.color)==null?void 0:S.getHexString()}`),console.log(` - emissive: ${(p=s.emissive)==null?void 0:p.getHexString()}`),console.log(` - emissiveIntensity: ${s.emissiveIntensity}`),console.log(` - roughness: ${s.roughness}`),console.log(` - metalness: ${s.metalness}`)},u=e.useCallback((s,l)=>{const f=typeof l=="string"?{map:l}:l,S=a.current.get(s);if(!S||!S.isMeshStandardMaterial){console.warn(`Material "${s}" not found or not MeshStandardMaterial`);return}const p=S;Object.entries(f).forEach(([A,E])=>{if(!E)return;const d=`${s}_${A}_${E}`,w=y.current.get(d);if(w){i(p,A,w);return}n(E).load(E,x=>{x.colorSpace=A==="map"||A==="emissiveMap"?R.SRGBColorSpace:R.NoColorSpace,x.wrapS=R.RepeatWrapping,x.wrapT=R.RepeatWrapping,y.current.set(d,x),i(p,A,x)},void 0,x=>{console.error(`Failed to load texture ${E}:`,x)})})},[n]),m=e.useCallback(()=>Array.from(a.current.keys()).sort(),[]),b=e.useCallback(s=>{const l=a.current.get(s);if(!l||!l.isMeshStandardMaterial)return;const f=l;f.map=null,f.normalMap=null,f.roughnessMap=null,f.metalnessMap=null,f.emissiveMap=null,f.alphaMap=null,f.aoMap=null,f.needsUpdate=!0},[]);return{setMaterialTextures:u,getMaterialNames:m,clearMaterialTextures:b}}function te({url:t,position:r=[0,0,0],rotation:o=[0,0,0],scale:a=1,meshVisibility:c,materialColors:g,materialTextures:y,onLoad:T,onError:h}){const{scene:n}=I.useGLTF(t),i=e.useRef(T);i.current=T;const u=e.useMemo(()=>{const b=n.clone();console.log("[Model] 🔍 Scene clone created, checking materials...");const s=[],l=new Set,f=[];let S=0;return b.traverse(p=>{if(S++,p.type==="Bone"&&f.push(p.name),p.isMesh){const A=p;s.push(A.name),A.castShadow=!0,A.receiveShadow=!0,(Array.isArray(A.material)?A.material:[A.material]).forEach(d=>{l.add(d.name),console.log(`[Model] 📦 Material found: "${d.name}" (uuid: ${d.uuid})`);const w=d;console.log(` - Has map: ${w.map?"YES":"NO"}`),console.log(` - Has normalMap: ${w.normalMap?"YES":"NO"}`),console.log(` - Has roughnessMap: ${w.roughnessMap?"YES":"NO"}`),console.log(` - Has metalnessMap: ${w.metalnessMap?"YES":"NO"}`)})}}),console.log(`[Model] 📊 Clone summary: ${s.length} meshes, ${l.size} materials`),setTimeout(()=>{var p;(p=i.current)==null||p.call(i,{meshes:s.sort(),materials:Array.from(l).sort(),bones:f.sort(),nodeCount:S})},0),b},[n]);K(u,c),G(u,g),z(u,y);const m=typeof a=="number"?[a,a,a]:a;return M.jsx("group",{position:r,rotation:o,scale:m,children:M.jsx("primitive",{object:u})})}te.preload=t=>{I.useGLTF.preload(t)};function re(t,r,o){const{actions:a,names:c}=I.useAnimations(t,r),g=e.useRef(null),y=e.useRef(o==null?void 0:o.defaultAnimation);e.useEffect(()=>{if(c.length===0)return;const i=y.current;let u=c[0];if(i){const b=c.find(s=>s===i||s.includes(i));b&&(u=b)}const m=a[u];m&&(m.reset().fadeIn(.5).play(),g.current=m)},[a,c]);const T=e.useCallback((i,u)=>{const{loop:m=!1,crossFadeDuration:b=.2,restoreDefault:s=!0}=u||{};let l=a[i];if(!l){const S=Object.keys(a).find(p=>p.toLowerCase().includes(i.toLowerCase())||i.toLowerCase().includes(p.toLowerCase()));S&&(l=a[S])}if(!l){console.warn(`Animation "${i}" not found. Available: ${c.join(", ")}`);return}const f=g.current;if(!(f===l&&l.isRunning())&&(f&&f!==l&&f.fadeOut(b),l.reset(),l.fadeIn(b),l.setLoop(m?R.LoopRepeat:R.LoopOnce,m?1/0:1),l.clampWhenFinished=!m,l.play(),m||l.getMixer().update(0),g.current=l,s&&!m&&y.current)){const S=l.getMixer(),p=A=>{if(A.action===l){S.removeEventListener("finished",p);const E=a[y.current];E&&(l.fadeOut(b),E.reset().fadeIn(b).play(),g.current=E)}};S.addEventListener("finished",p)}},[a,c]),h=e.useCallback(()=>{var i;(i=g.current)==null||i.fadeOut(.2),g.current=null},[]),n=e.useCallback(()=>c,[c]);return{playAnimation:T,stopAnimation:h,getAnimationNames:n,actions:a}}function q(t,r){const o=e.useRef(r||{}),a=e.useRef([]),c=e.useRef([]);e.useEffect(()=>{const h=new Set,n=[];t.traverse(i=>{i instanceof R.Mesh&&i.morphTargetDictionary&&i.morphTargetInfluences&&(n.push(i),Object.keys(i.morphTargetDictionary).forEach(u=>{h.add(u)}))}),a.current=Array.from(h).sort(),c.current=n},[t]),B.useFrame(()=>{const h=o.current;c.current.forEach(n=>{!n.morphTargetDictionary||!n.morphTargetInfluences||Object.entries(h).forEach(([i,u])=>{const m=n.morphTargetDictionary[i];m!==void 0&&(n.morphTargetInfluences[m]=u)})})}),e.useEffect(()=>{r&&(o.current={...r})},[r]);const g=e.useCallback((h,n)=>{o.current[h]=Math.max(0,Math.min(1,n))},[]),y=e.useCallback(()=>a.current,[]),T=e.useCallback(()=>({...o.current}),[]);return{setMorphTarget:g,getMorphTargetNames:y,getMorphTargetValues:T}}const oe=e.createContext(null);function ge(){const t=e.useContext(oe);if(!t)throw new Error("BoneAttachment must be used within an AnimatedModel");return t}const V=e.forwardRef(({url:t,position:r=[0,0,0],rotation:o=[0,0,0],scale:a=1,defaultAnimation:c,morphTargets:g,meshVisibility:y,materialColors:T,materialTextures:h,onLoad:n,onError:i,children:u},m)=>{const b=e.useRef(null),s=e.useRef([]),l=e.useRef(n);l.current=n;const{scene:f,animations:S}=I.useGLTF(t),p=e.useMemo(()=>ee.clone(f),[f]),{playAnimation:A,stopAnimation:E,getAnimationNames:d}=re(S,p,{defaultAnimation:c}),{setMorphTarget:w}=q(p,g),{setMeshVisibility:N,getMeshNames:x}=K(p,y),{setMaterialColor:v,getMaterialNames:L,getMaterialColor:$}=G(p,T),{setMaterialTextures:j,clearMaterialTextures:C}=z(p,h);e.useEffect(()=>{if(!p)return;const P=setTimeout(()=>{var J;const O=[],W=[],_=new Set,Y=new Set;let Z=0;p.traverse(F=>{if(Z++,F.type==="Bone"&&O.push(F.name),F.isMesh){const X=F;W.push(X.name),X.castShadow=!0,X.receiveShadow=!0,(Array.isArray(X.material)?X.material:[X.material]).forEach(U=>{_.add(U.name),U.shadowSide=R.DoubleSide}),X.morphTargetDictionary&&Object.keys(X.morphTargetDictionary).forEach(U=>{Y.add(U)})}}),s.current=Array.from(Y).sort(),(J=l.current)==null||J.call(l,{meshes:W.sort(),materials:Array.from(_).sort(),bones:O.sort(),nodeCount:Z,animations:S.map(F=>F.name),morphTargetNames:s.current})},0);return()=>clearTimeout(P)},[p,S]),e.useImperativeHandle(m,()=>({playAnimation:A,stopAnimation:E,getAnimationNames:d,getGroup:()=>b.current,setMorphTarget:w,getMorphTargetNames:()=>s.current,setMeshVisibility:N,getMeshNames:x,setMaterialColor:v,getMaterialNames:L,getMaterialColor:$,setMaterialTextures:j,clearMaterialTextures:C}));const k=e.useMemo(()=>({scene:p,getBone:P=>p.getObjectByName(P)||null}),[p]),D=typeof a=="number"?[a,a,a]:a;return M.jsx(oe.Provider,{value:k,children:M.jsxs("group",{ref:b,position:r,rotation:o,scale:D,children:[M.jsx("primitive",{object:p}),u]})})});V.displayName="AnimatedModel";V.preload=t=>{I.useGLTF.preload(t)};const se=e.forwardRef(({url:t,position:r=[0,0,0],rotation:o=[0,0,0],scale:a=1,morphTargets:c,meshVisibility:g,materialColors:y,materialTextures:T,onMorphTargetsFound:h,onLoad:n,onError:i},u)=>{const{scene:m}=I.useGLTF(t),b=e.useRef(n);b.current=n;const s=e.useRef(h);s.current=h;const l=e.useMemo(()=>m.clone(),[m]),{setMorphTarget:f,getMorphTargetNames:S,getMorphTargetValues:p}=q(l,c),{setMeshVisibility:A,getMeshNames:E}=K(l,g),{setMaterialColor:d,getMaterialNames:w,getMaterialColor:N}=G(l,y),{setMaterialTextures:x,clearMaterialTextures:v}=z(l,T);e.useEffect(()=>{var j;const $=S();$.length>0&&((j=s.current)==null||j.call(s,$))},[l,S]),e.useEffect(()=>{var D;if(!l)return;const $=[],j=new Set,C=[];let k=0;l.traverse(P=>{if(k++,P.type==="Bone"&&C.push(P.name),P.isMesh){const O=P;$.push(O.name),O.castShadow=!0,O.receiveShadow=!0,(Array.isArray(O.material)?O.material:[O.material]).forEach(_=>j.add(_.name))}}),(D=b.current)==null||D.call(b,{meshes:$.sort(),materials:Array.from(j).sort(),bones:C.sort(),nodeCount:k})},[l]),e.useImperativeHandle(u,()=>({setMorphTarget:f,getMorphTargetNames:S,getMorphTargetValues:p,setMeshVisibility:A,getMeshNames:E,setMaterialColor:d,getMaterialNames:w,getMaterialColor:N,setMaterialTextures:x,clearMaterialTextures:v}));const L=typeof a=="number"?[a,a,a]:a;return M.jsx("group",{position:r,rotation:o,scale:L,children:M.jsx("primitive",{object:l})})});se.displayName="MorphableModel";function he({children:t,bone:r,position:o=[0,0,0],rotation:a=[0,0,0],scale:c=1}){const{getBone:g}=ge(),[y,T]=e.useState(null);if(e.useEffect(()=>{const n=g(r);n?T(n):console.warn(`Bone "${r}" not found in model`)},[r,g]),!y)return null;const h=typeof c=="number"?[c,c,c]:c;return B.createPortal(M.jsx("group",{position:o,rotation:a,scale:h,children:t}),y)}function Me(t,r){const{scene:o,animations:a}=I.useGLTF(t),c=e.useMemo(()=>ee.clone(o),[o]);return e.useEffect(()=>{var n;if(!c)return;const g=[],y=[],T=new Set;let h=0;c.traverse(i=>{if(h++,i.type==="Bone"&&g.push(i.name),i.isMesh){const u=i;y.push(u.name),u.castShadow=!0,u.receiveShadow=!0,(Array.isArray(u.material)?u.material:[u.material]).forEach(b=>{T.add(b.name),b.shadowSide=R.DoubleSide})}}),(n=r==null?void 0:r.onLoad)==null||n.call(r,{meshes:y.sort(),materials:Array.from(T).sort(),bones:g.sort(),nodeCount:h})},[c,r]),{scene:c,animations:a}}function be(t){I.useGLTF.preload(t)}exports.AnimatedModel=V;exports.BoneAttachment=he;exports.Model=te;exports.MorphableModel=se;exports.Scene3D=de;exports.preloadModel=be;exports.useAnimationController=re;exports.useClonedModel=Me;exports.useMaterialColor=G;exports.useMaterialTexture=z;exports.useMeshVisibility=K;exports.useMorphTargets=q;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),B=require("@react-three/drei"),ae=require("three"),ie=require("three/examples/jsm/utils/SkeletonUtils.js"),P=require("@react-three/fiber"),le=require("three/examples/jsm/loaders/KTX2Loader.js"),b=require("react/jsx-runtime");function ee(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const a=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,a.get?a:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const v=ee(ae),te=ee(ie);function ce({position:r,target:t,controlsConfig:e}){const{camera:a}=P.useThree(),u=n.useRef(null);return n.useEffect(()=>{a&&(a.position.set(r[0],r[1],r[2]),a.updateProjectionMatrix(),u.current&&(u.current.target.set(t[0],t[1],t[2]),u.current.update()))},[r,t,a]),b.jsx(B.OrbitControls,{ref:u,makeDefault:!0,enabled:e.enabled,enablePan:e.enablePan,enableZoom:e.enableZoom,enableRotate:e.enableRotate,minDistance:e.minDistance,maxDistance:e.maxDistance,minPolarAngle:e.minPolarAngle,maxPolarAngle:e.maxPolarAngle,autoRotate:e.autoRotate,autoRotateSpeed:e.autoRotateSpeed})}function ue({background:r}){const t=r==null?void 0:r.startsWith("#");return r?t?b.jsx("color",{attach:"background",args:[r]}):b.jsx(pe,{url:r}):null}function pe({url:r}){const t=B.useTexture(r);return n.useMemo(()=>{t.colorSpace=v.SRGBColorSpace},[t]),b.jsx("primitive",{attach:"background",object:t})}function fe({config:r}){return b.jsx(B.Environment,{files:r.files,background:r.background??!1,blur:r.blur??0})}function de({config:r}){const{scene:t}=P.useThree();return n.useEffect(()=>{const e=r.intensity??1,a=r.blur??0,u="environmentIntensity"in t,p="backgroundBlurriness"in t,h="backgroundIntensity"in t,S=u?t.environmentIntensity:void 0,m=p?t.backgroundBlurriness:void 0,i=h?t.backgroundIntensity:void 0;return u&&(t.environmentIntensity=e),p&&(t.backgroundBlurriness=a),r.background&&h&&(t.backgroundIntensity=e),()=>{u&&(t.environmentIntensity=S??1),p&&(t.backgroundBlurriness=m??0),h&&(t.backgroundIntensity=i??1)}},[t,r]),null}const me={NoToneMapping:v.NoToneMapping,LinearToneMapping:v.LinearToneMapping,ReinhardToneMapping:v.ReinhardToneMapping,CineonToneMapping:v.CineonToneMapping,ACESFilmicToneMapping:v.ACESFilmicToneMapping};function ge({config:r}){const{gl:t}=P.useThree();return n.useEffect(()=>{const e=r.outputColorSpace==="linear"?v.LinearSRGBColorSpace:v.SRGBColorSpace,a=me[r.toneMapping??"ACESFilmicToneMapping"];t.physicallyCorrectLights=r.physicallyCorrectLights??!0,t.outputColorSpace=e,t.toneMapping=a,t.toneMappingExposure=r.toneMappingExposure??1},[t,r]),null}function he({config:r}){switch(r.type){case"spot":{const{position:t=[5,10,5],intensity:e=50,castShadow:a=!0,shadowMapSize:u=2048,angle:p=Math.PI/6,penumbra:h=.5,decay:S=2,distance:m=0,color:i="#ffffff"}=r;return b.jsx("spotLight",{position:t,intensity:e,castShadow:a,angle:p,penumbra:h,decay:S,distance:m,color:i,"shadow-mapSize-width":u,"shadow-mapSize-height":u})}case"point":{const{position:t=[0,5,0],intensity:e=20,color:a="#ffffff",distance:u=0,decay:p=2,castShadow:h=!1,shadowMapSize:S=2048}=r;return b.jsx("pointLight",{position:t,intensity:e,color:a,distance:u,decay:p,castShadow:h,"shadow-mapSize-width":S,"shadow-mapSize-height":S})}case"directional":{const{position:t=[10,20,10],intensity:e=40,color:a="#ffffff",castShadow:u=!0,shadowMapSize:p=2048}=r;return b.jsx("directionalLight",{position:t,intensity:e,color:a,castShadow:u,"shadow-mapSize-width":p,"shadow-mapSize-height":p})}case"hemisphere":{const{skyColor:t="#ffffff",groundColor:e="#444444",intensity:a=.5,position:u=[0,10,0]}=r,p=n.useMemo(()=>new v.Color(t),[t]),h=n.useMemo(()=>new v.Color(e),[e]);return b.jsx("hemisphereLight",{args:[p,h,a],position:u})}case"ambient":{const{intensity:t=.5,color:e="#ffffff"}=r;return b.jsx("ambientLight",{intensity:t,color:e})}default:return null}}function Me({onChange:r}){const{active:t,progress:e}=B.useProgress();return n.useEffect(()=>{r(t,e)},[t,e,r]),null}function be({children:r,camera:t={},controls:e={},background:a,shadows:u=!0,lights:p=[{type:"ambient",intensity:.5},{type:"spot",position:[5,10,5],intensity:50,castShadow:!0}],environment:h,renderer:S={physicallyCorrectLights:!0,outputColorSpace:"srgb",toneMapping:"ACESFilmicToneMapping",toneMappingExposure:1},contactShadows:m=!0,showLoadingOverlay:i=!0,style:s,className:f}){const[g,y]=n.useState(!1),[o,l]=n.useState(0),c=n.useRef(null),E=n.useCallback((d,w)=>{if(d){c.current!==null&&(window.clearTimeout(c.current),c.current=null),y(!0),l(Math.max(0,Math.min(100,Math.round(w))));return}l(100),c.current=window.setTimeout(()=>{y(!1),l(0),c.current=null},200)},[]);n.useEffect(()=>()=>{c.current!==null&&window.clearTimeout(c.current)},[]);const M={position:t.position||[0,2,5],fov:t.fov||45},T={target:e.target||[0,0,0],enabled:e.enabled??!0,enablePan:e.enablePan??!0,enableZoom:e.enableZoom??!0,enableRotate:e.enableRotate??!0,minDistance:e.minDistance,maxDistance:e.maxDistance,minPolarAngle:e.minPolarAngle,maxPolarAngle:e.maxPolarAngle,autoRotate:e.autoRotate??!1,autoRotateSpeed:e.autoRotateSpeed??2},C=typeof m=="object"?{position:m.position||[0,-1,0],opacity:m.opacity??.5,blur:m.blur??2}:m?{position:[0,-1,0],opacity:.5,blur:2}:null;return b.jsxs("div",{style:{...s||{},position:(s==null?void 0:s.position)??"relative"},className:f,children:[b.jsxs(P.Canvas,{shadows:u,camera:{position:M.position,fov:M.fov},style:{width:"100%",height:"100%"},children:[b.jsx(n.Suspense,{fallback:null,children:b.jsx(ue,{background:a})}),h&&b.jsxs(n.Suspense,{fallback:null,children:[b.jsx(fe,{config:h}),b.jsx(de,{config:h})]}),b.jsx(ge,{config:S}),p.map((d,w)=>b.jsx(he,{config:d},`${d.type}-${w}`)),b.jsx(n.Suspense,{fallback:null,children:r}),b.jsx(ce,{position:M.position,target:T.target,controlsConfig:T}),C&&b.jsx(B.ContactShadows,{position:C.position,opacity:C.opacity,blur:C.blur}),b.jsx(Me,{onChange:E})]}),i&&g&&b.jsx("div",{style:{position:"absolute",inset:0,background:"rgba(8, 10, 16, 0.56)",backdropFilter:"blur(18px)",WebkitBackdropFilter:"blur(18px)",display:"flex",alignItems:"center",justifyContent:"center",pointerEvents:"none",zIndex:10},children:b.jsxs("div",{style:{minWidth:220,padding:"16px 18px",borderRadius:14,border:"1px solid rgba(255,255,255,0.2)",background:"linear-gradient(180deg, rgba(18,24,36,0.9), rgba(13,17,27,0.9))",color:"#eef3ff",boxShadow:"0 10px 30px rgba(0,0,0,0.35)",fontFamily:"system-ui, -apple-system, Segoe UI, sans-serif",textAlign:"center"},children:[b.jsx("div",{style:{display:"flex",justifyContent:"center",marginBottom:10},children:b.jsxs("svg",{width:"34",height:"34",viewBox:"0 0 34 34","aria-hidden":"true",children:[b.jsx("circle",{cx:"17",cy:"17",r:"14",fill:"none",stroke:"rgba(255,255,255,0.2)",strokeWidth:"4"}),b.jsx("path",{d:"M31 17a14 14 0 0 1-14 14",fill:"none",stroke:"#67b4ff",strokeWidth:"4",strokeLinecap:"round",children:b.jsx("animateTransform",{attributeName:"transform",type:"rotate",from:"0 17 17",to:"360 17 17",dur:"0.9s",repeatCount:"indefinite"})})]})}),b.jsxs("div",{style:{fontSize:12,opacity:.82,marginTop:4},children:[o,"%"]})]})})]})}function H(r,t){const e=n.useRef(new Map),a=n.useRef({}),u=n.useRef({});n.useEffect(()=>{t&&(a.current={...t})},[t]),n.useEffect(()=>{if(!r)return;const m=new Map;r.traverse(i=>{if(i.isMesh){const s=i;s.name&&m.set(s.name,s)}}),e.current=m},[r]),P.useFrame(()=>{const m=e.current;if(m.size===0)return;const i={...a.current,...u.current};for(const[s,f]of Object.entries(i)){const g=m.get(s);g&&g.visible!==f&&(g.visible=f)}});const p=n.useCallback((m,i)=>{u.current[m]=i;const s=e.current.get(m);s&&(s.visible=i)},[]),h=n.useCallback(()=>Array.from(e.current.keys()).sort(),[]),S=n.useCallback(()=>{const m={};return e.current.forEach((i,s)=>{m[s]=i.visible}),m},[]);return{setMeshVisibility:p,getMeshNames:h,getMeshVisibility:S}}function G(r,t){const e=n.useRef(new Map),a=n.useRef(new Map);n.useEffect(()=>{if(!r)return;const i=new Map;r.traverse(s=>{if(s.isMesh){const f=s;(Array.isArray(f.material)?f.material:[f.material]).forEach(y=>{y.name&&!i.has(y.name)&&i.set(y.name,y)})}}),e.current=i,t&&Object.entries(t).forEach(([s,f])=>{const g=i.get(s);if(g&&!Array.isArray(g)){const y=u(f);g.color&&g.color.copy(y),a.current.set(s,y)}})},[r,t]),P.useFrame(()=>{a.current.forEach((i,s)=>{const f=e.current.get(s);if(f&&!Array.isArray(f)){const g=f;g.color&&!g.color.equals(i)&&(g.color.copy(i),g.needsUpdate=!0)}})});const u=i=>typeof i=="string"?new v.Color(i):new v.Color(i[0],i[1],i[2]),p=n.useCallback((i,s)=>{const f=u(s);a.current.set(i,f);const g=e.current.get(i);if(g&&!Array.isArray(g)){const y=g;y.color&&(y.color.copy(f),y.needsUpdate=!0)}},[]),h=n.useCallback(()=>Array.from(e.current.keys()).sort(),[]),S=n.useCallback(i=>{const s=e.current.get(i);if(s&&!Array.isArray(s)){const f=s;if(f.color)return"#"+f.color.getHexString()}return null},[]),m=n.useCallback(()=>{const i={};return e.current.forEach((s,f)=>{if(!Array.isArray(s)){const g=s;g.color&&(i[f]="#"+g.color.getHexString())}}),i},[]);return{setMaterialColor:p,getMaterialNames:h,getMaterialColor:S,getAllMaterialColors:m}}function U(r){const t=r.toLowerCase();if(t.endsWith(".ktx2"))return!0;try{const e=new URL(r,window.location.origin),a=decodeURIComponent(e.hash.replace(/^#/,"")).toLowerCase(),u=decodeURIComponent(e.search).toLowerCase(),p=decodeURIComponent(e.pathname).toLowerCase();return a.endsWith(".ktx2")||u.includes(".ktx2")||p.endsWith(".ktx2")}catch{return t.includes(".ktx2")}}function K(r,t){const{gl:e}=P.useThree(),a=n.useRef(new Map),u=n.useRef(new v.TextureLoader),p=n.useRef(null),h=n.useRef(new Map),S=n.useRef(new Set),m=n.useRef("");n.useEffect(()=>{if(!p.current)try{const o=typeof WebAssembly=="object"&&typeof WebAssembly.validate=="function";console.log("[useMaterialTexture] Browser features:"),console.log(` WebAssembly supported: ${o}`),console.log(` WebGL2: ${e.capabilities.isWebGL2}`);const l=new le.KTX2Loader;l.setTranscoderPath("/basis/"),l.detectSupport(e),p.current=l,console.log("[useMaterialTexture] ✅ KTX2Loader initialized"),console.log("[useMaterialTexture] Transcoder path: /basis/"),fetch("/basis/basis_transcoder.wasm").then(c=>{c.ok?console.log("[useMaterialTexture] ✅ basis_transcoder.wasm is accessible"):console.error("[useMaterialTexture] ❌ basis_transcoder.wasm returned",c.status)}).catch(c=>{console.error("[useMaterialTexture] ❌ Failed to check basis_transcoder.wasm:",c)}),o||(console.warn("[useMaterialTexture] ⚠️ WebAssembly not supported! KTX2 will fallback to CPU decoding (slow)"),console.warn("[useMaterialTexture] ⚠️ Recommend using WebP instead of KTX2 for this browser"))}catch(o){console.error("[useMaterialTexture] ❌ Failed to initialize KTX2Loader:",o)}return()=>{p.current&&(p.current.dispose(),p.current=null)}},[e]),n.useEffect(()=>{if(!r)return;const o=new Map;r.traverse(l=>{if(l.isMesh){const c=l;(Array.isArray(c.material)?c.material:[c.material]).forEach(M=>{M.name&&!o.has(M.name)&&o.set(M.name,M)})}}),a.current=o},[r]);const i=n.useCallback(o=>U(o)?p.current?p.current:(console.warn("[useMaterialTexture] KTX2Loader not initialized, falling back to TextureLoader"),u.current):u.current,[]);n.useEffect(()=>{if(!t||!r)return;const o=a.current;if(o.size===0)return;const l=JSON.stringify(t);if(m.current===l){console.log("[useMaterialTexture] Textures unchanged, skipping reload");return}m.current=l;let c=!1;const E=new Map;Object.entries(t).forEach(([d,w])=>{E.set(d,typeof w=="string"?{map:w}:w)}),console.log("[useMaterialTexture] Starting texture load for",E.size,"materials");const M=[];E.forEach((d,w)=>{var A,I;const O=o.get(w);if(!O||!O.isMeshStandardMaterial){console.warn(`[useMaterialTexture] Material "${w}" not found or not MeshStandardMaterial`);return}const x=O;console.log(`[useMaterialTexture] 📋 Material "${w}" BEFORE reset:`),console.log(` - map: ${x.map?"EXISTS":"null"} ${x.map?`(uuid: ${x.map.uuid})`:""}`),console.log(` - normalMap: ${x.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${x.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${x.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${x.emissiveMap?"EXISTS":"null"}`),console.log(` - aoMap: ${x.aoMap?"EXISTS":"null"}`),console.log(` - color: ${(A=x.color)==null?void 0:A.getHexString()}`),console.log(` - emissive: ${(I=x.emissive)==null?void 0:I.getHexString()}`),console.log(` - material uuid: ${x.uuid}`),Object.entries(d).forEach(([$,k])=>{if(!k)return;const R=$,j=x[R];j&&(console.log(`[useMaterialTexture] 🗑️ Disposing old ${R} (uuid: ${j.uuid})`),j.dispose(),x[R]=null)}),d.emissiveMap&&(x.emissive=new v.Color(0),x.emissiveIntensity=0),x.needsUpdate=!0,x.color=new v.Color(16777215),console.log(`[useMaterialTexture] ✅ Material "${w}" AFTER reset: only specified maps cleared`),Object.entries(d).forEach(([$,k])=>{if(!k)return;const R=`${w}_${$}_${k}`,j=h.current.get(R);if(j){console.log(`[useMaterialTexture] Using cached texture: ${w}.${$}`),c||s(x,$,j);return}if(S.current.has(R)){console.log(`[useMaterialTexture] Skipping already loading: ${w}.${$}`);return}M.push({materialName:w,textureType:$,url:k,material:x})})}),console.log(`[useMaterialTexture] Queued ${M.length} textures to load`);let T=0;const C=()=>{if(c||T>=M.length){console.log("[useMaterialTexture] ✅ All textures loaded"),console.log("[useMaterialTexture] 📊 FINAL material states:"),o.forEach((A,I)=>{var k,R;const $=A;console.log(` Material "${I}":`),console.log(` - map: ${$.map?"EXISTS":"null"} ${$.map?`(colorSpace: ${$.map.colorSpace})`:""}`),console.log(` - normalMap: ${$.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${$.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${$.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${$.emissiveMap?"EXISTS":"null"}`),console.log(` - color: ${(k=$.color)==null?void 0:k.getHexString()}`),console.log(` - emissive: ${(R=$.emissive)==null?void 0:R.getHexString()}`),console.log(` - emissiveIntensity: ${$.emissiveIntensity}`),console.log(` - roughness: ${$.roughness}`),console.log(` - metalness: ${$.metalness}`)});return}const d=M[T++],w=`${d.materialName}_${d.textureType}_${d.url}`;console.log(`[useMaterialTexture] Loading (${T}/${M.length}): ${d.materialName}.${d.textureType} from ${d.url}`),S.current.add(w);const O=i(d.url),x=U(d.url)?"KTX2Loader":"TextureLoader";console.log(`[useMaterialTexture] Using ${x} for ${d.url}`),O.load(d.url,A=>{var R,j,X,N,L,D;if(S.current.delete(w),c){console.log(`[useMaterialTexture] Disposed, cleaning up texture: ${d.materialName}.${d.textureType}`),A.dispose();return}const I=((R=A.image)==null?void 0:R.width)||((X=(j=A.source)==null?void 0:j.data)==null?void 0:X.width)||"unknown",$=((N=A.image)==null?void 0:N.height)||((D=(L=A.source)==null?void 0:L.data)==null?void 0:D.height)||"unknown";console.log(`[useMaterialTexture] ✅ Loaded: ${d.materialName}.${d.textureType} (${I}x${$})`),A.colorSpace=d.textureType==="map"||d.textureType==="emissiveMap"?v.SRGBColorSpace:v.NoColorSpace,A.wrapS=v.RepeatWrapping,A.wrapT=v.RepeatWrapping,A.flipY=!1,h.current.set(w,A),s(d.material,d.textureType,A);const k=U(d.url)?500:150;console.log(`[useMaterialTexture] Waiting111111 ${k}ms before next texture...`),setTimeout(C,0)},A=>{if(A.lengthComputable){const I=Math.round(A.loaded/A.total*100);I%25===0&&console.log(`[useMaterialTexture] Progress ${d.materialName}.${d.textureType}: ${I}%`)}},A=>{S.current.delete(w),c||(console.error(`[useMaterialTexture] ❌ Failed to load ${d.materialName}.${d.textureType} from ${d.url}`),console.error("[useMaterialTexture] Error details:",A),console.error("[useMaterialTexture] Loader type:",x),U(d.url)&&(console.error("[useMaterialTexture] KTX2 error - file may not be in Basis Universal format!"),console.error("[useMaterialTexture] Make sure files are created with: gltf-transform etc1s input.png output.ktx2"))),setTimeout(C,100)})};return C(),()=>{console.log("[useMaterialTexture] Cleanup: disposed"),c=!0}},[r,t,i]);const s=(o,l,c)=>{var E,M;switch(console.log(`[useMaterialTexture] 🎨 Applying texture: ${o.name}.${l} (texture uuid: ${c.uuid})`),l){case"map":o.map=c;break;case"normalMap":o.normalMap=c;break;case"roughnessMap":o.roughnessMap=c;break;case"metalnessMap":o.metalnessMap=c;break;case"emissiveMap":o.emissiveMap=c,o.emissive=new v.Color(16777215),o.emissiveIntensity=1;break;case"alphaMap":o.alphaMap=c,o.transparent=!0,o.alphaTest=Math.max(o.alphaTest??0,.001),o.depthWrite=!1;break;case"aoMap":o.aoMap=c;break}o.needsUpdate=!0,console.log(`[useMaterialTexture] ✅ Applied ${l} to ${o.name}, needsUpdate=true`),console.log(`[useMaterialTexture] 📊 Material "${o.name}" FINAL state:`),console.log(` - map: ${o.map?"EXISTS":"null"} ${o.map?`(uuid: ${o.map.uuid}, colorSpace: ${o.map.colorSpace})`:""}`),console.log(` - normalMap: ${o.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${o.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${o.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${o.emissiveMap?"EXISTS":"null"}`),console.log(` - aoMap: ${o.aoMap?"EXISTS":"null"}`),console.log(` - alphaMap: ${o.alphaMap?"EXISTS":"null"}`),console.log(` - transparent: ${o.transparent}`),console.log(` - alphaTest: ${o.alphaTest}`),console.log(` - depthWrite: ${o.depthWrite}`),console.log(` - color: ${(E=o.color)==null?void 0:E.getHexString()}`),console.log(` - emissive: ${(M=o.emissive)==null?void 0:M.getHexString()}`),console.log(` - emissiveIntensity: ${o.emissiveIntensity}`),console.log(` - roughness: ${o.roughness}`),console.log(` - metalness: ${o.metalness}`)},f=n.useCallback((o,l)=>{const c=typeof l=="string"?{map:l}:l,E=a.current.get(o);if(!E||!E.isMeshStandardMaterial){console.warn(`Material "${o}" not found or not MeshStandardMaterial`);return}const M=E;Object.entries(c).forEach(([T,C])=>{if(!C)return;const d=`${o}_${T}_${C}`,w=h.current.get(d);if(w){s(M,T,w);return}i(C).load(C,x=>{x.colorSpace=T==="map"||T==="emissiveMap"?v.SRGBColorSpace:v.NoColorSpace,x.wrapS=v.RepeatWrapping,x.wrapT=v.RepeatWrapping,h.current.set(d,x),s(M,T,x)},void 0,x=>{console.error(`Failed to load texture ${C}:`,x)})})},[i]),g=n.useCallback(()=>Array.from(a.current.keys()).sort(),[]),y=n.useCallback(o=>{const l=a.current.get(o);if(!l||!l.isMeshStandardMaterial)return;const c=l;c.map=null,c.normalMap=null,c.roughnessMap=null,c.metalnessMap=null,c.emissiveMap=null,c.alphaMap=null,c.aoMap=null,c.transparent=!1,c.alphaTest=0,c.depthWrite=!0,c.needsUpdate=!0},[]);return{setMaterialTextures:f,getMaterialNames:g,clearMaterialTextures:y}}function re({url:r,position:t=[0,0,0],rotation:e=[0,0,0],scale:a=1,meshVisibility:u,materialColors:p,materialTextures:h,onLoad:S,onError:m}){const{scene:i}=B.useGLTF(r),s=n.useRef(S);s.current=S;const f=n.useMemo(()=>{const y=i.clone();console.log("[Model] 🔍 Scene clone created, checking materials...");const o=[],l=new Set,c=[];let E=0;return y.traverse(M=>{if(E++,M.type==="Bone"&&c.push(M.name),M.isMesh){const T=M;o.push(T.name),T.castShadow=!0,T.receiveShadow=!0,(Array.isArray(T.material)?T.material:[T.material]).forEach(d=>{l.add(d.name),console.log(`[Model] 📦 Material found: "${d.name}" (uuid: ${d.uuid})`);const w=d;console.log(` - Has map: ${w.map?"YES":"NO"}`),console.log(` - Has normalMap: ${w.normalMap?"YES":"NO"}`),console.log(` - Has roughnessMap: ${w.roughnessMap?"YES":"NO"}`),console.log(` - Has metalnessMap: ${w.metalnessMap?"YES":"NO"}`)})}}),console.log(`[Model] 📊 Clone summary: ${o.length} meshes, ${l.size} materials`),setTimeout(()=>{var M;(M=s.current)==null||M.call(s,{meshes:o.sort(),materials:Array.from(l).sort(),bones:c.sort(),nodeCount:E})},0),y},[i]);H(f,u),G(f,p),K(f,h);const g=typeof a=="number"?[a,a,a]:a;return b.jsx("group",{position:t,rotation:e,scale:g,children:b.jsx("primitive",{object:f})})}re.preload=r=>{B.useGLTF.preload(r)};function ne(r,t,e){const{actions:a,names:u}=B.useAnimations(r,t),p=n.useRef(null),h=n.useRef(e==null?void 0:e.defaultAnimation);n.useEffect(()=>{h.current=e==null?void 0:e.defaultAnimation},[e==null?void 0:e.defaultAnimation]),n.useEffect(()=>{if(u.length===0)return;const s=h.current;let f=u[0];if(s){const y=u.find(o=>o===s||o.includes(s));y&&(f=y)}const g=a[f];g&&(g.reset().fadeIn(.5).play(),p.current=g)},[a,u]);const S=n.useCallback((s,f)=>{const{loop:g=!1,crossFadeDuration:y=.2,restoreDefault:o=!0}=f||{};let l=a[s];if(!l){const E=Object.keys(a).find(M=>M.toLowerCase().includes(s.toLowerCase())||s.toLowerCase().includes(M.toLowerCase()));E&&(l=a[E])}if(!l){console.warn(`Animation "${s}" not found. Available: ${u.join(", ")}`);return}const c=p.current;if(!(c===l&&l.isRunning())&&(c&&c!==l&&c.fadeOut(y),l.reset(),l.fadeIn(y),l.setLoop(g?v.LoopRepeat:v.LoopOnce,g?1/0:1),l.clampWhenFinished=!g,l.play(),g||l.getMixer().update(0),p.current=l,o&&!g&&h.current)){const E=l.getMixer(),M=T=>{if(T.action===l){E.removeEventListener("finished",M);const C=a[h.current];C&&(l.fadeOut(y),C.reset().fadeIn(y).play(),p.current=C)}};E.addEventListener("finished",M)}},[a,u]),m=n.useCallback(()=>{var s;(s=p.current)==null||s.fadeOut(.2),p.current=null},[]),i=n.useCallback(()=>u,[u]);return{playAnimation:S,stopAnimation:m,getAnimationNames:i,actions:a}}function q(r,t){const e=n.useRef(t||{}),a=n.useRef([]),u=n.useRef([]);n.useEffect(()=>{const m=new Set,i=[];r.traverse(s=>{s instanceof v.Mesh&&s.morphTargetDictionary&&s.morphTargetInfluences&&(i.push(s),Object.keys(s.morphTargetDictionary).forEach(f=>{m.add(f)}))}),a.current=Array.from(m).sort(),u.current=i},[r]),P.useFrame(()=>{const m=e.current;u.current.forEach(i=>{!i.morphTargetDictionary||!i.morphTargetInfluences||Object.entries(m).forEach(([s,f])=>{const g=i.morphTargetDictionary[s];g!==void 0&&(i.morphTargetInfluences[g]=f)})})}),n.useEffect(()=>{t&&(e.current={...t})},[t]);const p=n.useCallback((m,i)=>{e.current[m]=Math.max(0,Math.min(1,i))},[]),h=n.useCallback(()=>a.current,[]),S=n.useCallback(()=>({...e.current}),[]);return{setMorphTarget:p,getMorphTargetNames:h,getMorphTargetValues:S}}const oe=n.createContext(null);function ye(){const r=n.useContext(oe);if(!r)throw new Error("BoneAttachment must be used within an AnimatedModel");return r}const V=n.forwardRef(({url:r,position:t=[0,0,0],rotation:e=[0,0,0],scale:a=1,defaultAnimation:u,animation:p,morphTargets:h,meshVisibility:S,materialColors:m,materialTextures:i,onLoad:s,onError:f,children:g},y)=>{const o=n.useRef(null),l=n.useRef([]),c=n.useRef(s);c.current=s;const{scene:E,animations:M}=B.useGLTF(r),T=n.useMemo(()=>te.clone(E),[E]),{playAnimation:C,stopAnimation:d,getAnimationNames:w}=ne(M,T,{defaultAnimation:u});n.useEffect(()=>{p&&C(p,{loop:!0,restoreDefault:!1})},[p,C]);const{setMorphTarget:O}=q(T,h),{setMeshVisibility:x,getMeshNames:A}=H(T,S),{setMaterialColor:I,getMaterialNames:$,getMaterialColor:k}=G(T,m),{setMaterialTextures:R,clearMaterialTextures:j}=K(T,i);n.useEffect(()=>{if(!T)return;const L=setTimeout(()=>{var Q;const D=[],z=[],Y=new Set,Z=new Set;let J=0;T.traverse(F=>{if(J++,F.type==="Bone"&&D.push(F.name),F.isMesh){const W=F;z.push(W.name),W.castShadow=!0,W.receiveShadow=!0,(Array.isArray(W.material)?W.material:[W.material]).forEach(_=>{Y.add(_.name),_.shadowSide=v.DoubleSide}),W.morphTargetDictionary&&Object.keys(W.morphTargetDictionary).forEach(_=>{Z.add(_)})}}),l.current=Array.from(Z).sort(),(Q=c.current)==null||Q.call(c,{meshes:z.sort(),materials:Array.from(Y).sort(),bones:D.sort(),nodeCount:J,animations:M.map(F=>F.name),morphTargetNames:l.current})},0);return()=>clearTimeout(L)},[T,M]),n.useImperativeHandle(y,()=>({playAnimation:C,stopAnimation:d,getAnimationNames:w,getGroup:()=>o.current,setMorphTarget:O,getMorphTargetNames:()=>l.current,setMeshVisibility:x,getMeshNames:A,setMaterialColor:I,getMaterialNames:$,getMaterialColor:k,setMaterialTextures:R,clearMaterialTextures:j}));const X=n.useMemo(()=>({scene:T,getBone:L=>T.getObjectByName(L)||null}),[T]),N=typeof a=="number"?[a,a,a]:a;return b.jsx(oe.Provider,{value:X,children:b.jsxs("group",{ref:o,position:t,rotation:e,scale:N,children:[b.jsx("primitive",{object:T}),g]})})});V.displayName="AnimatedModel";V.preload=r=>{B.useGLTF.preload(r)};const se=n.forwardRef(({url:r,position:t=[0,0,0],rotation:e=[0,0,0],scale:a=1,morphTargets:u,meshVisibility:p,materialColors:h,materialTextures:S,onMorphTargetsFound:m,onLoad:i,onError:s},f)=>{const{scene:g}=B.useGLTF(r),y=n.useRef(i);y.current=i;const o=n.useRef(m);o.current=m;const l=n.useMemo(()=>g.clone(),[g]),{setMorphTarget:c,getMorphTargetNames:E,getMorphTargetValues:M}=q(l,u),{setMeshVisibility:T,getMeshNames:C}=H(l,p),{setMaterialColor:d,getMaterialNames:w,getMaterialColor:O}=G(l,h),{setMaterialTextures:x,clearMaterialTextures:A}=K(l,S);n.useEffect(()=>{var k;const $=E();$.length>0&&((k=o.current)==null||k.call(o,$))},[l,E]),n.useEffect(()=>{var X;if(!l)return;const $=[],k=new Set,R=[];let j=0;l.traverse(N=>{if(j++,N.type==="Bone"&&R.push(N.name),N.isMesh){const L=N;$.push(L.name),L.castShadow=!0,L.receiveShadow=!0,(Array.isArray(L.material)?L.material:[L.material]).forEach(z=>k.add(z.name))}}),(X=y.current)==null||X.call(y,{meshes:$.sort(),materials:Array.from(k).sort(),bones:R.sort(),nodeCount:j})},[l]),n.useImperativeHandle(f,()=>({setMorphTarget:c,getMorphTargetNames:E,getMorphTargetValues:M,setMeshVisibility:T,getMeshNames:C,setMaterialColor:d,getMaterialNames:w,getMaterialColor:O,setMaterialTextures:x,clearMaterialTextures:A}));const I=typeof a=="number"?[a,a,a]:a;return b.jsx("group",{position:t,rotation:e,scale:I,children:b.jsx("primitive",{object:l})})});se.displayName="MorphableModel";function Te({children:r,bone:t,position:e=[0,0,0],rotation:a=[0,0,0],scale:u=1}){const{getBone:p}=ye(),[h,S]=n.useState(null);if(n.useEffect(()=>{const i=p(t);i?S(i):console.warn(`Bone "${t}" not found in model`)},[t,p]),!h)return null;const m=typeof u=="number"?[u,u,u]:u;return P.createPortal(b.jsx("group",{position:e,rotation:a,scale:m,children:r}),h)}function xe(r,t){const{scene:e,animations:a}=B.useGLTF(r),u=n.useMemo(()=>te.clone(e),[e]);return n.useEffect(()=>{var i;if(!u)return;const p=[],h=[],S=new Set;let m=0;u.traverse(s=>{if(m++,s.type==="Bone"&&p.push(s.name),s.isMesh){const f=s;h.push(f.name),f.castShadow=!0,f.receiveShadow=!0,(Array.isArray(f.material)?f.material:[f.material]).forEach(y=>{S.add(y.name),y.shadowSide=v.DoubleSide})}}),(i=t==null?void 0:t.onLoad)==null||i.call(t,{meshes:h.sort(),materials:Array.from(S).sort(),bones:p.sort(),nodeCount:m})},[u,t]),{scene:u,animations:a}}function Se(r){B.useGLTF.preload(r)}exports.AnimatedModel=V;exports.BoneAttachment=Te;exports.Model=re;exports.MorphableModel=se;exports.Scene3D=be;exports.preloadModel=Se;exports.useAnimationController=ne;exports.useClonedModel=xe;exports.useMaterialColor=G;exports.useMaterialTexture=K;exports.useMeshVisibility=H;exports.useMorphTargets=q;
|
|
2
2
|
//# sourceMappingURL=mbt-3d.cjs.map
|