mbt-3d 0.3.9 → 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 +49 -9
- package/dist/mbt-3d.cjs +1 -1
- package/dist/mbt-3d.cjs.map +1 -1
- package/dist/mbt-3d.js +596 -550
- 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
|
@@ -270,7 +270,7 @@ export declare interface BoneAttachmentProps {
|
|
|
270
270
|
*
|
|
271
271
|
* @example
|
|
272
272
|
* ```tsx
|
|
273
|
-
* { type: 'directional', position: [10, 20, 10], intensity: 40, castShadow: true }
|
|
273
|
+
* { type: 'directional', position: [10, 20, 10], intensity: 40, castShadow: true, shadowMapSize: 2048 }
|
|
274
274
|
* ```
|
|
275
275
|
*/
|
|
276
276
|
declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
@@ -279,11 +279,17 @@ declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
|
279
279
|
position?: [number, number, number];
|
|
280
280
|
/** Enable shadow casting. Default: true */
|
|
281
281
|
castShadow?: boolean;
|
|
282
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
283
|
+
shadowMapSize?: number;
|
|
282
284
|
}
|
|
283
285
|
|
|
284
286
|
/**
|
|
285
287
|
* Environment (HDRI) configuration for realistic lighting and reflections
|
|
286
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
|
+
*
|
|
287
293
|
* @example
|
|
288
294
|
* ```tsx
|
|
289
295
|
* { files: '/scenes/studio.hdr', intensity: 1, background: false }
|
|
@@ -292,11 +298,11 @@ declare interface DirectionalLightConfig extends BaseLightConfig {
|
|
|
292
298
|
declare interface EnvironmentConfig {
|
|
293
299
|
/** URL to HDRI file (.hdr or .exr) */
|
|
294
300
|
files: string;
|
|
295
|
-
/** Environment intensity multiplier. Default: 1 */
|
|
301
|
+
/** Environment intensity multiplier for scene environment. Default: 1 */
|
|
296
302
|
intensity?: number;
|
|
297
303
|
/** Use HDRI as scene background. Default: false */
|
|
298
304
|
background?: boolean;
|
|
299
|
-
/**
|
|
305
|
+
/** Background blur amount (0-1). Default: 0 */
|
|
300
306
|
blur?: number;
|
|
301
307
|
}
|
|
302
308
|
|
|
@@ -572,7 +578,7 @@ export declare interface MorphableModelProps extends ModelProps {
|
|
|
572
578
|
*
|
|
573
579
|
* @example
|
|
574
580
|
* ```tsx
|
|
575
|
-
* { 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 }
|
|
576
582
|
* ```
|
|
577
583
|
*/
|
|
578
584
|
declare interface PointLightConfig extends BaseLightConfig {
|
|
@@ -585,10 +591,30 @@ declare interface PointLightConfig extends BaseLightConfig {
|
|
|
585
591
|
decay?: number;
|
|
586
592
|
/** Enable shadow casting. Default: false */
|
|
587
593
|
castShadow?: boolean;
|
|
594
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
595
|
+
shadowMapSize?: number;
|
|
588
596
|
}
|
|
589
597
|
|
|
590
598
|
export declare function preloadModel(url: string): void;
|
|
591
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
|
+
|
|
592
618
|
/**
|
|
593
619
|
* Scene3D - Main 3D scene container with built-in canvas, lighting, and controls
|
|
594
620
|
*
|
|
@@ -609,6 +635,7 @@ export declare function preloadModel(url: string): void;
|
|
|
609
635
|
* @param controls.enablePan - Enable camera panning with middle mouse. Default: `true`
|
|
610
636
|
* @param controls.enableZoom - Enable camera zoom with scroll wheel. Default: `true`
|
|
611
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]`
|
|
612
639
|
* @param controls.minDistance - Minimum zoom distance. Example: `2`
|
|
613
640
|
* @param controls.maxDistance - Maximum zoom distance. Example: `10`
|
|
614
641
|
* @param controls.minPolarAngle - Minimum vertical rotation angle in radians. Example: `Math.PI / 4`
|
|
@@ -617,7 +644,9 @@ export declare function preloadModel(url: string): void;
|
|
|
617
644
|
* @param controls.autoRotateSpeed - Auto-rotation speed. Default: `2`
|
|
618
645
|
* @param background - Background: image URL (e.g., `"/bg.jpg"`) or hex color (e.g., `"#1a1a2e"`)
|
|
619
646
|
* @param shadows - Enable shadow rendering. Default: `true`
|
|
620
|
-
* @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.
|
|
621
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 }`
|
|
622
651
|
* @param contactShadows.position - Shadow position as [x, y, z]. Example: `[0, -1, 0]`. Default: `[0, -1, 0]`
|
|
623
652
|
* @param contactShadows.opacity - Shadow opacity (0-1). Example: `0.5`. Default: `0.5`
|
|
@@ -644,7 +673,7 @@ export declare function preloadModel(url: string): void;
|
|
|
644
673
|
* <Scene3D
|
|
645
674
|
* camera={{ position: [0, 2, 5], fov: 45 }}
|
|
646
675
|
* lights={[
|
|
647
|
-
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true },
|
|
676
|
+
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true, shadowMapSize: 2048 },
|
|
648
677
|
* { type: 'spot', position: [-5, 10, -5], intensity: 30, castShadow: false },
|
|
649
678
|
* { type: 'point', position: [0, 5, 0], intensity: 20 },
|
|
650
679
|
* { type: 'ambient', intensity: 0.3 }
|
|
@@ -668,7 +697,7 @@ export declare function preloadModel(url: string): void;
|
|
|
668
697
|
* </Scene3D>
|
|
669
698
|
* ```
|
|
670
699
|
*/
|
|
671
|
-
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;
|
|
672
701
|
|
|
673
702
|
/**
|
|
674
703
|
* Props for Scene3D component
|
|
@@ -701,6 +730,8 @@ export declare interface Scene3DProps {
|
|
|
701
730
|
};
|
|
702
731
|
/** OrbitControls configuration for camera rotation */
|
|
703
732
|
controls?: {
|
|
733
|
+
/** Orbit target point [x, y, z]. Camera will look at this point. Default: [0, 0, 0] */
|
|
734
|
+
target?: [number, number, number];
|
|
704
735
|
/** Enable/disable all controls. Default: true */
|
|
705
736
|
enabled?: boolean;
|
|
706
737
|
/** Enable camera panning (middle mouse). Default: true */
|
|
@@ -728,8 +759,13 @@ export declare interface Scene3DProps {
|
|
|
728
759
|
shadows?: boolean;
|
|
729
760
|
/** Array of light configurations for multi-light setup */
|
|
730
761
|
lights?: LightConfigUnion[];
|
|
731
|
-
/**
|
|
762
|
+
/**
|
|
763
|
+
* Environment (HDRI) configuration for realistic lighting and reflections.
|
|
764
|
+
* Can be combined with `lights` for mixed lighting setups.
|
|
765
|
+
*/
|
|
732
766
|
environment?: EnvironmentConfig;
|
|
767
|
+
/** Optional renderer tuning (physically-correct lights, tone mapping, exposure, output color space). */
|
|
768
|
+
renderer?: RendererConfig;
|
|
733
769
|
/** Contact shadows configuration (ground shadows under models) */
|
|
734
770
|
contactShadows?: boolean | {
|
|
735
771
|
/** Shadow position [x, y, z]. Default: [0, -1, 0] */
|
|
@@ -752,7 +788,7 @@ export declare interface Scene3DProps {
|
|
|
752
788
|
*
|
|
753
789
|
* @example
|
|
754
790
|
* ```tsx
|
|
755
|
-
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true }
|
|
791
|
+
* { type: 'spot', position: [5, 10, 5], intensity: 50, castShadow: true, shadowMapSize: 2048 }
|
|
756
792
|
* ```
|
|
757
793
|
*/
|
|
758
794
|
declare interface SpotLightConfig extends BaseLightConfig {
|
|
@@ -761,6 +797,8 @@ declare interface SpotLightConfig extends BaseLightConfig {
|
|
|
761
797
|
position?: [number, number, number];
|
|
762
798
|
/** Enable shadow casting. Default: true */
|
|
763
799
|
castShadow?: boolean;
|
|
800
|
+
/** Shadow map size in px (square). Default: 2048 */
|
|
801
|
+
shadowMapSize?: number;
|
|
764
802
|
/** Cone angle in radians. Default: Math.PI / 6 */
|
|
765
803
|
angle?: number;
|
|
766
804
|
/** Penumbra (soft edges) 0-1. Default: 0.5 */
|
|
@@ -771,6 +809,8 @@ declare interface SpotLightConfig extends BaseLightConfig {
|
|
|
771
809
|
distance?: number;
|
|
772
810
|
}
|
|
773
811
|
|
|
812
|
+
export declare type ToneMappingMode = 'NoToneMapping' | 'LinearToneMapping' | 'ReinhardToneMapping' | 'CineonToneMapping' | 'ACESFilmicToneMapping';
|
|
813
|
+
|
|
774
814
|
export declare function useAnimationController(animations: THREE.AnimationClip[], scene: THREE.Object3D, options?: UseAnimationControllerOptions): {
|
|
775
815
|
playAnimation: (name: string, opts?: {
|
|
776
816
|
loop?: boolean;
|
package/dist/mbt-3d.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),O=require("@react-three/drei"),ae=require("three"),le=require("three/examples/jsm/utils/SkeletonUtils.js"),B=require("@react-three/fiber"),ie=require("three/examples/jsm/loaders/KTX2Loader.js"),h=require("react/jsx-runtime");function ee(r){const s=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const l=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(s,e,l.get?l:{enumerable:!0,get:()=>r[e]})}}return s.default=r,Object.freeze(s)}const R=ee(ae),te=ee(le);function ce({position:r,controlsConfig:s}){const{camera:e}=B.useThree(),l=t.useRef(null);return t.useEffect(()=>{r&&e&&(e.position.set(r[0],r[1],r[2]),e.updateProjectionMatrix(),l.current&&(l.current.target.set(0,0,0),l.current.update()))},[r,e]),h.jsx(O.OrbitControls,{ref:l,makeDefault:!0,enabled:s.enabled,enablePan:s.enablePan,enableZoom:s.enableZoom,enableRotate:s.enableRotate,minDistance:s.minDistance,maxDistance:s.maxDistance,minPolarAngle:s.minPolarAngle,maxPolarAngle:s.maxPolarAngle,autoRotate:s.autoRotate,autoRotateSpeed:s.autoRotateSpeed})}function ue({background:r}){const s=r==null?void 0:r.startsWith("#");return r?s?h.jsx("color",{attach:"background",args:[r]}):h.jsx(fe,{url:r}):null}function fe({url:r}){const s=O.useTexture(r);return t.useMemo(()=>{s.colorSpace=R.SRGBColorSpace},[s]),h.jsx("primitive",{attach:"background",object:s})}function me({config:r}){return h.jsx(O.Environment,{files:r.files,background:r.background??!1,blur:r.blur??0,children:h.jsx("group",{scale:r.intensity??1,children:h.jsx("ambientLight",{intensity:0})})})}function pe({config:r}){switch(r.type){case"spot":{const{position:s=[5,10,5],intensity:e=50,castShadow:l=!0,angle:u=Math.PI/6,penumbra:d=.5,decay:y=2,distance:S=0,color:g="#ffffff"}=r;return h.jsx("spotLight",{position:s,intensity:e,castShadow:l,angle:u,penumbra:d,decay:y,distance:S,color:g})}case"point":{const{position:s=[0,5,0],intensity:e=20,color:l="#ffffff",distance:u=0,decay:d=2,castShadow:y=!1}=r;return h.jsx("pointLight",{position:s,intensity:e,color:l,distance:u,decay:d,castShadow:y})}case"directional":{const{position:s=[10,20,10],intensity:e=40,color:l="#ffffff",castShadow:u=!0}=r;return h.jsx("directionalLight",{position:s,intensity:e,color:l,castShadow:u})}case"hemisphere":{const{skyColor:s="#ffffff",groundColor:e="#444444",intensity:l=.5,position:u=[0,10,0]}=r,d=t.useMemo(()=>new R.Color(s),[s]),y=t.useMemo(()=>new R.Color(e),[e]);return h.jsx("hemisphereLight",{args:[d,y,l],position:u})}case"ambient":{const{intensity:s=.5,color:e="#ffffff"}=r;return h.jsx("ambientLight",{intensity:s,color:e})}default:return null}}function de({onChange:r}){const{active:s,progress:e}=O.useProgress();return t.useEffect(()=>{r(s,e)},[s,e,r]),null}function ge({children:r,camera:s={},controls:e={},background:l,shadows:u=!0,lights:d=[{type:"ambient",intensity:.5},{type:"spot",position:[5,10,5],intensity:50,castShadow:!0}],environment:y,contactShadows:S=!0,showLoadingOverlay:g=!0,style:a,className:n}){const[f,m]=t.useState(!1),[x,o]=t.useState(0),i=t.useRef(null),c=t.useCallback((v,p)=>{if(v){i.current!==null&&(window.clearTimeout(i.current),i.current=null),m(!0),o(Math.max(0,Math.min(100,Math.round(p))));return}o(100),i.current=window.setTimeout(()=>{m(!1),o(0),i.current=null},200)},[]);t.useEffect(()=>()=>{i.current!==null&&window.clearTimeout(i.current)},[]);const $={position:s.position||[0,2,5],fov:s.fov||45},M={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},b=typeof S=="object"?{position:S.position||[0,-1,0],opacity:S.opacity??.5,blur:S.blur??2}:S?{position:[0,-1,0],opacity:.5,blur:2}:null;return h.jsxs("div",{style:{...a||{},position:(a==null?void 0:a.position)??"relative"},className:n,children:[h.jsxs(B.Canvas,{shadows:u,camera:{position:$.position,fov:$.fov},style:{width:"100%",height:"100%"},children:[h.jsx(t.Suspense,{fallback:null,children:h.jsx(ue,{background:l})}),y&&h.jsx(t.Suspense,{fallback:null,children:h.jsx(me,{config:y})}),d.map((v,p)=>h.jsx(pe,{config:v},`${v.type}-${p}`)),h.jsx(t.Suspense,{fallback:null,children:r}),h.jsx(ce,{position:$.position,controlsConfig:M}),b&&h.jsx(O.ContactShadows,{position:b.position,opacity:b.opacity,blur:b.blur}),h.jsx(de,{onChange:c})]}),g&&f&&h.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:h.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:[h.jsx("div",{style:{display:"flex",justifyContent:"center",marginBottom:10},children:h.jsxs("svg",{width:"34",height:"34",viewBox:"0 0 34 34","aria-hidden":"true",children:[h.jsx("circle",{cx:"17",cy:"17",r:"14",fill:"none",stroke:"rgba(255,255,255,0.2)",strokeWidth:"4"}),h.jsx("path",{d:"M31 17a14 14 0 0 1-14 14",fill:"none",stroke:"#67b4ff",strokeWidth:"4",strokeLinecap:"round",children:h.jsx("animateTransform",{attributeName:"transform",type:"rotate",from:"0 17 17",to:"360 17 17",dur:"0.9s",repeatCount:"indefinite"})})]})}),h.jsxs("div",{style:{fontSize:12,opacity:.82,marginTop:4},children:[x,"%"]})]})})]})}function K(r,s){const e=t.useRef(new Map),l=t.useRef({}),u=t.useRef({});t.useEffect(()=>{s&&(l.current={...s})},[s]),t.useEffect(()=>{if(!r)return;const g=new Map;r.traverse(a=>{if(a.isMesh){const n=a;n.name&&g.set(n.name,n)}}),e.current=g},[r]),B.useFrame(()=>{const g=e.current;if(g.size===0)return;const a={...l.current,...u.current};for(const[n,f]of Object.entries(a)){const m=g.get(n);m&&m.visible!==f&&(m.visible=f)}});const d=t.useCallback((g,a)=>{u.current[g]=a;const n=e.current.get(g);n&&(n.visible=a)},[]),y=t.useCallback(()=>Array.from(e.current.keys()).sort(),[]),S=t.useCallback(()=>{const g={};return e.current.forEach((a,n)=>{g[n]=a.visible}),g},[]);return{setMeshVisibility:d,getMeshNames:y,getMeshVisibility:S}}function G(r,s){const e=t.useRef(new Map),l=t.useRef(new Map);t.useEffect(()=>{if(!r)return;const a=new Map;r.traverse(n=>{if(n.isMesh){const f=n;(Array.isArray(f.material)?f.material:[f.material]).forEach(x=>{x.name&&!a.has(x.name)&&a.set(x.name,x)})}}),e.current=a,s&&Object.entries(s).forEach(([n,f])=>{const m=a.get(n);if(m&&!Array.isArray(m)){const x=u(f);m.color&&m.color.copy(x),l.current.set(n,x)}})},[r,s]),B.useFrame(()=>{l.current.forEach((a,n)=>{const f=e.current.get(n);if(f&&!Array.isArray(f)){const m=f;m.color&&!m.color.equals(a)&&(m.color.copy(a),m.needsUpdate=!0)}})});const u=a=>typeof a=="string"?new R.Color(a):new R.Color(a[0],a[1],a[2]),d=t.useCallback((a,n)=>{const f=u(n);l.current.set(a,f);const m=e.current.get(a);if(m&&!Array.isArray(m)){const x=m;x.color&&(x.color.copy(f),x.needsUpdate=!0)}},[]),y=t.useCallback(()=>Array.from(e.current.keys()).sort(),[]),S=t.useCallback(a=>{const n=e.current.get(a);if(n&&!Array.isArray(n)){const f=n;if(f.color)return"#"+f.color.getHexString()}return null},[]),g=t.useCallback(()=>{const a={};return e.current.forEach((n,f)=>{if(!Array.isArray(n)){const m=n;m.color&&(a[f]="#"+m.color.getHexString())}}),a},[]);return{setMaterialColor:d,getMaterialNames:y,getMaterialColor:S,getAllMaterialColors:g}}function H(r){const s=r.toLowerCase();if(s.endsWith(".ktx2"))return!0;try{const e=new URL(r,window.location.origin),l=decodeURIComponent(e.hash.replace(/^#/,"")).toLowerCase(),u=decodeURIComponent(e.search).toLowerCase(),d=decodeURIComponent(e.pathname).toLowerCase();return l.endsWith(".ktx2")||u.includes(".ktx2")||d.endsWith(".ktx2")}catch{return s.includes(".ktx2")}}function z(r,s){const{gl:e}=B.useThree(),l=t.useRef(new Map),u=t.useRef(new R.TextureLoader),d=t.useRef(null),y=t.useRef(new Map),S=t.useRef(new Set),g=t.useRef("");t.useEffect(()=>{if(!d.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 i=new ie.KTX2Loader;i.setTranscoderPath("/basis/"),i.detectSupport(e),d.current=i,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()=>{d.current&&(d.current.dispose(),d.current=null)}},[e]),t.useEffect(()=>{if(!r)return;const o=new Map;r.traverse(i=>{if(i.isMesh){const c=i;(Array.isArray(c.material)?c.material:[c.material]).forEach(M=>{M.name&&!o.has(M.name)&&o.set(M.name,M)})}}),l.current=o},[r]);const a=t.useCallback(o=>H(o)?d.current?d.current:(console.warn("[useMaterialTexture] KTX2Loader not initialized, falling back to TextureLoader"),u.current):u.current,[]);t.useEffect(()=>{if(!s||!r)return;const o=l.current;if(o.size===0)return;const i=JSON.stringify(s);if(g.current===i){console.log("[useMaterialTexture] Textures unchanged, skipping reload");return}g.current=i;let c=!1;const $=new Map;Object.entries(s).forEach(([p,A])=>{$.set(p,typeof A=="string"?{map:A}:A)}),console.log("[useMaterialTexture] Starting texture load for",$.size,"materials");const M=[];$.forEach((p,A)=>{var E,L;const P=o.get(A);if(!P||!P.isMeshStandardMaterial){console.warn(`[useMaterialTexture] Material "${A}" not found or not MeshStandardMaterial`);return}const T=P;console.log(`[useMaterialTexture] 📋 Material "${A}" BEFORE reset:`),console.log(` - map: ${T.map?"EXISTS":"null"} ${T.map?`(uuid: ${T.map.uuid})`:""}`),console.log(` - normalMap: ${T.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${T.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${T.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${T.emissiveMap?"EXISTS":"null"}`),console.log(` - aoMap: ${T.aoMap?"EXISTS":"null"}`),console.log(` - color: ${(E=T.color)==null?void 0:E.getHexString()}`),console.log(` - emissive: ${(L=T.emissive)==null?void 0:L.getHexString()}`),console.log(` - material uuid: ${T.uuid}`),Object.entries(p).forEach(([w,j])=>{if(!j)return;const C=w,k=T[C];k&&(console.log(`[useMaterialTexture] 🗑️ Disposing old ${C} (uuid: ${k.uuid})`),k.dispose(),T[C]=null)}),p.emissiveMap&&(T.emissive=new R.Color(0),T.emissiveIntensity=0),T.needsUpdate=!0,T.color=new R.Color(16777215),console.log(`[useMaterialTexture] ✅ Material "${A}" AFTER reset: only specified maps cleared`),Object.entries(p).forEach(([w,j])=>{if(!j)return;const C=`${A}_${w}_${j}`,k=y.current.get(C);if(k){console.log(`[useMaterialTexture] Using cached texture: ${A}.${w}`),c||n(T,w,k);return}if(S.current.has(C)){console.log(`[useMaterialTexture] Skipping already loading: ${A}.${w}`);return}M.push({materialName:A,textureType:w,url:j,material:T})})}),console.log(`[useMaterialTexture] Queued ${M.length} textures to load`);let b=0;const v=()=>{if(c||b>=M.length){console.log("[useMaterialTexture] ✅ All textures loaded"),console.log("[useMaterialTexture] 📊 FINAL material states:"),o.forEach((E,L)=>{var j,C;const w=E;console.log(` Material "${L}":`),console.log(` - map: ${w.map?"EXISTS":"null"} ${w.map?`(colorSpace: ${w.map.colorSpace})`:""}`),console.log(` - normalMap: ${w.normalMap?"EXISTS":"null"}`),console.log(` - roughnessMap: ${w.roughnessMap?"EXISTS":"null"}`),console.log(` - metalnessMap: ${w.metalnessMap?"EXISTS":"null"}`),console.log(` - emissiveMap: ${w.emissiveMap?"EXISTS":"null"}`),console.log(` - color: ${(j=w.color)==null?void 0:j.getHexString()}`),console.log(` - emissive: ${(C=w.emissive)==null?void 0:C.getHexString()}`),console.log(` - emissiveIntensity: ${w.emissiveIntensity}`),console.log(` - roughness: ${w.roughness}`),console.log(` - metalness: ${w.metalness}`)});return}const p=M[b++],A=`${p.materialName}_${p.textureType}_${p.url}`;console.log(`[useMaterialTexture] Loading (${b}/${M.length}): ${p.materialName}.${p.textureType} from ${p.url}`),S.current.add(A);const P=a(p.url),T=H(p.url)?"KTX2Loader":"TextureLoader";console.log(`[useMaterialTexture] Using ${T} for ${p.url}`),P.load(p.url,E=>{var C,k,X,D,I,W;if(S.current.delete(A),c){console.log(`[useMaterialTexture] Disposed, cleaning up texture: ${p.materialName}.${p.textureType}`),E.dispose();return}const L=((C=E.image)==null?void 0:C.width)||((X=(k=E.source)==null?void 0:k.data)==null?void 0:X.width)||"unknown",w=((D=E.image)==null?void 0:D.height)||((W=(I=E.source)==null?void 0:I.data)==null?void 0:W.height)||"unknown";console.log(`[useMaterialTexture] ✅ Loaded: ${p.materialName}.${p.textureType} (${L}x${w})`),E.colorSpace=p.textureType==="map"||p.textureType==="emissiveMap"?R.SRGBColorSpace:R.NoColorSpace,E.wrapS=R.RepeatWrapping,E.wrapT=R.RepeatWrapping,E.flipY=!1,y.current.set(A,E),n(p.material,p.textureType,E);const j=H(p.url)?500:150;console.log(`[useMaterialTexture] Waiting111111 ${j}ms before next texture...`),setTimeout(v,0)},E=>{if(E.lengthComputable){const L=Math.round(E.loaded/E.total*100);L%25===0&&console.log(`[useMaterialTexture] Progress ${p.materialName}.${p.textureType}: ${L}%`)}},E=>{S.current.delete(A),c||(console.error(`[useMaterialTexture] ❌ Failed to load ${p.materialName}.${p.textureType} from ${p.url}`),console.error("[useMaterialTexture] Error details:",E),console.error("[useMaterialTexture] Loader type:",T),H(p.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(v,100)})};return v(),()=>{console.log("[useMaterialTexture] Cleanup: disposed"),c=!0}},[r,s,a]);const n=(o,i,c)=>{var $,M;switch(console.log(`[useMaterialTexture] 🎨 Applying texture: ${o.name}.${i} (texture uuid: ${c.uuid})`),i){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 R.Color(16777215),o.emissiveIntensity=1;break;case"alphaMap":console.log(`[useMaterialTexture] Skipping alphaMap for "${o.name}" to prevent disappearing`);break;case"aoMap":o.aoMap=c;break}o.needsUpdate=!0,console.log(`[useMaterialTexture] ✅ Applied ${i} 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(` - color: ${($=o.color)==null?void 0:$.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=t.useCallback((o,i)=>{const c=typeof i=="string"?{map:i}:i,$=l.current.get(o);if(!$||!$.isMeshStandardMaterial){console.warn(`Material "${o}" not found or not MeshStandardMaterial`);return}const M=$;Object.entries(c).forEach(([b,v])=>{if(!v)return;const p=`${o}_${b}_${v}`,A=y.current.get(p);if(A){n(M,b,A);return}a(v).load(v,T=>{T.colorSpace=b==="map"||b==="emissiveMap"?R.SRGBColorSpace:R.NoColorSpace,T.wrapS=R.RepeatWrapping,T.wrapT=R.RepeatWrapping,y.current.set(p,T),n(M,b,T)},void 0,T=>{console.error(`Failed to load texture ${v}:`,T)})})},[a]),m=t.useCallback(()=>Array.from(l.current.keys()).sort(),[]),x=t.useCallback(o=>{const i=l.current.get(o);if(!i||!i.isMeshStandardMaterial)return;const c=i;c.map=null,c.normalMap=null,c.roughnessMap=null,c.metalnessMap=null,c.emissiveMap=null,c.alphaMap=null,c.aoMap=null,c.needsUpdate=!0},[]);return{setMaterialTextures:f,getMaterialNames:m,clearMaterialTextures:x}}function re({url:r,position:s=[0,0,0],rotation:e=[0,0,0],scale:l=1,meshVisibility:u,materialColors:d,materialTextures:y,onLoad:S,onError:g}){const{scene:a}=O.useGLTF(r),n=t.useRef(S);n.current=S;const f=t.useMemo(()=>{const x=a.clone();console.log("[Model] 🔍 Scene clone created, checking materials...");const o=[],i=new Set,c=[];let $=0;return x.traverse(M=>{if($++,M.type==="Bone"&&c.push(M.name),M.isMesh){const b=M;o.push(b.name),b.castShadow=!0,b.receiveShadow=!0,(Array.isArray(b.material)?b.material:[b.material]).forEach(p=>{i.add(p.name),console.log(`[Model] 📦 Material found: "${p.name}" (uuid: ${p.uuid})`);const A=p;console.log(` - Has map: ${A.map?"YES":"NO"}`),console.log(` - Has normalMap: ${A.normalMap?"YES":"NO"}`),console.log(` - Has roughnessMap: ${A.roughnessMap?"YES":"NO"}`),console.log(` - Has metalnessMap: ${A.metalnessMap?"YES":"NO"}`)})}}),console.log(`[Model] 📊 Clone summary: ${o.length} meshes, ${i.size} materials`),setTimeout(()=>{var M;(M=n.current)==null||M.call(n,{meshes:o.sort(),materials:Array.from(i).sort(),bones:c.sort(),nodeCount:$})},0),x},[a]);K(f,u),G(f,d),z(f,y);const m=typeof l=="number"?[l,l,l]:l;return h.jsx("group",{position:s,rotation:e,scale:m,children:h.jsx("primitive",{object:f})})}re.preload=r=>{O.useGLTF.preload(r)};function se(r,s,e){const{actions:l,names:u}=O.useAnimations(r,s),d=t.useRef(null),y=t.useRef(e==null?void 0:e.defaultAnimation);t.useEffect(()=>{y.current=e==null?void 0:e.defaultAnimation},[e==null?void 0:e.defaultAnimation]),t.useEffect(()=>{if(u.length===0)return;const n=y.current;let f=u[0];if(n){const x=u.find(o=>o===n||o.includes(n));x&&(f=x)}const m=l[f];m&&(m.reset().fadeIn(.5).play(),d.current=m)},[l,u]);const S=t.useCallback((n,f)=>{const{loop:m=!1,crossFadeDuration:x=.2,restoreDefault:o=!0}=f||{};let i=l[n];if(!i){const $=Object.keys(l).find(M=>M.toLowerCase().includes(n.toLowerCase())||n.toLowerCase().includes(M.toLowerCase()));$&&(i=l[$])}if(!i){console.warn(`Animation "${n}" not found. Available: ${u.join(", ")}`);return}const c=d.current;if(!(c===i&&i.isRunning())&&(c&&c!==i&&c.fadeOut(x),i.reset(),i.fadeIn(x),i.setLoop(m?R.LoopRepeat:R.LoopOnce,m?1/0:1),i.clampWhenFinished=!m,i.play(),m||i.getMixer().update(0),d.current=i,o&&!m&&y.current)){const $=i.getMixer(),M=b=>{if(b.action===i){$.removeEventListener("finished",M);const v=l[y.current];v&&(i.fadeOut(x),v.reset().fadeIn(x).play(),d.current=v)}};$.addEventListener("finished",M)}},[l,u]),g=t.useCallback(()=>{var n;(n=d.current)==null||n.fadeOut(.2),d.current=null},[]),a=t.useCallback(()=>u,[u]);return{playAnimation:S,stopAnimation:g,getAnimationNames:a,actions:l}}function q(r,s){const e=t.useRef(s||{}),l=t.useRef([]),u=t.useRef([]);t.useEffect(()=>{const g=new Set,a=[];r.traverse(n=>{n instanceof R.Mesh&&n.morphTargetDictionary&&n.morphTargetInfluences&&(a.push(n),Object.keys(n.morphTargetDictionary).forEach(f=>{g.add(f)}))}),l.current=Array.from(g).sort(),u.current=a},[r]),B.useFrame(()=>{const g=e.current;u.current.forEach(a=>{!a.morphTargetDictionary||!a.morphTargetInfluences||Object.entries(g).forEach(([n,f])=>{const m=a.morphTargetDictionary[n];m!==void 0&&(a.morphTargetInfluences[m]=f)})})}),t.useEffect(()=>{s&&(e.current={...s})},[s]);const d=t.useCallback((g,a)=>{e.current[g]=Math.max(0,Math.min(1,a))},[]),y=t.useCallback(()=>l.current,[]),S=t.useCallback(()=>({...e.current}),[]);return{setMorphTarget:d,getMorphTargetNames:y,getMorphTargetValues:S}}const oe=t.createContext(null);function he(){const r=t.useContext(oe);if(!r)throw new Error("BoneAttachment must be used within an AnimatedModel");return r}const V=t.forwardRef(({url:r,position:s=[0,0,0],rotation:e=[0,0,0],scale:l=1,defaultAnimation:u,animation:d,morphTargets:y,meshVisibility:S,materialColors:g,materialTextures:a,onLoad:n,onError:f,children:m},x)=>{const o=t.useRef(null),i=t.useRef([]),c=t.useRef(n);c.current=n;const{scene:$,animations:M}=O.useGLTF(r),b=t.useMemo(()=>te.clone($),[$]),{playAnimation:v,stopAnimation:p,getAnimationNames:A}=se(M,b,{defaultAnimation:u});t.useEffect(()=>{d&&v(d,{loop:!0,restoreDefault:!1})},[d,v]);const{setMorphTarget:P}=q(b,y),{setMeshVisibility:T,getMeshNames:E}=K(b,S),{setMaterialColor:L,getMaterialNames:w,getMaterialColor:j}=G(b,g),{setMaterialTextures:C,clearMaterialTextures:k}=z(b,a);t.useEffect(()=>{if(!b)return;const I=setTimeout(()=>{var Q;const W=[],_=[],Y=new Set,Z=new Set;let J=0;b.traverse(F=>{if(J++,F.type==="Bone"&&W.push(F.name),F.isMesh){const N=F;_.push(N.name),N.castShadow=!0,N.receiveShadow=!0,(Array.isArray(N.material)?N.material:[N.material]).forEach(U=>{Y.add(U.name),U.shadowSide=R.DoubleSide}),N.morphTargetDictionary&&Object.keys(N.morphTargetDictionary).forEach(U=>{Z.add(U)})}}),i.current=Array.from(Z).sort(),(Q=c.current)==null||Q.call(c,{meshes:_.sort(),materials:Array.from(Y).sort(),bones:W.sort(),nodeCount:J,animations:M.map(F=>F.name),morphTargetNames:i.current})},0);return()=>clearTimeout(I)},[b,M]),t.useImperativeHandle(x,()=>({playAnimation:v,stopAnimation:p,getAnimationNames:A,getGroup:()=>o.current,setMorphTarget:P,getMorphTargetNames:()=>i.current,setMeshVisibility:T,getMeshNames:E,setMaterialColor:L,getMaterialNames:w,getMaterialColor:j,setMaterialTextures:C,clearMaterialTextures:k}));const X=t.useMemo(()=>({scene:b,getBone:I=>b.getObjectByName(I)||null}),[b]),D=typeof l=="number"?[l,l,l]:l;return h.jsx(oe.Provider,{value:X,children:h.jsxs("group",{ref:o,position:s,rotation:e,scale:D,children:[h.jsx("primitive",{object:b}),m]})})});V.displayName="AnimatedModel";V.preload=r=>{O.useGLTF.preload(r)};const ne=t.forwardRef(({url:r,position:s=[0,0,0],rotation:e=[0,0,0],scale:l=1,morphTargets:u,meshVisibility:d,materialColors:y,materialTextures:S,onMorphTargetsFound:g,onLoad:a,onError:n},f)=>{const{scene:m}=O.useGLTF(r),x=t.useRef(a);x.current=a;const o=t.useRef(g);o.current=g;const i=t.useMemo(()=>m.clone(),[m]),{setMorphTarget:c,getMorphTargetNames:$,getMorphTargetValues:M}=q(i,u),{setMeshVisibility:b,getMeshNames:v}=K(i,d),{setMaterialColor:p,getMaterialNames:A,getMaterialColor:P}=G(i,y),{setMaterialTextures:T,clearMaterialTextures:E}=z(i,S);t.useEffect(()=>{var j;const w=$();w.length>0&&((j=o.current)==null||j.call(o,w))},[i,$]),t.useEffect(()=>{var X;if(!i)return;const w=[],j=new Set,C=[];let k=0;i.traverse(D=>{if(k++,D.type==="Bone"&&C.push(D.name),D.isMesh){const I=D;w.push(I.name),I.castShadow=!0,I.receiveShadow=!0,(Array.isArray(I.material)?I.material:[I.material]).forEach(_=>j.add(_.name))}}),(X=x.current)==null||X.call(x,{meshes:w.sort(),materials:Array.from(j).sort(),bones:C.sort(),nodeCount:k})},[i]),t.useImperativeHandle(f,()=>({setMorphTarget:c,getMorphTargetNames:$,getMorphTargetValues:M,setMeshVisibility:b,getMeshNames:v,setMaterialColor:p,getMaterialNames:A,getMaterialColor:P,setMaterialTextures:T,clearMaterialTextures:E}));const L=typeof l=="number"?[l,l,l]:l;return h.jsx("group",{position:s,rotation:e,scale:L,children:h.jsx("primitive",{object:i})})});ne.displayName="MorphableModel";function Me({children:r,bone:s,position:e=[0,0,0],rotation:l=[0,0,0],scale:u=1}){const{getBone:d}=he(),[y,S]=t.useState(null);if(t.useEffect(()=>{const a=d(s);a?S(a):console.warn(`Bone "${s}" not found in model`)},[s,d]),!y)return null;const g=typeof u=="number"?[u,u,u]:u;return B.createPortal(h.jsx("group",{position:e,rotation:l,scale:g,children:r}),y)}function be(r,s){const{scene:e,animations:l}=O.useGLTF(r),u=t.useMemo(()=>te.clone(e),[e]);return t.useEffect(()=>{var a;if(!u)return;const d=[],y=[],S=new Set;let g=0;u.traverse(n=>{if(g++,n.type==="Bone"&&d.push(n.name),n.isMesh){const f=n;y.push(f.name),f.castShadow=!0,f.receiveShadow=!0,(Array.isArray(f.material)?f.material:[f.material]).forEach(x=>{S.add(x.name),x.shadowSide=R.DoubleSide})}}),(a=s==null?void 0:s.onLoad)==null||a.call(s,{meshes:y.sort(),materials:Array.from(S).sort(),bones:d.sort(),nodeCount:g})},[u,s]),{scene:u,animations:l}}function ye(r){O.useGLTF.preload(r)}exports.AnimatedModel=V;exports.BoneAttachment=Me;exports.Model=re;exports.MorphableModel=ne;exports.Scene3D=ge;exports.preloadModel=ye;exports.useAnimationController=se;exports.useClonedModel=be;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
|