sa2kit 1.6.59 → 1.6.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/UniversalFileService-C3WQAFOV.js +15 -0
- package/dist/{UniversalFileService-J6ET6KZK.js.map → UniversalFileService-C3WQAFOV.js.map} +1 -1
- package/dist/UniversalFileService-O3IEROBN.mjs +6 -0
- package/dist/{UniversalFileService-336GFY6N.mjs.map → UniversalFileService-O3IEROBN.mjs.map} +1 -1
- package/dist/ai/llm/index.d.mts +70 -0
- package/dist/ai/llm/index.d.ts +70 -0
- package/dist/ai/llm/index.js +54 -0
- package/dist/ai/llm/index.js.map +1 -0
- package/dist/ai/llm/index.mjs +5 -0
- package/dist/ai/llm/index.mjs.map +1 -0
- package/dist/ai/llm/ui/electron/index.d.mts +5 -0
- package/dist/ai/llm/ui/electron/index.d.ts +5 -0
- package/dist/ai/llm/ui/electron/index.js +21 -0
- package/dist/ai/llm/ui/electron/index.js.map +1 -0
- package/dist/ai/llm/ui/electron/index.mjs +8 -0
- package/dist/ai/llm/ui/electron/index.mjs.map +1 -0
- package/dist/ai/llm/ui/miniapp/index.d.mts +9 -0
- package/dist/ai/llm/ui/miniapp/index.d.ts +9 -0
- package/dist/ai/llm/ui/miniapp/index.js +107 -0
- package/dist/ai/llm/ui/miniapp/index.js.map +1 -0
- package/dist/ai/llm/ui/miniapp/index.mjs +101 -0
- package/dist/ai/llm/ui/miniapp/index.mjs.map +1 -0
- package/dist/ai/llm/ui/rn/index.d.mts +9 -0
- package/dist/ai/llm/ui/rn/index.d.ts +9 -0
- package/dist/ai/llm/ui/rn/index.js +249 -0
- package/dist/ai/llm/ui/rn/index.js.map +1 -0
- package/dist/ai/llm/ui/rn/index.mjs +243 -0
- package/dist/ai/llm/ui/rn/index.mjs.map +1 -0
- package/dist/ai/llm/ui/web/index.d.mts +15 -0
- package/dist/ai/llm/ui/web/index.d.ts +15 -0
- package/dist/ai/llm/ui/web/index.js +21 -0
- package/dist/ai/llm/ui/web/index.js.map +1 -0
- package/dist/ai/llm/ui/web/index.mjs +8 -0
- package/dist/ai/llm/ui/web/index.mjs.map +1 -0
- package/dist/ar/index.d.mts +7 -0
- package/dist/ar/index.d.ts +7 -0
- package/dist/ar/index.js +17 -0
- package/dist/ar/index.js.map +1 -0
- package/dist/ar/index.mjs +4 -0
- package/dist/ar/index.mjs.map +1 -0
- package/dist/auth/index.js +22 -22
- package/dist/auth/index.mjs +2 -2
- package/dist/auth/legacy/db/index.d.mts +5 -0
- package/dist/auth/legacy/db/index.d.ts +5 -0
- package/dist/auth/legacy/db/index.js +34 -0
- package/dist/auth/legacy/db/index.js.map +1 -0
- package/dist/auth/legacy/db/index.mjs +5 -0
- package/dist/auth/legacy/db/index.mjs.map +1 -0
- package/dist/auth/legacy/index.d.mts +51 -0
- package/dist/auth/legacy/index.d.ts +51 -0
- package/dist/auth/legacy/index.js +146 -0
- package/dist/auth/legacy/index.js.map +1 -0
- package/dist/auth/legacy/index.mjs +13 -0
- package/dist/auth/legacy/index.mjs.map +1 -0
- package/dist/auth/legacy/logic/index.d.mts +9 -0
- package/dist/auth/legacy/logic/index.d.ts +9 -0
- package/dist/auth/legacy/logic/index.js +18 -0
- package/dist/auth/legacy/logic/index.js.map +1 -0
- package/dist/auth/legacy/logic/index.mjs +5 -0
- package/dist/auth/legacy/logic/index.mjs.map +1 -0
- package/dist/auth/legacy/routes/index.d.mts +50 -0
- package/dist/auth/legacy/routes/index.d.ts +50 -0
- package/dist/auth/legacy/routes/index.js +34 -0
- package/dist/auth/legacy/routes/index.js.map +1 -0
- package/dist/auth/legacy/routes/index.mjs +5 -0
- package/dist/auth/legacy/routes/index.mjs.map +1 -0
- package/dist/auth/legacy/schema/index.d.mts +401 -0
- package/dist/auth/legacy/schema/index.d.ts +401 -0
- package/dist/auth/legacy/schema/index.js +29 -0
- package/dist/auth/legacy/schema/index.js.map +1 -0
- package/dist/auth/legacy/schema/index.mjs +4 -0
- package/dist/auth/legacy/schema/index.mjs.map +1 -0
- package/dist/auth/legacy/server/index.d.mts +15 -0
- package/dist/auth/legacy/server/index.d.ts +15 -0
- package/dist/auth/legacy/server/index.js +65 -0
- package/dist/auth/legacy/server/index.js.map +1 -0
- package/dist/auth/legacy/server/index.mjs +8 -0
- package/dist/auth/legacy/server/index.mjs.map +1 -0
- package/dist/auth/legacy/services/index.d.mts +40 -0
- package/dist/auth/legacy/services/index.d.ts +40 -0
- package/dist/auth/legacy/services/index.js +14 -0
- package/dist/auth/legacy/services/index.js.map +1 -0
- package/dist/auth/legacy/services/index.mjs +5 -0
- package/dist/auth/legacy/services/index.mjs.map +1 -0
- package/dist/auth/legacy/ui/miniapp/index.d.mts +10 -0
- package/dist/auth/legacy/ui/miniapp/index.d.ts +10 -0
- package/dist/auth/legacy/ui/miniapp/index.js +23 -0
- package/dist/auth/legacy/ui/miniapp/index.js.map +1 -0
- package/dist/auth/legacy/ui/miniapp/index.mjs +6 -0
- package/dist/auth/legacy/ui/miniapp/index.mjs.map +1 -0
- package/dist/auth/legacy/ui/web/index.d.mts +22 -0
- package/dist/auth/legacy/ui/web/index.d.ts +22 -0
- package/dist/auth/legacy/ui/web/index.js +31 -0
- package/dist/auth/legacy/ui/web/index.js.map +1 -0
- package/dist/auth/legacy/ui/web/index.mjs +6 -0
- package/dist/auth/legacy/ui/web/index.mjs.map +1 -0
- package/dist/booking-B0BM8grt.d.mts +141 -0
- package/dist/booking-CUy8u7Za.d.ts +141 -0
- package/dist/{bookingAdminService-Dmg7dC6V.d.mts → bookingAdminService-BNEDyw7U.d.mts} +1 -1
- package/dist/{bookingAdminService-B2QDjSHJ.d.ts → bookingAdminService-BtOtG96L.d.ts} +1 -1
- package/dist/calendar/index.d.mts +390 -237
- package/dist/calendar/index.d.ts +390 -237
- package/dist/calendar/index.js +3825 -3785
- package/dist/calendar/index.js.map +1 -1
- package/dist/calendar/index.mjs +3730 -3696
- package/dist/calendar/index.mjs.map +1 -1
- package/dist/calendar/routes/index.js +30 -327
- package/dist/calendar/routes/index.js.map +1 -1
- package/dist/calendar/routes/index.mjs +1 -323
- package/dist/calendar/routes/index.mjs.map +1 -1
- package/dist/calendar/server.d.mts +6 -0
- package/dist/calendar/server.d.ts +6 -0
- package/dist/calendar/server.js +41 -13
- package/dist/calendar/server.js.map +1 -1
- package/dist/calendar/server.mjs +2 -2
- package/dist/calendar/server.mjs.map +1 -1
- package/dist/{cart-D3o67Q3H.d.ts → cart-Cw3i0Dy6.d.ts} +1 -1
- package/dist/{cart-CcZ7rQyG.d.mts → cart-DLSbsihH.d.mts} +1 -1
- package/dist/chunk-24F7KUED.js +263 -0
- package/dist/chunk-24F7KUED.js.map +1 -0
- package/dist/{chunk-YMS6BPXS.js → chunk-27IUMDDK.js} +3 -3
- package/dist/{chunk-YMS6BPXS.js.map → chunk-27IUMDDK.js.map} +1 -1
- package/dist/chunk-37M6NZIF.js +279 -0
- package/dist/chunk-37M6NZIF.js.map +1 -0
- package/dist/chunk-3JMUNOUT.js +144 -0
- package/dist/chunk-3JMUNOUT.js.map +1 -0
- package/dist/chunk-3PFCOTJP.mjs +256 -0
- package/dist/chunk-3PFCOTJP.mjs.map +1 -0
- package/dist/{chunk-SKCMZYSQ.js → chunk-3YSRTVIY.js} +31 -15
- package/dist/chunk-3YSRTVIY.js.map +1 -0
- package/dist/{chunk-NZZZUMMX.mjs → chunk-57MVE5LL.mjs} +3 -3
- package/dist/{chunk-NZZZUMMX.mjs.map → chunk-57MVE5LL.mjs.map} +1 -1
- package/dist/{chunk-622Y6LTH.mjs → chunk-5BLZEVWK.mjs} +196 -468
- package/dist/chunk-5BLZEVWK.mjs.map +1 -0
- package/dist/{chunk-UVHPCLP6.js → chunk-5LCGOCKG.js} +5 -5
- package/dist/{chunk-UVHPCLP6.js.map → chunk-5LCGOCKG.js.map} +1 -1
- package/dist/chunk-6XUQ2B4K.js +219 -0
- package/dist/chunk-6XUQ2B4K.js.map +1 -0
- package/dist/{chunk-NCOXT7SK.js → chunk-77UEPWVQ.js} +4 -4
- package/dist/{chunk-NCOXT7SK.js.map → chunk-77UEPWVQ.js.map} +1 -1
- package/dist/chunk-C76U5FF4.mjs +10 -0
- package/dist/chunk-C76U5FF4.mjs.map +1 -0
- package/dist/chunk-CFM56MGO.mjs +35 -0
- package/dist/chunk-CFM56MGO.mjs.map +1 -0
- package/dist/{chunk-LJGJPAQ4.js → chunk-COOI6MT3.js} +2 -11
- package/dist/chunk-COOI6MT3.js.map +1 -0
- package/dist/chunk-CPSFYP34.mjs +140 -0
- package/dist/chunk-CPSFYP34.mjs.map +1 -0
- package/dist/chunk-D22QBOCM.mjs +336 -0
- package/dist/chunk-D22QBOCM.mjs.map +1 -0
- package/dist/chunk-DA4QV64P.mjs +35 -0
- package/dist/chunk-DA4QV64P.mjs.map +1 -0
- package/dist/{chunk-FVDPGX6A.mjs → chunk-DWJLOHAE.mjs} +2 -11
- package/dist/chunk-DWJLOHAE.mjs.map +1 -0
- package/dist/chunk-EKDLZND6.js +275 -0
- package/dist/chunk-EKDLZND6.js.map +1 -0
- package/dist/chunk-EKQPFZXQ.js +12 -0
- package/dist/chunk-EKQPFZXQ.js.map +1 -0
- package/dist/chunk-ERAAB5VG.js +324 -0
- package/dist/chunk-ERAAB5VG.js.map +1 -0
- package/dist/chunk-ESLY72VI.mjs +175 -0
- package/dist/chunk-ESLY72VI.mjs.map +1 -0
- package/dist/chunk-FGQGWW73.js +38 -0
- package/dist/chunk-FGQGWW73.js.map +1 -0
- package/dist/chunk-FXQOXLDE.js +120 -0
- package/dist/chunk-FXQOXLDE.js.map +1 -0
- package/dist/chunk-FZELCJR7.mjs +19 -0
- package/dist/chunk-FZELCJR7.mjs.map +1 -0
- package/dist/{chunk-HHVDOIPV.js → chunk-H3P2PGZL.js} +3 -3
- package/dist/{chunk-HHVDOIPV.js.map → chunk-H3P2PGZL.js.map} +1 -1
- package/dist/chunk-HBQMN5QM.mjs +10 -0
- package/dist/chunk-HBQMN5QM.mjs.map +1 -0
- package/dist/chunk-ITRIXMXF.mjs +862 -0
- package/dist/chunk-ITRIXMXF.mjs.map +1 -0
- package/dist/chunk-IUWSCUDC.js +4 -0
- package/dist/chunk-IUWSCUDC.js.map +1 -0
- package/dist/chunk-JCKCKRC2.js +50 -0
- package/dist/chunk-JCKCKRC2.js.map +1 -0
- package/dist/chunk-L7GQNY54.mjs +286 -0
- package/dist/chunk-L7GQNY54.mjs.map +1 -0
- package/dist/{chunk-ZRWED7Q6.js → chunk-LDVJ7URJ.js} +235 -520
- package/dist/chunk-LDVJ7URJ.js.map +1 -0
- package/dist/{chunk-WK3HTUID.js → chunk-MLP74E3O.js} +609 -1643
- package/dist/chunk-MLP74E3O.js.map +1 -0
- package/dist/chunk-NAX4TUT7.js +182 -0
- package/dist/chunk-NAX4TUT7.js.map +1 -0
- package/dist/chunk-NW4EN4YI.mjs +213 -0
- package/dist/chunk-NW4EN4YI.mjs.map +1 -0
- package/dist/{chunk-7CMGQX3S.mjs → chunk-OX6VMQDU.mjs} +14 -13
- package/dist/chunk-OX6VMQDU.mjs.map +1 -0
- package/dist/chunk-P3QMT3AY.mjs +44 -0
- package/dist/chunk-P3QMT3AY.mjs.map +1 -0
- package/dist/chunk-PJ4KYAQZ.mjs +631 -0
- package/dist/chunk-PJ4KYAQZ.mjs.map +1 -0
- package/dist/chunk-PLSEAREM.js +345 -0
- package/dist/chunk-PLSEAREM.js.map +1 -0
- package/dist/{chunk-EGJPS7OL.mjs → chunk-QZU4UJZG.mjs} +3 -3
- package/dist/{chunk-EGJPS7OL.mjs.map → chunk-QZU4UJZG.mjs.map} +1 -1
- package/dist/chunk-RJVR33ME.mjs +3 -0
- package/dist/chunk-RJVR33ME.mjs.map +1 -0
- package/dist/chunk-SYBHDB2D.js +650 -0
- package/dist/chunk-SYBHDB2D.js.map +1 -0
- package/dist/chunk-TVKVM7JT.js +21 -0
- package/dist/chunk-TVKVM7JT.js.map +1 -0
- package/dist/{chunk-UZB4IO3T.mjs → chunk-UTB72ZJ7.mjs} +415 -1449
- package/dist/chunk-UTB72ZJ7.mjs.map +1 -0
- package/dist/chunk-V5HE6IYN.js +12 -0
- package/dist/chunk-V5HE6IYN.js.map +1 -0
- package/dist/chunk-V7EVKD5G.mjs +116 -0
- package/dist/chunk-V7EVKD5G.mjs.map +1 -0
- package/dist/chunk-VGPR3KLR.js +872 -0
- package/dist/chunk-VGPR3KLR.js.map +1 -0
- package/dist/chunk-VS7WATQD.js +255 -0
- package/dist/chunk-VS7WATQD.js.map +1 -0
- package/dist/chunk-VSP7XJT5.mjs +272 -0
- package/dist/chunk-VSP7XJT5.mjs.map +1 -0
- package/dist/{chunk-SNBILYSH.mjs → chunk-VTKAIOP5.mjs} +5 -5
- package/dist/{chunk-SNBILYSH.mjs.map → chunk-VTKAIOP5.mjs.map} +1 -1
- package/dist/chunk-VULJUXTF.mjs +267 -0
- package/dist/chunk-VULJUXTF.mjs.map +1 -0
- package/dist/chunk-XAHM6B3V.js +44 -0
- package/dist/chunk-XAHM6B3V.js.map +1 -0
- package/dist/chunk-YSF5YISM.mjs +248 -0
- package/dist/chunk-YSF5YISM.mjs.map +1 -0
- package/dist/{chunk-OFYBMMWT.mjs → chunk-YYJEVAJI.mjs} +3 -3
- package/dist/{chunk-OFYBMMWT.mjs.map → chunk-YYJEVAJI.mjs.map} +1 -1
- package/dist/components/index.d.mts +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +182 -181
- package/dist/components/index.mjs +4 -3
- package/dist/{booking-BXtkG2ns.d.mts → index-Bi666jIm.d.mts} +1 -139
- package/dist/{booking-BXtkG2ns.d.ts → index-Bi666jIm.d.ts} +1 -139
- package/dist/index-DNKZ7-R_.d.mts +184 -0
- package/dist/index-DNKZ7-R_.d.ts +184 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +285 -229
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -10
- package/dist/index.mjs.map +1 -1
- package/dist/mikuFusionGame/index.js +3 -3
- package/dist/mikuFusionGame/index.mjs +2 -2
- package/dist/mmd/index.d.mts +67 -9
- package/dist/mmd/index.d.ts +67 -9
- package/dist/mmd/index.js +969 -625
- package/dist/mmd/index.js.map +1 -1
- package/dist/mmd/index.mjs +969 -628
- package/dist/mmd/index.mjs.map +1 -1
- package/dist/portfolio/index.js +10 -9
- package/dist/portfolio/index.mjs +5 -4
- package/dist/qqbot/index.d.mts +2 -0
- package/dist/qqbot/index.d.ts +2 -0
- package/dist/qqbot/index.js +21 -0
- package/dist/qqbot/index.js.map +1 -0
- package/dist/qqbot/index.mjs +4 -0
- package/dist/qqbot/index.mjs.map +1 -0
- package/dist/qqbot/server/index.d.mts +91 -0
- package/dist/qqbot/server/index.d.ts +91 -0
- package/dist/qqbot/server/index.js +21 -0
- package/dist/qqbot/server/index.js.map +1 -0
- package/dist/qqbot/server/index.mjs +4 -0
- package/dist/qqbot/server/index.mjs.map +1 -0
- package/dist/qqbot/ui/web/index.d.mts +10 -0
- package/dist/qqbot/ui/web/index.d.ts +10 -0
- package/dist/qqbot/ui/web/index.js +105 -0
- package/dist/qqbot/ui/web/index.js.map +1 -0
- package/dist/qqbot/ui/web/index.mjs +99 -0
- package/dist/qqbot/ui/web/index.mjs.map +1 -0
- package/dist/screenReceiver/index.d.mts +78 -0
- package/dist/screenReceiver/index.d.ts +78 -0
- package/dist/screenReceiver/index.js +17 -0
- package/dist/screenReceiver/index.js.map +1 -0
- package/dist/screenReceiver/index.mjs +4 -0
- package/dist/screenReceiver/index.mjs.map +1 -0
- package/dist/screenReceiver/server/index.d.mts +36 -0
- package/dist/screenReceiver/server/index.d.ts +36 -0
- package/dist/screenReceiver/server/index.js +160 -0
- package/dist/screenReceiver/server/index.js.map +1 -0
- package/dist/screenReceiver/server/index.mjs +157 -0
- package/dist/screenReceiver/server/index.mjs.map +1 -0
- package/dist/showmasterpiece/db/index.js +42 -42
- package/dist/showmasterpiece/db/index.mjs +1 -1
- package/dist/showmasterpiece/index.d.mts +8 -6
- package/dist/showmasterpiece/index.d.ts +8 -6
- package/dist/showmasterpiece/index.js +142 -130
- package/dist/showmasterpiece/index.js.map +1 -1
- package/dist/showmasterpiece/index.mjs +18 -6
- package/dist/showmasterpiece/index.mjs.map +1 -1
- package/dist/showmasterpiece/logic/index.d.mts +9 -17
- package/dist/showmasterpiece/logic/index.d.ts +9 -17
- package/dist/showmasterpiece/logic/index.js +35 -34
- package/dist/showmasterpiece/logic/index.mjs +3 -2
- package/dist/showmasterpiece/logic/miniapp/index.d.mts +15 -0
- package/dist/showmasterpiece/logic/miniapp/index.d.ts +15 -0
- package/dist/showmasterpiece/logic/miniapp/index.js +42 -0
- package/dist/showmasterpiece/logic/miniapp/index.js.map +1 -0
- package/dist/showmasterpiece/logic/miniapp/index.mjs +5 -0
- package/dist/showmasterpiece/logic/miniapp/index.mjs.map +1 -0
- package/dist/showmasterpiece/server/index.js +42 -42
- package/dist/showmasterpiece/server/index.mjs +1 -1
- package/dist/showmasterpiece/ui/miniapp/index.d.mts +5 -2
- package/dist/showmasterpiece/ui/miniapp/index.d.ts +5 -2
- package/dist/showmasterpiece/ui/miniapp/index.js +83 -55
- package/dist/showmasterpiece/ui/miniapp/index.js.map +1 -1
- package/dist/showmasterpiece/ui/miniapp/index.mjs +83 -55
- package/dist/showmasterpiece/ui/miniapp/index.mjs.map +1 -1
- package/dist/showmasterpiece/ui/web/index.d.mts +3 -2
- package/dist/showmasterpiece/ui/web/index.d.ts +3 -2
- package/dist/showmasterpiece/ui/web/index.js +44 -33
- package/dist/showmasterpiece/ui/web/index.mjs +16 -5
- package/dist/testYourself/index.js +13 -13
- package/dist/testYourself/index.mjs +2 -2
- package/dist/types-B-hOccQw.d.mts +122 -0
- package/dist/types-B8rGXc4e.d.mts +38 -0
- package/dist/types-Cg89HGz2.d.ts +38 -0
- package/dist/types-CvKvpyN8.d.mts +48 -0
- package/dist/types-CvKvpyN8.d.ts +48 -0
- package/dist/types-Dy6x2gJW.d.ts +122 -0
- package/dist/universalFile/server/index.js +11 -11
- package/dist/universalFile/server/index.mjs +4 -4
- package/package.json +106 -1
- package/dist/UniversalFileService-336GFY6N.mjs +0 -6
- package/dist/UniversalFileService-J6ET6KZK.js +0 -15
- package/dist/chunk-622Y6LTH.mjs.map +0 -1
- package/dist/chunk-7CMGQX3S.mjs.map +0 -1
- package/dist/chunk-FVDPGX6A.mjs.map +0 -1
- package/dist/chunk-GVVS4IMM.mjs +0 -302
- package/dist/chunk-GVVS4IMM.mjs.map +0 -1
- package/dist/chunk-LJGJPAQ4.js.map +0 -1
- package/dist/chunk-SKCMZYSQ.js.map +0 -1
- package/dist/chunk-UZB4IO3T.mjs.map +0 -1
- package/dist/chunk-WC5QFO3T.js +0 -314
- package/dist/chunk-WC5QFO3T.js.map +0 -1
- package/dist/chunk-WK3HTUID.js.map +0 -1
- package/dist/chunk-ZRWED7Q6.js.map +0 -1
package/dist/mmd/index.mjs
CHANGED
|
@@ -2,14 +2,15 @@ import { PMXParser } from '../chunk-RSJSZ7QH.mjs';
|
|
|
2
2
|
export { PMXParser } from '../chunk-RSJSZ7QH.mjs';
|
|
3
3
|
import { useMusic } from '../chunk-EB4NR623.mjs';
|
|
4
4
|
import '../chunk-4HC6M7FK.mjs';
|
|
5
|
+
import { DEFAULT_AR_ASSETS, loadARJS } from '../chunk-CFM56MGO.mjs';
|
|
5
6
|
import '../chunk-WMJKH4XE.mjs';
|
|
6
|
-
import React10, { forwardRef, useRef, useState, useEffect, useImperativeHandle, useCallback, useMemo } from 'react';
|
|
7
|
+
import React10, { forwardRef, useRef, useState, useEffect, useImperativeHandle, useCallback, useMemo, useId } from 'react';
|
|
7
8
|
import { clsx } from 'clsx';
|
|
8
9
|
import * as THREE2 from 'three';
|
|
9
|
-
import {
|
|
10
|
-
import { SkipBack, Pause, Play, SkipForward, Camera, Repeat, Repeat1, Shuffle, ListMusic, Music, X, Search, Loader2, Grid3x3, Settings, Minimize, Maximize, Video, Check, User, Image } from 'lucide-react';
|
|
10
|
+
import { MMDAnimationHelper, MMDLoader, OutlineEffect, OrbitControls } from 'three-stdlib';
|
|
11
|
+
import { SkipBack, Pause, Play, SkipForward, Camera, Repeat, Repeat1, Shuffle, ListMusic, Music, X, Search, Loader2, Upload, CheckCircle2, Grid3x3, Settings, Minimize, Maximize, Video, Check, User, Image } from 'lucide-react';
|
|
12
|
+
import JSZip from 'jszip';
|
|
11
13
|
import { createPortal } from 'react-dom';
|
|
12
|
-
import Script from 'next/script';
|
|
13
14
|
|
|
14
15
|
// src/mmd/pmx/editor/PMXEditor.ts
|
|
15
16
|
var PMXEditor = class {
|
|
@@ -3413,6 +3414,188 @@ var MMDLightingDebugPanel = ({
|
|
|
3413
3414
|
));
|
|
3414
3415
|
};
|
|
3415
3416
|
MMDLightingDebugPanel.displayName = "MMDLightingDebugPanel";
|
|
3417
|
+
var MMD_UPLOAD_CONFIGS = {
|
|
3418
|
+
model: {
|
|
3419
|
+
moduleId: "mmd-models",
|
|
3420
|
+
acceptedTypes: [".zip"],
|
|
3421
|
+
maxFileSize: 150,
|
|
3422
|
+
description: "MMD model package (ZIP)",
|
|
3423
|
+
hint: "Include PMX/PMD and textures in the ZIP with original folder structure."
|
|
3424
|
+
},
|
|
3425
|
+
motion: {
|
|
3426
|
+
moduleId: "mmd-motions",
|
|
3427
|
+
acceptedTypes: [".vmd"],
|
|
3428
|
+
maxFileSize: 20,
|
|
3429
|
+
description: "MMD motion file"
|
|
3430
|
+
},
|
|
3431
|
+
camera: {
|
|
3432
|
+
moduleId: "mmd-cameras",
|
|
3433
|
+
acceptedTypes: [".vmd"],
|
|
3434
|
+
maxFileSize: 10,
|
|
3435
|
+
description: "MMD camera motion"
|
|
3436
|
+
},
|
|
3437
|
+
audio: {
|
|
3438
|
+
moduleId: "mmd-audios",
|
|
3439
|
+
acceptedTypes: [".mp3", ".wav", ".ogg", ".m4a"],
|
|
3440
|
+
maxFileSize: 20,
|
|
3441
|
+
description: "Audio track"
|
|
3442
|
+
},
|
|
3443
|
+
stage: {
|
|
3444
|
+
moduleId: "mmd-stages",
|
|
3445
|
+
acceptedTypes: [".zip"],
|
|
3446
|
+
maxFileSize: 200,
|
|
3447
|
+
description: "Stage package (ZIP)",
|
|
3448
|
+
hint: "Include stage model and textures in the ZIP with original folder structure."
|
|
3449
|
+
},
|
|
3450
|
+
thumbnail: {
|
|
3451
|
+
moduleId: "mmd-thumbnails",
|
|
3452
|
+
acceptedTypes: [".jpg", ".jpeg", ".png", ".webp"],
|
|
3453
|
+
maxFileSize: 5,
|
|
3454
|
+
description: "Thumbnail image"
|
|
3455
|
+
}
|
|
3456
|
+
};
|
|
3457
|
+
var formatMegabytes = (size) => `${(size / 1024 / 1024).toFixed(2)} MB`;
|
|
3458
|
+
var MMDUploadPanel = ({
|
|
3459
|
+
resourceType,
|
|
3460
|
+
fileService,
|
|
3461
|
+
userId,
|
|
3462
|
+
permission = "public",
|
|
3463
|
+
label,
|
|
3464
|
+
description,
|
|
3465
|
+
hint,
|
|
3466
|
+
acceptedTypes,
|
|
3467
|
+
maxFileSizeMB,
|
|
3468
|
+
validateZip = true,
|
|
3469
|
+
disabled = false,
|
|
3470
|
+
className,
|
|
3471
|
+
style,
|
|
3472
|
+
onUploaded,
|
|
3473
|
+
onError,
|
|
3474
|
+
onProgress
|
|
3475
|
+
}) => {
|
|
3476
|
+
const inputId = useId();
|
|
3477
|
+
const [uploading, setUploading] = useState(false);
|
|
3478
|
+
const [progress, setProgress] = useState(null);
|
|
3479
|
+
const [error, setError] = useState(null);
|
|
3480
|
+
const [uploadedFile, setUploadedFile] = useState(null);
|
|
3481
|
+
const [uploadedUrl, setUploadedUrl] = useState(null);
|
|
3482
|
+
const [dragOver, setDragOver] = useState(false);
|
|
3483
|
+
const config = MMD_UPLOAD_CONFIGS[resourceType];
|
|
3484
|
+
const mergedAcceptedTypes = acceptedTypes ?? config.acceptedTypes;
|
|
3485
|
+
const maxSize = maxFileSizeMB ?? config.maxFileSize;
|
|
3486
|
+
const hintText = hint ?? config.hint;
|
|
3487
|
+
const titleText = label ?? config.description;
|
|
3488
|
+
const descriptionText = description ?? `Max ${maxSize} MB`;
|
|
3489
|
+
const acceptAttr = useMemo(() => mergedAcceptedTypes.join(","), [mergedAcceptedTypes]);
|
|
3490
|
+
const validateZipContents = async (file) => {
|
|
3491
|
+
if (!validateZip || !(resourceType === "model" || resourceType === "stage")) return;
|
|
3492
|
+
const buffer = await file.arrayBuffer();
|
|
3493
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
3494
|
+
const entries = Object.keys(zip.files);
|
|
3495
|
+
if (!entries.length) {
|
|
3496
|
+
throw new Error("ZIP is empty.");
|
|
3497
|
+
}
|
|
3498
|
+
const hasModel = entries.some((name) => /\.[pP][mM][xX]$/.test(name)) || resourceType === "stage" && entries.some((name) => /\.[pP][mM][dD]$/.test(name));
|
|
3499
|
+
const hasAssets = entries.some(
|
|
3500
|
+
(name) => /\.(png|jpg|jpeg|bmp|tga|dds|spa|sph)$/i.test(name)
|
|
3501
|
+
);
|
|
3502
|
+
if (!hasModel) {
|
|
3503
|
+
throw new Error("ZIP does not contain a PMX/PMD model file.");
|
|
3504
|
+
}
|
|
3505
|
+
if (!hasAssets) {
|
|
3506
|
+
throw new Error("ZIP does not include texture assets.");
|
|
3507
|
+
}
|
|
3508
|
+
};
|
|
3509
|
+
const handleUpload = async (file) => {
|
|
3510
|
+
if (disabled || uploading) return;
|
|
3511
|
+
setError(null);
|
|
3512
|
+
setProgress(null);
|
|
3513
|
+
if (file.size > maxSize * 1024 * 1024) {
|
|
3514
|
+
setError(`File size exceeds ${maxSize} MB.`);
|
|
3515
|
+
return;
|
|
3516
|
+
}
|
|
3517
|
+
try {
|
|
3518
|
+
setUploading(true);
|
|
3519
|
+
await validateZipContents(file);
|
|
3520
|
+
const fileInfo = {
|
|
3521
|
+
file,
|
|
3522
|
+
moduleId: config.moduleId,
|
|
3523
|
+
businessId: userId,
|
|
3524
|
+
permission
|
|
3525
|
+
};
|
|
3526
|
+
const metadata = await fileService.uploadFile(fileInfo, (progressEvent) => {
|
|
3527
|
+
setProgress(progressEvent);
|
|
3528
|
+
onProgress?.(progressEvent);
|
|
3529
|
+
});
|
|
3530
|
+
let url;
|
|
3531
|
+
if (fileService.getFileUrl) {
|
|
3532
|
+
url = await fileService.getFileUrl(metadata.id);
|
|
3533
|
+
setUploadedUrl(url ?? null);
|
|
3534
|
+
} else {
|
|
3535
|
+
setUploadedUrl(null);
|
|
3536
|
+
}
|
|
3537
|
+
setUploadedFile(metadata);
|
|
3538
|
+
setUploading(false);
|
|
3539
|
+
onUploaded?.({ file: metadata, url });
|
|
3540
|
+
} catch (err) {
|
|
3541
|
+
const message = err instanceof Error ? err.message : "Upload failed.";
|
|
3542
|
+
setError(message);
|
|
3543
|
+
setUploading(false);
|
|
3544
|
+
onError?.(err instanceof Error ? err : new Error(message));
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
const handleFileInput = (event) => {
|
|
3548
|
+
const file = event.target.files?.[0];
|
|
3549
|
+
if (file) {
|
|
3550
|
+
handleUpload(file);
|
|
3551
|
+
}
|
|
3552
|
+
};
|
|
3553
|
+
const handleDrop = (event) => {
|
|
3554
|
+
event.preventDefault();
|
|
3555
|
+
setDragOver(false);
|
|
3556
|
+
const file = event.dataTransfer.files?.[0];
|
|
3557
|
+
if (file) {
|
|
3558
|
+
handleUpload(file);
|
|
3559
|
+
}
|
|
3560
|
+
};
|
|
3561
|
+
return /* @__PURE__ */ React10.createElement("div", { className: clsx("space-y-4", className), style }, /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("div", { className: "text-sm font-semibold text-gray-900" }, titleText), /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-gray-500" }, descriptionText), hintText && /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-amber-600 mt-1" }, hintText)), /* @__PURE__ */ React10.createElement(
|
|
3562
|
+
"div",
|
|
3563
|
+
{
|
|
3564
|
+
className: clsx(
|
|
3565
|
+
"rounded-lg border-2 border-dashed px-4 py-6 text-center transition-colors",
|
|
3566
|
+
dragOver ? "border-blue-500 bg-blue-50" : "border-gray-300",
|
|
3567
|
+
disabled ? "opacity-50 pointer-events-none" : "cursor-pointer"
|
|
3568
|
+
),
|
|
3569
|
+
onDragOver: (event) => {
|
|
3570
|
+
event.preventDefault();
|
|
3571
|
+
setDragOver(true);
|
|
3572
|
+
},
|
|
3573
|
+
onDragLeave: () => setDragOver(false),
|
|
3574
|
+
onDrop: handleDrop
|
|
3575
|
+
},
|
|
3576
|
+
/* @__PURE__ */ React10.createElement(
|
|
3577
|
+
"input",
|
|
3578
|
+
{
|
|
3579
|
+
id: inputId,
|
|
3580
|
+
type: "file",
|
|
3581
|
+
accept: acceptAttr,
|
|
3582
|
+
className: "hidden",
|
|
3583
|
+
onChange: handleFileInput,
|
|
3584
|
+
disabled: disabled || uploading
|
|
3585
|
+
}
|
|
3586
|
+
),
|
|
3587
|
+
/* @__PURE__ */ React10.createElement("label", { htmlFor: inputId, className: "flex flex-col items-center gap-2" }, /* @__PURE__ */ React10.createElement(Upload, { className: "h-6 w-6 text-gray-500" }), /* @__PURE__ */ React10.createElement("span", { className: "text-sm text-gray-600" }, "Click to select or drag file here"), /* @__PURE__ */ React10.createElement("span", { className: "text-xs text-gray-400" }, mergedAcceptedTypes.join(", ")))
|
|
3588
|
+
), uploading && /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2 text-sm text-blue-600" }, /* @__PURE__ */ React10.createElement(Loader2, { className: "h-4 w-4 animate-spin" }), "Uploading", progress ? ` ${progress.progress}%` : "..."), progress && /* @__PURE__ */ React10.createElement("div", { className: "text-xs text-gray-500" }, formatMegabytes(progress.uploadedBytes), " / ", formatMegabytes(progress.totalBytes)), error && /* @__PURE__ */ React10.createElement("div", { className: "text-sm text-red-600" }, error), uploadedFile && /* @__PURE__ */ React10.createElement("div", { className: "flex items-center justify-between rounded-lg border border-green-200 bg-green-50 px-3 py-2 text-sm text-green-700" }, /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React10.createElement(CheckCircle2, { className: "h-4 w-4" }), /* @__PURE__ */ React10.createElement("span", { className: "truncate" }, uploadedFile.originalName)), uploadedUrl && /* @__PURE__ */ React10.createElement(
|
|
3589
|
+
"a",
|
|
3590
|
+
{
|
|
3591
|
+
href: uploadedUrl,
|
|
3592
|
+
target: "_blank",
|
|
3593
|
+
rel: "noreferrer",
|
|
3594
|
+
className: "text-green-700 underline"
|
|
3595
|
+
},
|
|
3596
|
+
"Open"
|
|
3597
|
+
)));
|
|
3598
|
+
};
|
|
3416
3599
|
function diagnoseMaterialsMMD(scene, renderer) {
|
|
3417
3600
|
const report = {
|
|
3418
3601
|
totalMaterials: 0,
|
|
@@ -5064,6 +5247,8 @@ var MMDVisualNovel = forwardRef(
|
|
|
5064
5247
|
onScriptComplete,
|
|
5065
5248
|
onError,
|
|
5066
5249
|
showDebugInfo = false,
|
|
5250
|
+
debug = false,
|
|
5251
|
+
onTransitionStateChange,
|
|
5067
5252
|
showSkipButton = true,
|
|
5068
5253
|
showAutoButton = true,
|
|
5069
5254
|
showHistoryButton = true,
|
|
@@ -5103,6 +5288,26 @@ var MMDVisualNovel = forwardRef(
|
|
|
5103
5288
|
const cheerParticlesRef = useRef(null);
|
|
5104
5289
|
const currentNode = nodes[currentNodeIndex];
|
|
5105
5290
|
const currentDialogue = currentNode?.dialogues[currentDialogueIndex] || null;
|
|
5291
|
+
const log = useCallback((...args) => {
|
|
5292
|
+
if (!debug) return;
|
|
5293
|
+
console.log("[MMDVisualNovel]", ...args);
|
|
5294
|
+
}, [debug]);
|
|
5295
|
+
useEffect(() => {
|
|
5296
|
+
if (!onTransitionStateChange) return;
|
|
5297
|
+
if (!isStarted) {
|
|
5298
|
+
onTransitionStateChange("idle");
|
|
5299
|
+
return;
|
|
5300
|
+
}
|
|
5301
|
+
if (isTransitioning) {
|
|
5302
|
+
onTransitionStateChange("transitioning");
|
|
5303
|
+
return;
|
|
5304
|
+
}
|
|
5305
|
+
if (isLoading || !isAnimationPlaying) {
|
|
5306
|
+
onTransitionStateChange("loading");
|
|
5307
|
+
return;
|
|
5308
|
+
}
|
|
5309
|
+
onTransitionStateChange("ready");
|
|
5310
|
+
}, [isStarted, isTransitioning, isLoading, isAnimationPlaying, onTransitionStateChange]);
|
|
5106
5311
|
const addToHistory = useCallback((dialogue, nodeIndex, dialogueIndex) => {
|
|
5107
5312
|
setHistory((prev) => [
|
|
5108
5313
|
...prev,
|
|
@@ -5134,11 +5339,11 @@ var MMDVisualNovel = forwardRef(
|
|
|
5134
5339
|
if (!node) return;
|
|
5135
5340
|
const currentResources = nodes[currentNodeIndex]?.resources;
|
|
5136
5341
|
if (!force && currentResources?.motionPath && !isVmdFinishedRef.current) {
|
|
5137
|
-
|
|
5342
|
+
log("VMD not finished, showing confirmation");
|
|
5138
5343
|
setPendingNodeIndex(nodeIndex);
|
|
5139
5344
|
return;
|
|
5140
5345
|
}
|
|
5141
|
-
|
|
5346
|
+
log("Transitioning to node", nodeIndex);
|
|
5142
5347
|
setIsTransitioning(true);
|
|
5143
5348
|
setIsLoading(true);
|
|
5144
5349
|
setIsAnimationPlaying(false);
|
|
@@ -5160,7 +5365,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5160
5365
|
}
|
|
5161
5366
|
setTimeout(() => {
|
|
5162
5367
|
setIsTransitioning(false);
|
|
5163
|
-
|
|
5368
|
+
log("Transition to node completed, waiting for model load", nodeIndex);
|
|
5164
5369
|
}, 100);
|
|
5165
5370
|
}, 300);
|
|
5166
5371
|
},
|
|
@@ -5174,7 +5379,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5174
5379
|
const val = variables[key];
|
|
5175
5380
|
if (val !== void 0 && map[val] !== void 0) {
|
|
5176
5381
|
nextNodeIndex = map[val];
|
|
5177
|
-
|
|
5382
|
+
log("Branching", { key, val, nextNodeIndex });
|
|
5178
5383
|
} else {
|
|
5179
5384
|
nextNodeIndex = defaultIndex;
|
|
5180
5385
|
}
|
|
@@ -5182,7 +5387,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5182
5387
|
if (nextNodeIndex < nodes.length && nextNodeIndex >= 0) {
|
|
5183
5388
|
goToNode(nextNodeIndex);
|
|
5184
5389
|
} else if (loop) {
|
|
5185
|
-
|
|
5390
|
+
log("Reached final node, showing loop confirmation");
|
|
5186
5391
|
setShowLoopConfirm(true);
|
|
5187
5392
|
} else {
|
|
5188
5393
|
onScriptComplete?.();
|
|
@@ -5274,7 +5479,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5274
5479
|
if (nextNodeIndex < nodes.length) {
|
|
5275
5480
|
goToNode(nextNodeIndex);
|
|
5276
5481
|
} else if (loop) {
|
|
5277
|
-
|
|
5482
|
+
log("Skip reached final node, showing loop confirmation");
|
|
5278
5483
|
setShowLoopConfirm(true);
|
|
5279
5484
|
} else {
|
|
5280
5485
|
onScriptComplete?.();
|
|
@@ -5301,16 +5506,16 @@ var MMDVisualNovel = forwardRef(
|
|
|
5301
5506
|
setIsLoading(true);
|
|
5302
5507
|
setIsAnimationPlaying(false);
|
|
5303
5508
|
typingCompleteRef.current = false;
|
|
5304
|
-
|
|
5509
|
+
log("Back to start screen");
|
|
5305
5510
|
}, [initialNodeIndex, initialDialogueIndex]);
|
|
5306
5511
|
const handleCheer = useCallback(() => {
|
|
5307
|
-
|
|
5512
|
+
log("Trigger cheer effect");
|
|
5308
5513
|
cheerParticlesRef.current?.trigger();
|
|
5309
5514
|
}, []);
|
|
5310
5515
|
const handleRestartLoop = useCallback(() => {
|
|
5311
5516
|
setShowLoopConfirm(false);
|
|
5312
5517
|
goToNode(0, true);
|
|
5313
|
-
|
|
5518
|
+
log("Restart loop");
|
|
5314
5519
|
}, [goToNode]);
|
|
5315
5520
|
useImperativeHandle(
|
|
5316
5521
|
ref,
|
|
@@ -5379,17 +5584,17 @@ var MMDVisualNovel = forwardRef(
|
|
|
5379
5584
|
loop: currentNode.loopAnimation === true,
|
|
5380
5585
|
mobileOptimization,
|
|
5381
5586
|
onLoad: () => {
|
|
5382
|
-
|
|
5587
|
+
log("MMDPlayerBase onLoad");
|
|
5383
5588
|
setIsLoading(false);
|
|
5384
5589
|
if (isStartedRef.current) {
|
|
5385
|
-
|
|
5590
|
+
log("Game already started, triggering play");
|
|
5386
5591
|
setTimeout(() => {
|
|
5387
5592
|
playerRef.current?.play();
|
|
5388
5593
|
}, 100);
|
|
5389
5594
|
}
|
|
5390
5595
|
},
|
|
5391
5596
|
onPlay: () => {
|
|
5392
|
-
|
|
5597
|
+
log("MMDPlayerBase onPlay");
|
|
5393
5598
|
setIsAnimationPlaying(true);
|
|
5394
5599
|
},
|
|
5395
5600
|
onTimeUpdate: (time) => {
|
|
@@ -5398,7 +5603,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5398
5603
|
const isLooped = time < lastAnimationTimeRef.current && lastAnimationTimeRef.current > 0;
|
|
5399
5604
|
if (isNearEnd || isLooped) {
|
|
5400
5605
|
if (!isVmdFinishedRef.current) {
|
|
5401
|
-
|
|
5606
|
+
log("VMD finished/looped, marking as finished");
|
|
5402
5607
|
isVmdFinishedRef.current = true;
|
|
5403
5608
|
setIsVmdFinished(true);
|
|
5404
5609
|
}
|
|
@@ -5406,7 +5611,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5406
5611
|
lastAnimationTimeRef.current = time;
|
|
5407
5612
|
},
|
|
5408
5613
|
onEnded: () => {
|
|
5409
|
-
|
|
5614
|
+
log("VMD ended, marking as finished");
|
|
5410
5615
|
isVmdFinishedRef.current = true;
|
|
5411
5616
|
setIsVmdFinished(true);
|
|
5412
5617
|
},
|
|
@@ -5452,17 +5657,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5452
5657
|
/* @__PURE__ */ React10.createElement(
|
|
5453
5658
|
LoadingOverlay,
|
|
5454
5659
|
{
|
|
5455
|
-
isLoading: (
|
|
5456
|
-
const shouldShowLoading = (isLoading || isTransitioning || !isAnimationPlaying) && isStarted;
|
|
5457
|
-
console.log("[MMDVisualNovel] LoadingOverlay conditions:", {
|
|
5458
|
-
isLoading,
|
|
5459
|
-
isTransitioning,
|
|
5460
|
-
isAnimationPlaying,
|
|
5461
|
-
isStarted,
|
|
5462
|
-
shouldShowLoading
|
|
5463
|
-
});
|
|
5464
|
-
return shouldShowLoading;
|
|
5465
|
-
})(),
|
|
5660
|
+
isLoading: (isLoading || isTransitioning || !isAnimationPlaying) && isStarted,
|
|
5466
5661
|
showStartScreen: !isStarted,
|
|
5467
5662
|
scriptName: script.name,
|
|
5468
5663
|
loadingText: "\u6B63\u5728\u51C6\u5907\u573A\u666F\u4E2D...",
|
|
@@ -5474,44 +5669,31 @@ var MMDVisualNovel = forwardRef(
|
|
|
5474
5669
|
customAboutContent
|
|
5475
5670
|
}
|
|
5476
5671
|
),
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
{
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
onSkip: handleSkip,
|
|
5503
|
-
onResetCamera: () => {
|
|
5504
|
-
playerRef.current?.resetCamera();
|
|
5505
|
-
setIsCameraManual(false);
|
|
5506
|
-
},
|
|
5507
|
-
isCameraManual,
|
|
5508
|
-
showControls: true,
|
|
5509
|
-
showSkipButton,
|
|
5510
|
-
showAutoButton,
|
|
5511
|
-
showHistoryButton
|
|
5512
|
-
}
|
|
5513
|
-
) : null;
|
|
5514
|
-
})(),
|
|
5672
|
+
isStarted && isAnimationPlaying && currentDialogue && !showHistory && !showChoices && !showLoopConfirm ? /* @__PURE__ */ React10.createElement(
|
|
5673
|
+
DialogueBox,
|
|
5674
|
+
{
|
|
5675
|
+
dialogue: currentDialogue,
|
|
5676
|
+
theme: dialogueTheme,
|
|
5677
|
+
isTyping,
|
|
5678
|
+
isAutoMode,
|
|
5679
|
+
onClick: handleDialogueClick,
|
|
5680
|
+
onSkipTyping: () => {
|
|
5681
|
+
typingCompleteRef.current = true;
|
|
5682
|
+
},
|
|
5683
|
+
onToggleAuto: toggleAutoMode,
|
|
5684
|
+
onOpenHistory: () => setShowHistory(true),
|
|
5685
|
+
onSkip: handleSkip,
|
|
5686
|
+
onResetCamera: () => {
|
|
5687
|
+
playerRef.current?.resetCamera();
|
|
5688
|
+
setIsCameraManual(false);
|
|
5689
|
+
},
|
|
5690
|
+
isCameraManual,
|
|
5691
|
+
showControls: true,
|
|
5692
|
+
showSkipButton,
|
|
5693
|
+
showAutoButton,
|
|
5694
|
+
showHistoryButton
|
|
5695
|
+
}
|
|
5696
|
+
) : null,
|
|
5515
5697
|
pendingNodeIndex !== null && /* @__PURE__ */ React10.createElement(
|
|
5516
5698
|
SkipConfirmDialog,
|
|
5517
5699
|
{
|
|
@@ -5534,7 +5716,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
5534
5716
|
if (choice.setVariable) {
|
|
5535
5717
|
const { key, value } = choice.setVariable;
|
|
5536
5718
|
setVariables((prev) => ({ ...prev, [key]: value }));
|
|
5537
|
-
|
|
5719
|
+
log("Variable set", { key, value });
|
|
5538
5720
|
}
|
|
5539
5721
|
choice.onSelect?.();
|
|
5540
5722
|
if (choice.effect) {
|
|
@@ -5676,6 +5858,7 @@ var MMDVisualNovelWithSelector = forwardRef((props, ref) => {
|
|
|
5676
5858
|
script,
|
|
5677
5859
|
modelSelector,
|
|
5678
5860
|
onModelSelectionChange,
|
|
5861
|
+
resourceMappingMode = "resource-map",
|
|
5679
5862
|
...restProps
|
|
5680
5863
|
} = props;
|
|
5681
5864
|
const {
|
|
@@ -5702,20 +5885,39 @@ var MMDVisualNovelWithSelector = forwardRef((props, ref) => {
|
|
|
5702
5885
|
return model?.path || stageModels[0]?.path || "";
|
|
5703
5886
|
}, [stageModels, selectedStageId]);
|
|
5704
5887
|
const modifiedScript = useMemo(() => {
|
|
5888
|
+
if (resourceMappingMode === "full-clone") {
|
|
5889
|
+
return {
|
|
5890
|
+
...script,
|
|
5891
|
+
nodes: script.nodes.map((node) => ({
|
|
5892
|
+
...node,
|
|
5893
|
+
resources: {
|
|
5894
|
+
...node.resources,
|
|
5895
|
+
modelPath: selectedCharacterPath,
|
|
5896
|
+
stageModelPath: selectedStagePath
|
|
5897
|
+
}
|
|
5898
|
+
}))
|
|
5899
|
+
};
|
|
5900
|
+
}
|
|
5705
5901
|
return {
|
|
5706
5902
|
...script,
|
|
5707
|
-
nodes: script.nodes.map((node) =>
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5903
|
+
nodes: script.nodes.map((node) => {
|
|
5904
|
+
const nextModelPath = selectedCharacterPath;
|
|
5905
|
+
const nextStagePath = selectedStagePath;
|
|
5906
|
+
const resources = node.resources;
|
|
5907
|
+
if (resources.modelPath === nextModelPath && resources.stageModelPath === nextStagePath) {
|
|
5908
|
+
return node;
|
|
5909
|
+
}
|
|
5910
|
+
return {
|
|
5911
|
+
...node,
|
|
5912
|
+
resources: {
|
|
5913
|
+
...resources,
|
|
5914
|
+
modelPath: nextModelPath,
|
|
5915
|
+
stageModelPath: nextStagePath
|
|
5916
|
+
}
|
|
5917
|
+
};
|
|
5918
|
+
})
|
|
5717
5919
|
};
|
|
5718
|
-
}, [script, selectedCharacterPath, selectedStagePath]);
|
|
5920
|
+
}, [script, selectedCharacterPath, selectedStagePath, resourceMappingMode]);
|
|
5719
5921
|
const handleCharacterChange = useCallback((id) => {
|
|
5720
5922
|
setSelectedCharacterId(id);
|
|
5721
5923
|
onModelSelectionChange?.(id, selectedStageId);
|
|
@@ -6298,594 +6500,733 @@ var MMDMusicPlayer = forwardRef(
|
|
|
6298
6500
|
}
|
|
6299
6501
|
);
|
|
6300
6502
|
MMDMusicPlayer.displayName = "MMDMusicPlayer";
|
|
6301
|
-
|
|
6302
|
-
|
|
6503
|
+
|
|
6504
|
+
// src/mmd/ar/types.ts
|
|
6505
|
+
var ARMode = /* @__PURE__ */ ((ARMode2) => {
|
|
6506
|
+
ARMode2["Overlay"] = "overlay";
|
|
6507
|
+
ARMode2["WorldFixed"] = "world-fixed";
|
|
6508
|
+
return ARMode2;
|
|
6509
|
+
})(ARMode || {});
|
|
6510
|
+
|
|
6511
|
+
// src/mmd/ar/MMDARApp.tsx
|
|
6512
|
+
var DEFAULT_MODEL_SCALE = 0.1;
|
|
6513
|
+
function disposeMesh(object) {
|
|
6514
|
+
object.traverse((child) => {
|
|
6515
|
+
if (child instanceof THREE2.Mesh || child instanceof THREE2.SkinnedMesh) {
|
|
6516
|
+
if (child.geometry) {
|
|
6517
|
+
child.geometry.dispose();
|
|
6518
|
+
}
|
|
6519
|
+
const materials = Array.isArray(child.material) ? child.material : [child.material];
|
|
6520
|
+
materials.forEach((material) => {
|
|
6521
|
+
if (material instanceof THREE2.Material) {
|
|
6522
|
+
Object.values(material).forEach((value) => {
|
|
6523
|
+
if (value instanceof THREE2.Texture) {
|
|
6524
|
+
value.dispose();
|
|
6525
|
+
}
|
|
6526
|
+
});
|
|
6527
|
+
material.dispose();
|
|
6528
|
+
}
|
|
6529
|
+
});
|
|
6530
|
+
}
|
|
6531
|
+
});
|
|
6303
6532
|
}
|
|
6304
|
-
var
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6533
|
+
var MMDARApp = forwardRef((props, ref) => {
|
|
6534
|
+
const {
|
|
6535
|
+
stage,
|
|
6536
|
+
mobileOptimization,
|
|
6537
|
+
cameraConfig,
|
|
6538
|
+
cameraParametersUrl,
|
|
6539
|
+
markerConfig,
|
|
6540
|
+
mirrored = false,
|
|
6541
|
+
showSettings,
|
|
6542
|
+
modelPresets,
|
|
6543
|
+
motionPresets,
|
|
6544
|
+
audioPresets,
|
|
6545
|
+
defaultModelId,
|
|
6546
|
+
defaultMotionId,
|
|
6547
|
+
defaultAudioId,
|
|
6548
|
+
modelScale,
|
|
6549
|
+
modelOffset,
|
|
6550
|
+
initialModelVisible = false,
|
|
6551
|
+
placementText = "Place Model",
|
|
6552
|
+
arMode,
|
|
6553
|
+
defaultARMode,
|
|
6554
|
+
autoPlay = true,
|
|
6555
|
+
loop = true,
|
|
6556
|
+
onCameraReady,
|
|
6557
|
+
onCameraError,
|
|
6558
|
+
onResourcesChange,
|
|
6559
|
+
onModelPlaced,
|
|
6560
|
+
onARModeChange,
|
|
6561
|
+
onLoad,
|
|
6562
|
+
onError,
|
|
6563
|
+
className,
|
|
6564
|
+
style
|
|
6565
|
+
} = props;
|
|
6310
6566
|
const containerRef = useRef(null);
|
|
6567
|
+
const videoContainerRef = useRef(null);
|
|
6311
6568
|
const canvasRef = useRef(null);
|
|
6312
|
-
const sceneRef = useRef();
|
|
6313
|
-
const cameraRef = useRef();
|
|
6314
|
-
const rendererRef = useRef();
|
|
6315
|
-
const arToolkitSourceRef = useRef();
|
|
6316
|
-
const arToolkitContextRef = useRef();
|
|
6317
|
-
const markerRootRef = useRef();
|
|
6318
|
-
const markerControlsRef = useRef();
|
|
6319
|
-
const modelRootRef = useRef();
|
|
6320
|
-
const
|
|
6321
|
-
const
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
const
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
}
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6569
|
+
const sceneRef = useRef(null);
|
|
6570
|
+
const cameraRef = useRef(null);
|
|
6571
|
+
const rendererRef = useRef(null);
|
|
6572
|
+
const arToolkitSourceRef = useRef(null);
|
|
6573
|
+
const arToolkitContextRef = useRef(null);
|
|
6574
|
+
const markerRootRef = useRef(null);
|
|
6575
|
+
const markerControlsRef = useRef(null);
|
|
6576
|
+
const modelRootRef = useRef(null);
|
|
6577
|
+
const mmdHelperRef = useRef(null);
|
|
6578
|
+
const mmdMeshRef = useRef(null);
|
|
6579
|
+
const animationFrameRef = useRef(null);
|
|
6580
|
+
const markerDetectedRef = useRef(false);
|
|
6581
|
+
const audioRef = useRef(null);
|
|
6582
|
+
const autoPlayRef = useRef(autoPlay);
|
|
6583
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
6584
|
+
const [cameraReady, setCameraReady] = useState(false);
|
|
6585
|
+
const [arReady, setArReady] = useState(false);
|
|
6586
|
+
const [error, setError] = useState(null);
|
|
6587
|
+
const [markerDetected, setMarkerDetected] = useState(false);
|
|
6588
|
+
const [modelPlaced, setModelPlaced] = useState(initialModelVisible);
|
|
6589
|
+
const [settingsVisible, setSettingsVisible] = useState(showSettings ?? false);
|
|
6590
|
+
const [internalARMode, setInternalARMode] = useState(
|
|
6591
|
+
defaultARMode ?? arMode ?? "overlay" /* Overlay */
|
|
6592
|
+
);
|
|
6593
|
+
const [cameraFacing, setCameraFacing] = useState(
|
|
6594
|
+
cameraConfig?.facingMode ?? "environment"
|
|
6595
|
+
);
|
|
6596
|
+
const [selectedModelId, setSelectedModelId] = useState(
|
|
6597
|
+
defaultModelId ?? modelPresets[0]?.id ?? ""
|
|
6598
|
+
);
|
|
6599
|
+
const [selectedMotionId, setSelectedMotionId] = useState(
|
|
6600
|
+
defaultMotionId ?? motionPresets[0]?.id ?? ""
|
|
6601
|
+
);
|
|
6602
|
+
const [selectedAudioId, setSelectedAudioId] = useState(
|
|
6603
|
+
defaultAudioId ?? audioPresets?.[0]?.id ?? ""
|
|
6604
|
+
);
|
|
6605
|
+
const [overrideResources, setOverrideResources] = useState(null);
|
|
6606
|
+
const resolvedARMode = arMode ?? internalARMode;
|
|
6607
|
+
const resolvedMarkerConfig = useMemo(() => {
|
|
6608
|
+
return {
|
|
6609
|
+
type: markerConfig?.type ?? "pattern",
|
|
6610
|
+
patternUrl: markerConfig?.patternUrl ?? DEFAULT_AR_ASSETS.patternUrl,
|
|
6611
|
+
barcodeValue: markerConfig?.barcodeValue ?? 0,
|
|
6612
|
+
changeMatrixMode: markerConfig?.changeMatrixMode ?? "modelViewMatrix"
|
|
6613
|
+
};
|
|
6614
|
+
}, [markerConfig]);
|
|
6615
|
+
const resolvedResources = useMemo(() => {
|
|
6616
|
+
if (overrideResources) {
|
|
6617
|
+
return overrideResources;
|
|
6360
6618
|
}
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6619
|
+
const modelPreset = modelPresets.find((preset) => preset.id === selectedModelId);
|
|
6620
|
+
if (!modelPreset) {
|
|
6621
|
+
return null;
|
|
6622
|
+
}
|
|
6623
|
+
const motionPreset = motionPresets.find((preset) => preset.id === selectedMotionId);
|
|
6624
|
+
const audioPreset = audioPresets?.find((preset) => preset.id === selectedAudioId);
|
|
6625
|
+
return {
|
|
6626
|
+
modelPath: modelPreset.modelPath,
|
|
6627
|
+
motionPath: motionPreset?.motionPath,
|
|
6628
|
+
audioPath: audioPreset?.audioPath
|
|
6629
|
+
};
|
|
6630
|
+
}, [
|
|
6631
|
+
overrideResources,
|
|
6632
|
+
modelPresets,
|
|
6633
|
+
motionPresets,
|
|
6634
|
+
audioPresets,
|
|
6635
|
+
selectedModelId,
|
|
6636
|
+
selectedMotionId,
|
|
6637
|
+
selectedAudioId
|
|
6638
|
+
]);
|
|
6639
|
+
const resolveModelScale = useCallback(() => {
|
|
6640
|
+
if (!modelScale) {
|
|
6641
|
+
return new THREE2.Vector3(DEFAULT_MODEL_SCALE, DEFAULT_MODEL_SCALE, DEFAULT_MODEL_SCALE);
|
|
6642
|
+
}
|
|
6643
|
+
if (typeof modelScale === "number") {
|
|
6644
|
+
return new THREE2.Vector3(modelScale, modelScale, modelScale);
|
|
6645
|
+
}
|
|
6646
|
+
return new THREE2.Vector3(modelScale.x, modelScale.y, modelScale.z);
|
|
6647
|
+
}, [modelScale]);
|
|
6648
|
+
const applyModelTransform = useCallback(
|
|
6649
|
+
(mesh) => {
|
|
6650
|
+
const scale = resolveModelScale();
|
|
6651
|
+
mesh.scale.copy(scale);
|
|
6652
|
+
if (modelOffset) {
|
|
6653
|
+
mesh.position.set(modelOffset.x, modelOffset.y, modelOffset.z);
|
|
6654
|
+
return;
|
|
6367
6655
|
}
|
|
6368
|
-
|
|
6369
|
-
if (
|
|
6370
|
-
|
|
6371
|
-
console.log("Querying camera permission status...");
|
|
6372
|
-
const permissionPromise = navigator.permissions.query({ name: "camera" });
|
|
6373
|
-
const timeoutPromise2 = new Promise((_, reject) => {
|
|
6374
|
-
setTimeout(() => reject(new Error("Permission query timeout")), 5e3);
|
|
6375
|
-
});
|
|
6376
|
-
const permissionStatus = await Promise.race([permissionPromise, timeoutPromise2]);
|
|
6377
|
-
console.log("Permission status:", permissionStatus.state);
|
|
6378
|
-
if (permissionStatus.state === "denied") {
|
|
6379
|
-
throw new Error("\u6444\u50CF\u5934\u6743\u9650\u5DF2\u88AB\u62D2\u7EDD\uFF0C\u8BF7\u5728\u6D4F\u89C8\u5668\u8BBE\u7F6E\u4E2D\u5141\u8BB8\u8BBF\u95EE\u6444\u50CF\u5934");
|
|
6380
|
-
}
|
|
6381
|
-
} catch (permissionError) {
|
|
6382
|
-
console.warn("Permission query failed or timed out, proceeding with getUserMedia:", permissionError);
|
|
6383
|
-
}
|
|
6656
|
+
const box = new THREE2.Box3().setFromObject(mesh);
|
|
6657
|
+
if (Number.isFinite(box.min.y)) {
|
|
6658
|
+
mesh.position.y += -box.min.y;
|
|
6384
6659
|
}
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6660
|
+
},
|
|
6661
|
+
[modelOffset, resolveModelScale]
|
|
6662
|
+
);
|
|
6663
|
+
const updateModelPlacement = useCallback(
|
|
6664
|
+
(visible) => {
|
|
6665
|
+
if (!modelRootRef.current) return;
|
|
6666
|
+
modelRootRef.current.visible = visible;
|
|
6667
|
+
setModelPlaced(visible);
|
|
6668
|
+
},
|
|
6669
|
+
[]
|
|
6670
|
+
);
|
|
6671
|
+
const attachModelRoot = useCallback(
|
|
6672
|
+
(mode) => {
|
|
6673
|
+
if (!modelRootRef.current || !sceneRef.current || !cameraRef.current) return;
|
|
6674
|
+
if (mode === "overlay" /* Overlay */) {
|
|
6675
|
+
if (modelRootRef.current.parent !== cameraRef.current) {
|
|
6676
|
+
modelRootRef.current.parent?.remove(modelRootRef.current);
|
|
6677
|
+
cameraRef.current.add(modelRootRef.current);
|
|
6678
|
+
}
|
|
6679
|
+
modelRootRef.current.position.set(0, -1, -3);
|
|
6680
|
+
modelRootRef.current.quaternion.identity();
|
|
6681
|
+
updateModelPlacement(true);
|
|
6682
|
+
} else {
|
|
6683
|
+
if (modelRootRef.current.parent !== sceneRef.current) {
|
|
6684
|
+
modelRootRef.current.parent?.remove(modelRootRef.current);
|
|
6685
|
+
sceneRef.current.add(modelRootRef.current);
|
|
6392
6686
|
}
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
const errorMessage = error instanceof Error ? error.message : "\u65E0\u6CD5\u8BBF\u95EE\u6444\u50CF\u5934";
|
|
6405
|
-
setState((prev) => ({ ...prev, error: errorMessage, isLoading: false }));
|
|
6406
|
-
onError?.(errorMessage);
|
|
6407
|
-
return false;
|
|
6408
|
-
}
|
|
6409
|
-
}, [width, height, onError]);
|
|
6410
|
-
const createModel = useCallback((modelType) => {
|
|
6411
|
-
let geometry;
|
|
6412
|
-
let material;
|
|
6413
|
-
let mesh;
|
|
6414
|
-
switch (modelType) {
|
|
6415
|
-
case "sphere":
|
|
6416
|
-
geometry = new THREE2.SphereGeometry(0.5, 32, 32);
|
|
6417
|
-
material = new THREE2.MeshPhongMaterial({
|
|
6418
|
-
color: 16738740,
|
|
6419
|
-
shininess: 100,
|
|
6420
|
-
specular: 1118481
|
|
6421
|
-
});
|
|
6422
|
-
mesh = new THREE2.Mesh(geometry, material);
|
|
6423
|
-
break;
|
|
6424
|
-
case "cube":
|
|
6425
|
-
geometry = new THREE2.BoxGeometry(0.8, 0.8, 0.8);
|
|
6426
|
-
material = new THREE2.MeshPhongMaterial({
|
|
6427
|
-
color: 65407,
|
|
6428
|
-
shininess: 100,
|
|
6429
|
-
specular: 1118481
|
|
6430
|
-
});
|
|
6431
|
-
mesh = new THREE2.Mesh(geometry, material);
|
|
6432
|
-
break;
|
|
6433
|
-
case "torus":
|
|
6434
|
-
geometry = new THREE2.TorusGeometry(0.4, 0.2, 16, 100);
|
|
6435
|
-
material = new THREE2.MeshPhongMaterial({
|
|
6436
|
-
color: 16753920,
|
|
6437
|
-
shininess: 100,
|
|
6438
|
-
specular: 1118481
|
|
6439
|
-
});
|
|
6440
|
-
mesh = new THREE2.Mesh(geometry, material);
|
|
6441
|
-
break;
|
|
6442
|
-
default:
|
|
6443
|
-
geometry = new THREE2.SphereGeometry(0.5, 32, 32);
|
|
6444
|
-
material = new THREE2.MeshPhongMaterial({
|
|
6445
|
-
color: 16738740,
|
|
6446
|
-
shininess: 100,
|
|
6447
|
-
specular: 1118481
|
|
6448
|
-
});
|
|
6449
|
-
mesh = new THREE2.Mesh(geometry, material);
|
|
6687
|
+
updateModelPlacement(initialModelVisible);
|
|
6688
|
+
}
|
|
6689
|
+
},
|
|
6690
|
+
[initialModelVisible, updateModelPlacement]
|
|
6691
|
+
);
|
|
6692
|
+
const stopCameraStream = useCallback(() => {
|
|
6693
|
+
const source = arToolkitSourceRef.current;
|
|
6694
|
+
if (!source?.domElement) return;
|
|
6695
|
+
const stream = source.domElement.srcObject;
|
|
6696
|
+
if (stream) {
|
|
6697
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
6450
6698
|
}
|
|
6451
|
-
mesh.rotation.x = Math.PI / 4;
|
|
6452
|
-
mesh.rotation.y = Math.PI / 4;
|
|
6453
|
-
return mesh;
|
|
6454
6699
|
}, []);
|
|
6455
|
-
const
|
|
6456
|
-
|
|
6457
|
-
|
|
6700
|
+
const cleanupAR = useCallback(() => {
|
|
6701
|
+
stopCameraStream();
|
|
6702
|
+
if (markerRootRef.current && sceneRef.current) {
|
|
6703
|
+
sceneRef.current.remove(markerRootRef.current);
|
|
6704
|
+
markerRootRef.current.clear();
|
|
6705
|
+
}
|
|
6706
|
+
markerRootRef.current = null;
|
|
6707
|
+
markerControlsRef.current = null;
|
|
6708
|
+
const videoContainer = videoContainerRef.current;
|
|
6709
|
+
const videoElement = arToolkitSourceRef.current?.domElement;
|
|
6710
|
+
if (videoContainer && videoElement && videoElement.parentElement === videoContainer) {
|
|
6711
|
+
videoContainer.removeChild(videoElement);
|
|
6712
|
+
}
|
|
6713
|
+
arToolkitSourceRef.current?.dispose?.();
|
|
6714
|
+
arToolkitSourceRef.current = null;
|
|
6715
|
+
arToolkitContextRef.current = null;
|
|
6716
|
+
markerDetectedRef.current = false;
|
|
6717
|
+
setMarkerDetected(false);
|
|
6718
|
+
setCameraReady(false);
|
|
6719
|
+
setArReady(false);
|
|
6720
|
+
}, [stopCameraStream]);
|
|
6721
|
+
const setupRenderer = useCallback(() => {
|
|
6722
|
+
if (rendererRef.current) return;
|
|
6723
|
+
if (!canvasRef.current) return;
|
|
6724
|
+
const renderer = new THREE2.WebGLRenderer({
|
|
6725
|
+
canvas: canvasRef.current,
|
|
6726
|
+
antialias: true,
|
|
6727
|
+
alpha: true
|
|
6728
|
+
});
|
|
6729
|
+
renderer.setClearColor(0, 0);
|
|
6730
|
+
renderer.setPixelRatio(mobileOptimization?.pixelRatio ?? window.devicePixelRatio ?? 1);
|
|
6731
|
+
rendererRef.current = renderer;
|
|
6732
|
+
const scene = new THREE2.Scene();
|
|
6733
|
+
sceneRef.current = scene;
|
|
6734
|
+
const camera = new THREE2.Camera();
|
|
6735
|
+
cameraRef.current = camera;
|
|
6736
|
+
scene.add(camera);
|
|
6737
|
+
const modelRoot = new THREE2.Group();
|
|
6738
|
+
modelRoot.visible = initialModelVisible;
|
|
6739
|
+
modelRootRef.current = modelRoot;
|
|
6740
|
+
scene.add(modelRoot);
|
|
6741
|
+
const ambientLight = new THREE2.AmbientLight(
|
|
6742
|
+
16777215,
|
|
6743
|
+
stage?.ambientLightIntensity ?? 0.8
|
|
6744
|
+
);
|
|
6745
|
+
scene.add(ambientLight);
|
|
6746
|
+
const directionalLight = new THREE2.DirectionalLight(
|
|
6747
|
+
16777215,
|
|
6748
|
+
stage?.directionalLightIntensity ?? 0.6
|
|
6749
|
+
);
|
|
6750
|
+
directionalLight.position.set(1, 1, 1);
|
|
6751
|
+
scene.add(directionalLight);
|
|
6752
|
+
attachModelRoot(resolvedARMode);
|
|
6753
|
+
}, [
|
|
6754
|
+
attachModelRoot,
|
|
6755
|
+
initialModelVisible,
|
|
6756
|
+
mobileOptimization?.pixelRatio,
|
|
6757
|
+
resolvedARMode,
|
|
6758
|
+
stage?.ambientLightIntensity,
|
|
6759
|
+
stage?.directionalLightIntensity
|
|
6760
|
+
]);
|
|
6761
|
+
const resize = useCallback(() => {
|
|
6762
|
+
if (!containerRef.current || !rendererRef.current) return;
|
|
6763
|
+
const width = containerRef.current.clientWidth;
|
|
6764
|
+
const height = containerRef.current.clientHeight;
|
|
6765
|
+
if (width === 0 || height === 0) return;
|
|
6766
|
+
rendererRef.current.setSize(width, height);
|
|
6767
|
+
const source = arToolkitSourceRef.current;
|
|
6768
|
+
if (source?.onResizeElement && source?.copyElementSizeTo) {
|
|
6769
|
+
source.onResizeElement();
|
|
6770
|
+
source.copyElementSizeTo(rendererRef.current.domElement);
|
|
6771
|
+
if (arToolkitContextRef.current?.arController?.canvas) {
|
|
6772
|
+
source.copyElementSizeTo(arToolkitContextRef.current.arController.canvas);
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
}, []);
|
|
6776
|
+
const startRenderLoop = useCallback(() => {
|
|
6777
|
+
if (animationFrameRef.current) return;
|
|
6778
|
+
if (!rendererRef.current || !sceneRef.current || !cameraRef.current) return;
|
|
6779
|
+
const renderer = rendererRef.current;
|
|
6780
|
+
const scene = sceneRef.current;
|
|
6781
|
+
const camera = cameraRef.current;
|
|
6782
|
+
const clock = new THREE2.Clock();
|
|
6783
|
+
const render = () => {
|
|
6784
|
+
animationFrameRef.current = requestAnimationFrame(render);
|
|
6785
|
+
if (arToolkitSourceRef.current?.ready) {
|
|
6786
|
+
arToolkitContextRef.current?.update(arToolkitSourceRef.current.domElement);
|
|
6787
|
+
if (markerRootRef.current) {
|
|
6788
|
+
const isVisible = markerRootRef.current.visible;
|
|
6789
|
+
if (isVisible !== markerDetectedRef.current) {
|
|
6790
|
+
markerDetectedRef.current = isVisible;
|
|
6791
|
+
setMarkerDetected(isVisible);
|
|
6792
|
+
}
|
|
6793
|
+
}
|
|
6794
|
+
}
|
|
6795
|
+
if (mmdHelperRef.current && autoPlayRef.current) {
|
|
6796
|
+
const delta = clock.getDelta();
|
|
6797
|
+
mmdHelperRef.current.update(delta);
|
|
6798
|
+
}
|
|
6799
|
+
renderer.render(scene, camera);
|
|
6800
|
+
};
|
|
6801
|
+
render();
|
|
6802
|
+
}, []);
|
|
6803
|
+
const setupAR = useCallback(async (facingOverride) => {
|
|
6804
|
+
if (!sceneRef.current || !cameraRef.current) return;
|
|
6805
|
+
const THREEx = await loadARJS({ three: THREE2 });
|
|
6806
|
+
const facingMode = facingOverride ?? cameraFacing;
|
|
6807
|
+
const sourceWidth = typeof cameraConfig?.width === "number" ? cameraConfig.width : cameraConfig?.width?.ideal;
|
|
6808
|
+
const sourceHeight = typeof cameraConfig?.height === "number" ? cameraConfig.height : cameraConfig?.height?.ideal;
|
|
6809
|
+
const arToolkitSource = new THREEx.ArToolkitSource({
|
|
6810
|
+
sourceType: "webcam",
|
|
6811
|
+
sourceWidth: sourceWidth ?? 1280,
|
|
6812
|
+
sourceHeight: sourceHeight ?? 720,
|
|
6813
|
+
facingMode
|
|
6814
|
+
});
|
|
6815
|
+
arToolkitSourceRef.current = arToolkitSource;
|
|
6816
|
+
const arToolkitContext = new THREEx.ArToolkitContext({
|
|
6817
|
+
cameraParametersUrl: cameraParametersUrl ?? DEFAULT_AR_ASSETS.cameraParametersUrl,
|
|
6818
|
+
detectionMode: "mono",
|
|
6819
|
+
maxDetectionRate: 30
|
|
6820
|
+
});
|
|
6821
|
+
arToolkitContextRef.current = arToolkitContext;
|
|
6822
|
+
const markerRoot = new THREE2.Group();
|
|
6823
|
+
markerRootRef.current = markerRoot;
|
|
6824
|
+
sceneRef.current.add(markerRoot);
|
|
6825
|
+
markerControlsRef.current = new THREEx.ArMarkerControls(
|
|
6826
|
+
arToolkitContext,
|
|
6827
|
+
markerRoot,
|
|
6828
|
+
resolvedMarkerConfig
|
|
6829
|
+
);
|
|
6830
|
+
arToolkitContext.init(() => {
|
|
6831
|
+
if (!cameraRef.current) return;
|
|
6832
|
+
cameraRef.current.projectionMatrix.copy(arToolkitContext.getProjectionMatrix());
|
|
6833
|
+
setArReady(true);
|
|
6834
|
+
});
|
|
6835
|
+
arToolkitSource.init(() => {
|
|
6836
|
+
const videoElement = arToolkitSource.domElement;
|
|
6837
|
+
if (videoContainerRef.current && videoElement.parentElement !== videoContainerRef.current) {
|
|
6838
|
+
videoContainerRef.current.appendChild(videoElement);
|
|
6839
|
+
}
|
|
6840
|
+
videoElement.setAttribute("playsinline", "true");
|
|
6841
|
+
videoElement.style.position = "absolute";
|
|
6842
|
+
videoElement.style.inset = "0";
|
|
6843
|
+
videoElement.style.width = "100%";
|
|
6844
|
+
videoElement.style.height = "100%";
|
|
6845
|
+
videoElement.style.objectFit = "cover";
|
|
6846
|
+
videoElement.style.zIndex = "0";
|
|
6847
|
+
if (mirrored) {
|
|
6848
|
+
videoElement.style.transform = "scaleX(-1)";
|
|
6849
|
+
}
|
|
6850
|
+
setCameraReady(true);
|
|
6851
|
+
const stream = videoElement.srcObject;
|
|
6852
|
+
if (stream) {
|
|
6853
|
+
onCameraReady?.(stream);
|
|
6854
|
+
}
|
|
6855
|
+
resize();
|
|
6856
|
+
});
|
|
6857
|
+
}, [
|
|
6858
|
+
cameraConfig?.height,
|
|
6859
|
+
cameraConfig?.width,
|
|
6860
|
+
cameraFacing,
|
|
6861
|
+
cameraParametersUrl,
|
|
6862
|
+
mirrored,
|
|
6863
|
+
onCameraReady,
|
|
6864
|
+
resize,
|
|
6865
|
+
resolvedMarkerConfig
|
|
6866
|
+
]);
|
|
6867
|
+
const loadMMDResources = useCallback(async () => {
|
|
6868
|
+
if (!resolvedResources || !sceneRef.current || !modelRootRef.current) {
|
|
6458
6869
|
return;
|
|
6459
6870
|
}
|
|
6871
|
+
setIsLoading(true);
|
|
6872
|
+
setError(null);
|
|
6873
|
+
if (mmdMeshRef.current) {
|
|
6874
|
+
if (mmdHelperRef.current) {
|
|
6875
|
+
mmdHelperRef.current.remove(mmdMeshRef.current);
|
|
6876
|
+
}
|
|
6877
|
+
modelRootRef.current.remove(mmdMeshRef.current);
|
|
6878
|
+
disposeMesh(mmdMeshRef.current);
|
|
6879
|
+
mmdMeshRef.current = null;
|
|
6880
|
+
}
|
|
6881
|
+
if (!mmdHelperRef.current) {
|
|
6882
|
+
mmdHelperRef.current = new MMDAnimationHelper({ afterglow: 2 });
|
|
6883
|
+
}
|
|
6884
|
+
const loader = new MMDLoader();
|
|
6885
|
+
const loadModel = () => new Promise((resolve, reject) => {
|
|
6886
|
+
if (resolvedResources.motionPath) {
|
|
6887
|
+
loader.loadWithAnimation(
|
|
6888
|
+
resolvedResources.modelPath,
|
|
6889
|
+
resolvedResources.motionPath,
|
|
6890
|
+
(mmd) => resolve({ mesh: mmd.mesh, animation: mmd.animation }),
|
|
6891
|
+
void 0,
|
|
6892
|
+
(err) => reject(err)
|
|
6893
|
+
);
|
|
6894
|
+
} else {
|
|
6895
|
+
loader.load(
|
|
6896
|
+
resolvedResources.modelPath,
|
|
6897
|
+
(mesh) => resolve({ mesh }),
|
|
6898
|
+
void 0,
|
|
6899
|
+
(err) => reject(err)
|
|
6900
|
+
);
|
|
6901
|
+
}
|
|
6902
|
+
});
|
|
6460
6903
|
try {
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6904
|
+
const { mesh, animation } = await loadModel();
|
|
6905
|
+
configureMaterialsForMMD(mesh, {
|
|
6906
|
+
enableGradientMap: true,
|
|
6907
|
+
shininess: 30,
|
|
6908
|
+
specularColor: 8947848
|
|
6909
|
+
});
|
|
6910
|
+
applyModelTransform(mesh);
|
|
6911
|
+
mesh.castShadow = true;
|
|
6912
|
+
mesh.receiveShadow = stage?.modelReceiveShadow ?? true;
|
|
6913
|
+
mmdMeshRef.current = mesh;
|
|
6914
|
+
modelRootRef.current.add(mesh);
|
|
6915
|
+
if (animation) {
|
|
6916
|
+
mmdHelperRef.current.add(mesh, {
|
|
6917
|
+
animation,
|
|
6918
|
+
physics: false
|
|
6919
|
+
});
|
|
6920
|
+
}
|
|
6921
|
+
setIsLoading(false);
|
|
6922
|
+
onResourcesChange?.(resolvedResources);
|
|
6923
|
+
onLoad?.();
|
|
6924
|
+
} catch (err) {
|
|
6925
|
+
const message = err instanceof Error ? err.message : "Failed to load MMD resources";
|
|
6926
|
+
setError(message);
|
|
6927
|
+
setIsLoading(false);
|
|
6928
|
+
onError?.(err instanceof Error ? err : new Error(message));
|
|
6929
|
+
}
|
|
6930
|
+
}, [applyModelTransform, onError, onLoad, onResourcesChange, resolvedResources, stage?.modelReceiveShadow]);
|
|
6931
|
+
const updateAudio = useCallback(() => {
|
|
6932
|
+
if (!resolvedResources?.audioPath) {
|
|
6933
|
+
if (audioRef.current) {
|
|
6934
|
+
audioRef.current.pause();
|
|
6935
|
+
audioRef.current.src = "";
|
|
6936
|
+
audioRef.current = null;
|
|
6937
|
+
}
|
|
6938
|
+
return;
|
|
6475
6939
|
}
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
if (setting === "cameraFacing" || setting === "markerType" || setting === "quality") {
|
|
6480
|
-
setTimeout(() => {
|
|
6481
|
-
alert("\u6B64\u8BBE\u7F6E\u53D8\u66F4\u9700\u8981\u91CD\u65B0\u542F\u52A8 AR \u7CFB\u7EDF\u3002\u8BF7\u5237\u65B0\u9875\u9762\u4EE5\u5E94\u7528\u65B0\u8BBE\u7F6E\u3002");
|
|
6482
|
-
}, 100);
|
|
6940
|
+
if (audioRef.current) {
|
|
6941
|
+
audioRef.current.pause();
|
|
6942
|
+
audioRef.current.src = "";
|
|
6483
6943
|
}
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6944
|
+
const audio = new Audio(resolvedResources.audioPath);
|
|
6945
|
+
audio.loop = loop;
|
|
6946
|
+
audioRef.current = audio;
|
|
6947
|
+
if (autoPlay || modelPlaced) {
|
|
6948
|
+
audio.play().catch(() => void 0);
|
|
6949
|
+
}
|
|
6950
|
+
}, [autoPlay, loop, modelPlaced, resolvedResources?.audioPath]);
|
|
6951
|
+
const placeModel = useCallback(() => {
|
|
6952
|
+
if (!modelRootRef.current) return;
|
|
6953
|
+
if (resolvedARMode === "overlay" /* Overlay */) {
|
|
6954
|
+
updateModelPlacement(true);
|
|
6955
|
+
onModelPlaced?.();
|
|
6488
6956
|
return;
|
|
6489
6957
|
}
|
|
6490
|
-
|
|
6958
|
+
if (!markerRootRef.current) return;
|
|
6959
|
+
modelRootRef.current.position.copy(markerRootRef.current.position);
|
|
6960
|
+
modelRootRef.current.quaternion.copy(markerRootRef.current.quaternion);
|
|
6961
|
+
updateModelPlacement(true);
|
|
6962
|
+
onModelPlaced?.();
|
|
6963
|
+
}, [onModelPlaced, resolvedARMode, updateModelPlacement]);
|
|
6964
|
+
const removeModel = useCallback(() => {
|
|
6965
|
+
updateModelPlacement(false);
|
|
6966
|
+
}, [updateModelPlacement]);
|
|
6967
|
+
useImperativeHandle(ref, () => ({
|
|
6968
|
+
startCamera: async () => {
|
|
6969
|
+
cleanupAR();
|
|
6970
|
+
await setupAR();
|
|
6971
|
+
},
|
|
6972
|
+
stopCamera: () => {
|
|
6973
|
+
cleanupAR();
|
|
6974
|
+
},
|
|
6975
|
+
switchCamera: async () => {
|
|
6976
|
+
const next = cameraFacing === "environment" ? "user" : "environment";
|
|
6977
|
+
setCameraFacing(next);
|
|
6978
|
+
cleanupAR();
|
|
6979
|
+
await setupAR(next);
|
|
6980
|
+
},
|
|
6981
|
+
snapshot: async () => {
|
|
6982
|
+
if (!rendererRef.current) return "";
|
|
6491
6983
|
const canvas = document.createElement("canvas");
|
|
6492
6984
|
const context = canvas.getContext("2d");
|
|
6493
|
-
if (!context)
|
|
6494
|
-
|
|
6495
|
-
|
|
6985
|
+
if (!context) return "";
|
|
6986
|
+
const width = rendererRef.current.domElement.width;
|
|
6987
|
+
const height = rendererRef.current.domElement.height;
|
|
6496
6988
|
canvas.width = width;
|
|
6497
6989
|
canvas.height = height;
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
context.drawImage(rendererCanvas, 0, 0, width, height);
|
|
6501
|
-
if (arToolkitSourceRef.current && arToolkitSourceRef.current.domElement) {
|
|
6502
|
-
const videoElement = arToolkitSourceRef.current.domElement;
|
|
6503
|
-
context.globalCompositeOperation = "source-over";
|
|
6990
|
+
const videoElement = arToolkitSourceRef.current?.domElement;
|
|
6991
|
+
if (videoElement) {
|
|
6504
6992
|
context.drawImage(videoElement, 0, 0, width, height);
|
|
6505
6993
|
}
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
}
|
|
6518
|
-
}, "image/png");
|
|
6519
|
-
} catch (error) {
|
|
6520
|
-
console.error("Failed to take photo:", error);
|
|
6521
|
-
setState((prev) => ({ ...prev, error: "\u62CD\u7167\u5931\u8D25" }));
|
|
6522
|
-
}
|
|
6523
|
-
}, [width, height]);
|
|
6524
|
-
const initializeAR = useCallback(async () => {
|
|
6525
|
-
try {
|
|
6526
|
-
console.log("Starting AR initialization...");
|
|
6527
|
-
if (!window.__arjs_ready) {
|
|
6528
|
-
console.log("Waiting for AR.js initialization...");
|
|
6529
|
-
await new Promise((resolve, reject) => {
|
|
6530
|
-
const check = setInterval(() => {
|
|
6531
|
-
if (window.__arjs_ready) {
|
|
6532
|
-
clearInterval(check);
|
|
6533
|
-
console.log("AR.js initialization complete!");
|
|
6534
|
-
resolve();
|
|
6535
|
-
}
|
|
6536
|
-
}, 50);
|
|
6537
|
-
setTimeout(() => {
|
|
6538
|
-
clearInterval(check);
|
|
6539
|
-
reject(new Error("AR.js initialization timeout"));
|
|
6540
|
-
}, 15e3);
|
|
6541
|
-
});
|
|
6994
|
+
context.drawImage(rendererRef.current.domElement, 0, 0, width, height);
|
|
6995
|
+
return canvas.toDataURL("image/png");
|
|
6996
|
+
},
|
|
6997
|
+
placeModel,
|
|
6998
|
+
removeModel,
|
|
6999
|
+
switchModel: (resources) => {
|
|
7000
|
+
setOverrideResources(resources);
|
|
7001
|
+
},
|
|
7002
|
+
setARMode: (mode) => {
|
|
7003
|
+
if (!arMode) {
|
|
7004
|
+
setInternalARMode(mode);
|
|
6542
7005
|
}
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
...state.cameraFacing && { facingMode: state.cameraFacing }
|
|
6563
|
-
});
|
|
6564
|
-
arToolkitSourceRef.current = arToolkitSource;
|
|
6565
|
-
const arToolkitContext = new THREEx.ArToolkitContext({
|
|
6566
|
-
cameraParametersUrl: "data/camera_para.dat",
|
|
6567
|
-
// 使用内建相机参数
|
|
6568
|
-
detectionMode: "mono",
|
|
6569
|
-
// 根据质量设置调整检测参数
|
|
6570
|
-
...state.quality && {
|
|
6571
|
-
maxDetectionRate: state.quality === "high" ? 60 : state.quality === "medium" ? 30 : 15
|
|
6572
|
-
}
|
|
6573
|
-
});
|
|
6574
|
-
arToolkitContextRef.current = arToolkitContext;
|
|
6575
|
-
arToolkitContext.init(() => {
|
|
6576
|
-
cameraRef.current.projectionMatrix.copy(arToolkitContext.getProjectionMatrix());
|
|
6577
|
-
const markerRoot = new THREE2.Group();
|
|
6578
|
-
sceneRef.current.add(markerRoot);
|
|
6579
|
-
markerRootRef.current = markerRoot;
|
|
6580
|
-
const markerGeometry = new THREE2.BoxGeometry(1, 1, 0.1);
|
|
6581
|
-
const markerMaterial = new THREE2.MeshBasicMaterial({
|
|
6582
|
-
color: 65280,
|
|
6583
|
-
transparent: true,
|
|
6584
|
-
opacity: 0.7,
|
|
6585
|
-
wireframe: state.showWireframe
|
|
6586
|
-
// 根据设置显示线框
|
|
6587
|
-
});
|
|
6588
|
-
const markerMesh = new THREE2.Mesh(markerGeometry, markerMaterial);
|
|
6589
|
-
markerMesh.position.set(0, 0, 0);
|
|
6590
|
-
markerRoot.add(markerMesh);
|
|
6591
|
-
if (!state.showWireframe) {
|
|
6592
|
-
const edges = new THREE2.EdgesGeometry(markerGeometry);
|
|
6593
|
-
const lineMaterial = new THREE2.LineBasicMaterial({ color: 16777215 });
|
|
6594
|
-
const wireframe = new THREE2.LineSegments(edges, lineMaterial);
|
|
6595
|
-
markerRoot.add(wireframe);
|
|
6596
|
-
}
|
|
6597
|
-
const markerControls = new THREEx.ArMarkerControls(arToolkitContext, markerRoot, {
|
|
6598
|
-
type: state.markerType,
|
|
6599
|
-
...state.markerType === "barcode" ? { barcodeValue: 0 } : { patternUrl: "data/patt.hiro" }
|
|
6600
|
-
});
|
|
6601
|
-
markerControlsRef.current = markerControls;
|
|
6602
|
-
if (state.lightingEnabled) {
|
|
6603
|
-
const ambientLight = new THREE2.AmbientLight(4210752, 0.6);
|
|
6604
|
-
sceneRef.current.add(ambientLight);
|
|
6605
|
-
const directionalLight = new THREE2.DirectionalLight(16777215, 0.8);
|
|
6606
|
-
directionalLight.position.set(1, 1, 1);
|
|
6607
|
-
sceneRef.current.add(directionalLight);
|
|
6608
|
-
}
|
|
6609
|
-
const modelRoot = new THREE2.Group();
|
|
6610
|
-
modelRoot.visible = false;
|
|
6611
|
-
sceneRef.current.add(modelRoot);
|
|
6612
|
-
modelRootRef.current = modelRoot;
|
|
6613
|
-
setState((prev) => ({
|
|
6614
|
-
...prev,
|
|
6615
|
-
arReady: true,
|
|
6616
|
-
isLoading: false
|
|
6617
|
-
}));
|
|
6618
|
-
onReady?.();
|
|
6619
|
-
console.log("AR.js and marker system initialized successfully");
|
|
6620
|
-
});
|
|
6621
|
-
arToolkitSource.init(() => {
|
|
6622
|
-
arToolkitSource.domElement.style.display = "none";
|
|
6623
|
-
setState((prev) => ({ ...prev, cameraReady: true }));
|
|
6624
|
-
console.log("Camera initialized successfully");
|
|
6625
|
-
});
|
|
6626
|
-
return true;
|
|
6627
|
-
} catch (error) {
|
|
6628
|
-
console.error("Failed to initialize AR.js:", error);
|
|
6629
|
-
const errorMessage = error instanceof Error ? error.message : "AR.js \u521D\u59CB\u5316\u5931\u8D25";
|
|
6630
|
-
setState((prev) => ({
|
|
6631
|
-
...prev,
|
|
6632
|
-
error: errorMessage,
|
|
6633
|
-
isLoading: false
|
|
6634
|
-
}));
|
|
6635
|
-
onError?.(errorMessage);
|
|
6636
|
-
return false;
|
|
6637
|
-
}
|
|
6638
|
-
}, [width, height, requestCameraPermission, onReady, onError]);
|
|
6639
|
-
const render = useCallback(() => {
|
|
6640
|
-
if (!rendererRef.current || !sceneRef.current || !cameraRef.current) return;
|
|
6641
|
-
requestAnimationFrame(render);
|
|
6642
|
-
if (arToolkitSourceRef.current && arToolkitSourceRef.current.ready) {
|
|
6643
|
-
arToolkitContextRef.current.update(arToolkitSourceRef.current.domElement);
|
|
6644
|
-
if (markerRootRef.current && markerRootRef.current.visible !== state.markerDetected) {
|
|
6645
|
-
setState((prev) => ({ ...prev, markerDetected: markerRootRef.current.visible }));
|
|
7006
|
+
attachModelRoot(mode);
|
|
7007
|
+
onARModeChange?.(mode);
|
|
7008
|
+
},
|
|
7009
|
+
getARMode: () => resolvedARMode
|
|
7010
|
+
}));
|
|
7011
|
+
useEffect(() => {
|
|
7012
|
+
autoPlayRef.current = autoPlay || modelPlaced;
|
|
7013
|
+
}, [autoPlay, modelPlaced]);
|
|
7014
|
+
useEffect(() => {
|
|
7015
|
+
if (showSettings !== void 0) {
|
|
7016
|
+
setSettingsVisible(showSettings);
|
|
7017
|
+
}
|
|
7018
|
+
}, [showSettings]);
|
|
7019
|
+
useEffect(() => {
|
|
7020
|
+
if (cameraConfig?.facingMode) {
|
|
7021
|
+
if (cameraConfig.facingMode !== cameraFacing) {
|
|
7022
|
+
setCameraFacing(cameraConfig.facingMode);
|
|
7023
|
+
cleanupAR();
|
|
7024
|
+
setupAR(cameraConfig.facingMode).catch(() => void 0);
|
|
6646
7025
|
}
|
|
6647
7026
|
}
|
|
6648
|
-
|
|
6649
|
-
|
|
7027
|
+
}, [cameraConfig?.facingMode, cameraFacing, cleanupAR, setupAR]);
|
|
7028
|
+
useEffect(() => {
|
|
7029
|
+
if (!modelPresets.find((preset) => preset.id === selectedModelId)) {
|
|
7030
|
+
setSelectedModelId(modelPresets[0]?.id ?? "");
|
|
6650
7031
|
}
|
|
6651
|
-
|
|
6652
|
-
}, [state.markerDetected]);
|
|
7032
|
+
}, [modelPresets, selectedModelId]);
|
|
6653
7033
|
useEffect(() => {
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
}
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
}
|
|
6685
|
-
};
|
|
6686
|
-
initialize();
|
|
7034
|
+
if (!motionPresets.find((preset) => preset.id === selectedMotionId)) {
|
|
7035
|
+
setSelectedMotionId(motionPresets[0]?.id ?? "");
|
|
7036
|
+
}
|
|
7037
|
+
}, [motionPresets, selectedMotionId]);
|
|
7038
|
+
useEffect(() => {
|
|
7039
|
+
if (audioPresets && !audioPresets.find((preset) => preset.id === selectedAudioId)) {
|
|
7040
|
+
setSelectedAudioId(audioPresets[0]?.id ?? "");
|
|
7041
|
+
}
|
|
7042
|
+
}, [audioPresets, selectedAudioId]);
|
|
7043
|
+
useEffect(() => {
|
|
7044
|
+
if (typeof window === "undefined") return;
|
|
7045
|
+
if (!rendererRef.current) {
|
|
7046
|
+
setupRenderer();
|
|
7047
|
+
}
|
|
7048
|
+
if (!arToolkitSourceRef.current) {
|
|
7049
|
+
setupAR().then(() => {
|
|
7050
|
+
startRenderLoop();
|
|
7051
|
+
}).catch((err) => {
|
|
7052
|
+
const message = err instanceof Error ? err.message : "Failed to initialize AR";
|
|
7053
|
+
setError(message);
|
|
7054
|
+
setIsLoading(false);
|
|
7055
|
+
onCameraError?.(err instanceof Error ? err : new Error(message));
|
|
7056
|
+
});
|
|
7057
|
+
} else {
|
|
7058
|
+
startRenderLoop();
|
|
7059
|
+
}
|
|
7060
|
+
const resizeObserver = new ResizeObserver(resize);
|
|
7061
|
+
if (containerRef.current) {
|
|
7062
|
+
resizeObserver.observe(containerRef.current);
|
|
7063
|
+
}
|
|
6687
7064
|
return () => {
|
|
7065
|
+
resizeObserver.disconnect();
|
|
7066
|
+
cleanupAR();
|
|
7067
|
+
if (animationFrameRef.current) {
|
|
7068
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
7069
|
+
animationFrameRef.current = null;
|
|
7070
|
+
}
|
|
6688
7071
|
if (rendererRef.current) {
|
|
6689
7072
|
rendererRef.current.dispose();
|
|
7073
|
+
rendererRef.current = null;
|
|
6690
7074
|
}
|
|
6691
|
-
if (
|
|
6692
|
-
|
|
6693
|
-
const stream = arToolkitSourceRef.current.domElement.srcObject;
|
|
6694
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
6695
|
-
}
|
|
6696
|
-
arToolkitSourceRef.current.domElement?.remove();
|
|
7075
|
+
if (sceneRef.current && modelRootRef.current) {
|
|
7076
|
+
sceneRef.current.remove(modelRootRef.current);
|
|
6697
7077
|
}
|
|
6698
|
-
if (
|
|
6699
|
-
|
|
7078
|
+
if (mmdMeshRef.current) {
|
|
7079
|
+
if (mmdHelperRef.current) {
|
|
7080
|
+
mmdHelperRef.current.remove(mmdMeshRef.current);
|
|
7081
|
+
}
|
|
7082
|
+
disposeMesh(mmdMeshRef.current);
|
|
7083
|
+
mmdMeshRef.current = null;
|
|
6700
7084
|
}
|
|
7085
|
+
mmdHelperRef.current = null;
|
|
7086
|
+
audioRef.current?.pause();
|
|
7087
|
+
audioRef.current = null;
|
|
6701
7088
|
};
|
|
6702
|
-
}, [
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
checkTHREEx();
|
|
6721
|
-
},
|
|
6722
|
-
onError: (error) => {
|
|
6723
|
-
console.error("Failed to load AR.js:", error);
|
|
6724
|
-
setState((prev) => ({
|
|
6725
|
-
...prev,
|
|
6726
|
-
error: "AR.js \u52A0\u8F7D\u5931\u8D25",
|
|
6727
|
-
isLoading: false
|
|
6728
|
-
}));
|
|
6729
|
-
}
|
|
6730
|
-
}
|
|
6731
|
-
), /* @__PURE__ */ React10.createElement(
|
|
6732
|
-
"canvas",
|
|
6733
|
-
{
|
|
6734
|
-
ref: canvasRef,
|
|
6735
|
-
className: "absolute inset-0 w-full h-full",
|
|
6736
|
-
style: { display: state.arReady ? "block" : "none" }
|
|
6737
|
-
}
|
|
6738
|
-
), state.isLoading && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 flex items-center justify-center bg-gray-900 text-white" }, /* @__PURE__ */ React10.createElement("div", { className: "text-center" }, /* @__PURE__ */ React10.createElement("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-white mx-auto mb-4" }), /* @__PURE__ */ React10.createElement("p", null, "\u6B63\u5728\u521D\u59CB\u5316 AR \u73AF\u5883..."))), state.error && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 flex items-center justify-center bg-red-900 text-white" }, /* @__PURE__ */ React10.createElement("div", { className: "text-center max-w-md" }, /* @__PURE__ */ React10.createElement("h2", { className: "text-xl font-bold mb-4" }, "\u521D\u59CB\u5316\u5931\u8D25"), /* @__PURE__ */ React10.createElement("p", { className: "text-red-200 mb-4" }, state.error), /* @__PURE__ */ React10.createElement(
|
|
6739
|
-
"button",
|
|
6740
|
-
{
|
|
6741
|
-
onClick: () => window.location.reload(),
|
|
6742
|
-
className: "px-4 py-2 bg-red-600 hover:bg-red-700 rounded-lg transition-colors"
|
|
6743
|
-
},
|
|
6744
|
-
"\u91CD\u65B0\u52A0\u8F7D"
|
|
6745
|
-
))), state.arReady && !state.error && /* @__PURE__ */ React10.createElement(React10.Fragment, null, !state.modelPlaced && /* @__PURE__ */ React10.createElement("div", { className: "absolute top-4 left-4 right-4 bg-black/70 text-white p-4 rounded-lg" }, /* @__PURE__ */ React10.createElement("h3", { className: "font-bold mb-2" }, "AR \u653E\u7F6E\u8BF4\u660E"), /* @__PURE__ */ React10.createElement("p", { className: "text-sm text-gray-300" }, "1. \u5141\u8BB8\u6444\u50CF\u5934\u8BBF\u95EE\u6743\u9650", /* @__PURE__ */ React10.createElement("br", null), "2. \u51C6\u5907\u4E00\u4E2A\u6761\u7801\u6807\u8BB0 (\u503C: 0) \u6216 Hiro \u6807\u8BB0\u56FE\u6848", /* @__PURE__ */ React10.createElement("br", null), "3. \u5C06\u6444\u50CF\u5934\u5BF9\u51C6\u6807\u8BB0\uFF0C\u7EFF\u8272\u7ACB\u65B9\u4F53\u5C06\u51FA\u73B0\u5728\u6807\u8BB0\u4F4D\u7F6E", /* @__PURE__ */ React10.createElement("br", null), state.markerDetected ? /* @__PURE__ */ React10.createElement("span", { className: "text-green-400 font-bold" }, "\u2713 \u6807\u8BB0\u5DF2\u68C0\u6D4B\u5230\uFF01") : /* @__PURE__ */ React10.createElement("span", { className: "text-yellow-400" }, "\u7B49\u5F85\u6807\u8BB0\u68C0\u6D4B..."), /* @__PURE__ */ React10.createElement("br", null), '4. \u70B9\u51FB"\u653E\u7F6E\u6A21\u578B"\u6309\u94AE\u56FA\u5B9A\u6A21\u578B\u4F4D\u7F6E')), state.showSettings && /* @__PURE__ */ React10.createElement("div", { className: "absolute top-4 right-4 bg-black/90 text-white p-4 rounded-lg min-w-80 max-w-sm max-h-96 overflow-y-auto" }, /* @__PURE__ */ React10.createElement("h3", { className: "font-bold mb-4 text-lg" }, "\u2699\uFE0F \u8BBE\u7F6E\u9762\u677F"), /* @__PURE__ */ React10.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React10.createElement("div", { className: "border-b border-gray-600 pb-3" }, /* @__PURE__ */ React10.createElement("h4", { className: "font-semibold mb-2 text-blue-300" }, "\u{1F4F7} \u6444\u50CF\u5934\u8BBE\u7F6E"), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u6444\u50CF\u5934\u671D\u5411"), /* @__PURE__ */ React10.createElement(
|
|
6746
|
-
"select",
|
|
6747
|
-
{
|
|
6748
|
-
value: state.cameraFacing,
|
|
6749
|
-
onChange: (e) => handleARSettingChange("cameraFacing", e.target.value),
|
|
6750
|
-
className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
|
|
6751
|
-
},
|
|
6752
|
-
/* @__PURE__ */ React10.createElement("option", { value: "environment" }, "\u540E\u7F6E\u6444\u50CF\u5934"),
|
|
6753
|
-
/* @__PURE__ */ React10.createElement("option", { value: "user" }, "\u524D\u7F6E\u6444\u50CF\u5934")
|
|
6754
|
-
))), /* @__PURE__ */ React10.createElement("div", { className: "border-b border-gray-600 pb-3" }, /* @__PURE__ */ React10.createElement("h4", { className: "font-semibold mb-2 text-green-300" }, "\u{1F3AF} AR \u68C0\u6D4B\u8BBE\u7F6E"), /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u6807\u8BB0\u7C7B\u578B"), /* @__PURE__ */ React10.createElement(
|
|
6755
|
-
"select",
|
|
6756
|
-
{
|
|
6757
|
-
value: state.markerType,
|
|
6758
|
-
onChange: (e) => handleARSettingChange("markerType", e.target.value),
|
|
6759
|
-
className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
|
|
6760
|
-
},
|
|
6761
|
-
/* @__PURE__ */ React10.createElement("option", { value: "barcode" }, "\u6761\u7801 (Barcode)"),
|
|
6762
|
-
/* @__PURE__ */ React10.createElement("option", { value: "pattern" }, "\u56FE\u6848 (Hiro)")
|
|
6763
|
-
)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u68C0\u6D4B\u8D28\u91CF"), /* @__PURE__ */ React10.createElement(
|
|
6764
|
-
"select",
|
|
6765
|
-
{
|
|
6766
|
-
value: state.quality,
|
|
6767
|
-
onChange: (e) => handleARSettingChange("quality", e.target.value),
|
|
6768
|
-
className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
|
|
6769
|
-
},
|
|
6770
|
-
/* @__PURE__ */ React10.createElement("option", { value: "low" }, "\u4F4E\u8D28\u91CF (15fps)"),
|
|
6771
|
-
/* @__PURE__ */ React10.createElement("option", { value: "medium" }, "\u4E2D\u7B49\u8D28\u91CF (30fps)"),
|
|
6772
|
-
/* @__PURE__ */ React10.createElement("option", { value: "high" }, "\u9AD8\u8D28\u91CF (60fps)")
|
|
6773
|
-
)))), /* @__PURE__ */ React10.createElement("div", { className: "border-b border-gray-600 pb-3" }, /* @__PURE__ */ React10.createElement("h4", { className: "font-semibold mb-2 text-purple-300" }, "\u{1F441}\uFE0F \u89C6\u89C9\u8BBE\u7F6E"), /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React10.createElement("label", { className: "flex items-center" }, /* @__PURE__ */ React10.createElement(
|
|
6774
|
-
"input",
|
|
6775
|
-
{
|
|
6776
|
-
type: "checkbox",
|
|
6777
|
-
checked: state.showWireframe,
|
|
6778
|
-
onChange: (e) => setState((prev) => ({ ...prev, showWireframe: e.target.checked })),
|
|
6779
|
-
className: "mr-2"
|
|
6780
|
-
}
|
|
6781
|
-
), /* @__PURE__ */ React10.createElement("span", { className: "text-sm" }, "\u663E\u793A\u7EBF\u6846")), /* @__PURE__ */ React10.createElement("label", { className: "flex items-center" }, /* @__PURE__ */ React10.createElement(
|
|
6782
|
-
"input",
|
|
6783
|
-
{
|
|
6784
|
-
type: "checkbox",
|
|
6785
|
-
checked: state.lightingEnabled,
|
|
6786
|
-
onChange: (e) => setState((prev) => ({ ...prev, lightingEnabled: e.target.checked })),
|
|
6787
|
-
className: "mr-2"
|
|
6788
|
-
}
|
|
6789
|
-
), /* @__PURE__ */ React10.createElement("span", { className: "text-sm" }, "\u542F\u7528\u5149\u7167")))), /* @__PURE__ */ React10.createElement("div", { className: "border-b border-gray-600 pb-3" }, /* @__PURE__ */ React10.createElement("h4", { className: "font-semibold mb-2 text-orange-300" }, "\u{1F3AD} \u6A21\u578B\u4E0E\u52A8\u753B"), /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u6A21\u578B\u9009\u62E9"), /* @__PURE__ */ React10.createElement(
|
|
6790
|
-
"select",
|
|
6791
|
-
{
|
|
6792
|
-
value: state.selectedModel,
|
|
6793
|
-
onChange: (e) => setState((prev) => ({ ...prev, selectedModel: e.target.value })),
|
|
6794
|
-
className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
|
|
6795
|
-
},
|
|
6796
|
-
/* @__PURE__ */ React10.createElement("option", { value: "sphere" }, "\u{1F310} \u7403\u4F53"),
|
|
6797
|
-
/* @__PURE__ */ React10.createElement("option", { value: "cube" }, "\u2B1C \u7ACB\u65B9\u4F53"),
|
|
6798
|
-
/* @__PURE__ */ React10.createElement("option", { value: "torus" }, "\u2B55 \u5706\u73AF")
|
|
6799
|
-
)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u52A8\u4F5C\u9009\u62E9"), /* @__PURE__ */ React10.createElement(
|
|
6800
|
-
"select",
|
|
6801
|
-
{
|
|
6802
|
-
value: state.selectedMotion,
|
|
6803
|
-
onChange: (e) => setState((prev) => ({ ...prev, selectedMotion: e.target.value })),
|
|
6804
|
-
className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
|
|
6805
|
-
},
|
|
6806
|
-
/* @__PURE__ */ React10.createElement("option", { value: "idle" }, "\u{1F9D8} \u5F85\u673A"),
|
|
6807
|
-
/* @__PURE__ */ React10.createElement("option", { value: "dance" }, "\u{1F483} \u821E\u8E48"),
|
|
6808
|
-
/* @__PURE__ */ React10.createElement("option", { value: "wave" }, "\u{1F44B} \u6325\u624B")
|
|
6809
|
-
)), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium mb-1" }, "\u97F3\u4E50\u9009\u62E9"), /* @__PURE__ */ React10.createElement(
|
|
6810
|
-
"select",
|
|
7089
|
+
}, [cleanupAR, onCameraError, resize, setupAR, setupRenderer, startRenderLoop]);
|
|
7090
|
+
useEffect(() => {
|
|
7091
|
+
attachModelRoot(resolvedARMode);
|
|
7092
|
+
}, [attachModelRoot, resolvedARMode]);
|
|
7093
|
+
useEffect(() => {
|
|
7094
|
+
if (resolvedResources) {
|
|
7095
|
+
loadMMDResources();
|
|
7096
|
+
updateAudio();
|
|
7097
|
+
} else if (modelPresets.length === 0) {
|
|
7098
|
+
const message = "No model presets configured.";
|
|
7099
|
+
setError(message);
|
|
7100
|
+
setIsLoading(false);
|
|
7101
|
+
onError?.(new Error(message));
|
|
7102
|
+
}
|
|
7103
|
+
}, [loadMMDResources, modelPresets.length, onError, resolvedResources, updateAudio]);
|
|
7104
|
+
const mirroredStyle = mirrored ? { transform: "scaleX(-1)" } : void 0;
|
|
7105
|
+
return /* @__PURE__ */ React10.createElement(
|
|
7106
|
+
"div",
|
|
6811
7107
|
{
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
7108
|
+
ref: containerRef,
|
|
7109
|
+
className: clsx("relative w-full h-full overflow-hidden bg-black", className),
|
|
7110
|
+
style
|
|
6815
7111
|
},
|
|
6816
|
-
/* @__PURE__ */ React10.createElement("
|
|
6817
|
-
/* @__PURE__ */ React10.createElement("
|
|
6818
|
-
/* @__PURE__ */ React10.createElement("
|
|
6819
|
-
|
|
6820
|
-
"
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
7112
|
+
/* @__PURE__ */ React10.createElement("div", { ref: videoContainerRef, className: "absolute inset-0", style: mirroredStyle }),
|
|
7113
|
+
/* @__PURE__ */ React10.createElement("canvas", { ref: canvasRef, className: "absolute inset-0 w-full h-full", style: mirroredStyle }),
|
|
7114
|
+
isLoading && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 flex items-center justify-center bg-black/70 text-white z-20" }, /* @__PURE__ */ React10.createElement("div", { className: "text-center" }, /* @__PURE__ */ React10.createElement("div", { className: "h-10 w-10 animate-spin rounded-full border-b-2 border-white mx-auto mb-3" }), /* @__PURE__ */ React10.createElement("div", null, "Initializing AR..."))),
|
|
7115
|
+
error && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 flex items-center justify-center bg-red-950/80 text-white z-20" }, /* @__PURE__ */ React10.createElement("div", { className: "text-center max-w-sm px-4" }, /* @__PURE__ */ React10.createElement("div", { className: "text-lg font-semibold mb-2" }, "AR Error"), /* @__PURE__ */ React10.createElement("div", { className: "text-sm text-red-200" }, error))),
|
|
7116
|
+
arReady && !error && /* @__PURE__ */ React10.createElement(React10.Fragment, null, resolvedARMode !== "overlay" /* Overlay */ && !modelPlaced && /* @__PURE__ */ React10.createElement("div", { className: "absolute top-4 left-4 right-4 bg-black/70 text-white p-3 rounded-lg text-sm z-10" }, /* @__PURE__ */ React10.createElement("div", { className: "font-semibold mb-1" }, "Marker Placement"), /* @__PURE__ */ React10.createElement("div", { className: "text-gray-200" }, 'Align the marker in view, then tap "', placementText, '" to place the model.'), /* @__PURE__ */ React10.createElement("div", { className: "mt-2" }, markerDetected ? /* @__PURE__ */ React10.createElement("span", { className: "text-green-400" }, "Marker detected") : /* @__PURE__ */ React10.createElement("span", { className: "text-yellow-400" }, "Waiting for marker..."))), /* @__PURE__ */ React10.createElement("div", { className: "absolute top-4 right-4 flex items-center space-x-2 z-10" }, /* @__PURE__ */ React10.createElement(
|
|
7117
|
+
"span",
|
|
7118
|
+
{
|
|
7119
|
+
className: clsx("h-2.5 w-2.5 rounded-full", cameraReady ? "bg-green-400" : "bg-red-400"),
|
|
7120
|
+
title: "Camera"
|
|
7121
|
+
}
|
|
7122
|
+
), /* @__PURE__ */ React10.createElement(
|
|
7123
|
+
"span",
|
|
7124
|
+
{
|
|
7125
|
+
className: clsx("h-2.5 w-2.5 rounded-full", arReady ? "bg-green-400" : "bg-red-400"),
|
|
7126
|
+
title: "AR"
|
|
7127
|
+
}
|
|
7128
|
+
), /* @__PURE__ */ React10.createElement(
|
|
7129
|
+
"span",
|
|
7130
|
+
{
|
|
7131
|
+
className: clsx("h-2.5 w-2.5 rounded-full", markerDetected ? "bg-blue-400" : "bg-gray-400"),
|
|
7132
|
+
title: "Marker"
|
|
7133
|
+
}
|
|
7134
|
+
)), /* @__PURE__ */ React10.createElement("div", { className: "absolute bottom-4 left-4 right-4 flex justify-center gap-3 z-10" }, /* @__PURE__ */ React10.createElement(
|
|
7135
|
+
"button",
|
|
7136
|
+
{
|
|
7137
|
+
onClick: () => setSettingsVisible((prev) => !prev),
|
|
7138
|
+
className: "px-4 py-2 rounded-lg bg-gray-700 text-white hover:bg-gray-600"
|
|
6830
7139
|
},
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
}
|
|
6842
|
-
if (markerRootRef.current) {
|
|
6843
|
-
markerRootRef.current.visible = true;
|
|
6844
|
-
}
|
|
6845
|
-
setState((prev) => ({
|
|
6846
|
-
...prev,
|
|
6847
|
-
modelPlaced: false,
|
|
6848
|
-
markerDetected: false,
|
|
6849
|
-
selectedModel: "sphere",
|
|
6850
|
-
selectedMotion: "idle",
|
|
6851
|
-
selectedAudio: "none"
|
|
6852
|
-
}));
|
|
7140
|
+
"Settings"
|
|
7141
|
+
), resolvedARMode !== "overlay" /* Overlay */ && !modelPlaced && /* @__PURE__ */ React10.createElement(
|
|
7142
|
+
"button",
|
|
7143
|
+
{
|
|
7144
|
+
onClick: placeModel,
|
|
7145
|
+
disabled: !markerDetected,
|
|
7146
|
+
className: clsx(
|
|
7147
|
+
"px-5 py-2 rounded-lg text-white",
|
|
7148
|
+
markerDetected ? "bg-emerald-600 hover:bg-emerald-500" : "bg-gray-500"
|
|
7149
|
+
)
|
|
6853
7150
|
},
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
},
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
"
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
7151
|
+
placementText
|
|
7152
|
+
), modelPlaced && /* @__PURE__ */ React10.createElement(
|
|
7153
|
+
"button",
|
|
7154
|
+
{
|
|
7155
|
+
onClick: removeModel,
|
|
7156
|
+
className: "px-5 py-2 rounded-lg text-white bg-orange-600 hover:bg-orange-500"
|
|
7157
|
+
},
|
|
7158
|
+
"Reset"
|
|
7159
|
+
)), settingsVisible && /* @__PURE__ */ React10.createElement("div", { className: "absolute top-16 right-4 bg-black/80 text-white p-4 rounded-lg w-64 space-y-3 z-10" }, /* @__PURE__ */ React10.createElement("div", { className: "text-sm font-semibold" }, "AR Settings"), /* @__PURE__ */ React10.createElement("label", { className: "block text-xs text-gray-300" }, "Model", /* @__PURE__ */ React10.createElement(
|
|
7160
|
+
"select",
|
|
7161
|
+
{
|
|
7162
|
+
value: selectedModelId,
|
|
7163
|
+
onChange: (event) => {
|
|
7164
|
+
setOverrideResources(null);
|
|
7165
|
+
setSelectedModelId(event.target.value);
|
|
7166
|
+
},
|
|
7167
|
+
className: "mt-1 w-full bg-gray-700 text-white text-sm rounded px-2 py-1"
|
|
7168
|
+
},
|
|
7169
|
+
modelPresets.map((preset) => /* @__PURE__ */ React10.createElement("option", { key: preset.id, value: preset.id }, preset.name))
|
|
7170
|
+
)), /* @__PURE__ */ React10.createElement("label", { className: "block text-xs text-gray-300" }, "Motion", /* @__PURE__ */ React10.createElement(
|
|
7171
|
+
"select",
|
|
7172
|
+
{
|
|
7173
|
+
value: selectedMotionId,
|
|
7174
|
+
onChange: (event) => {
|
|
7175
|
+
setOverrideResources(null);
|
|
7176
|
+
setSelectedMotionId(event.target.value);
|
|
7177
|
+
},
|
|
7178
|
+
className: "mt-1 w-full bg-gray-700 text-white text-sm rounded px-2 py-1"
|
|
7179
|
+
},
|
|
7180
|
+
motionPresets.map((preset) => /* @__PURE__ */ React10.createElement("option", { key: preset.id, value: preset.id }, preset.name))
|
|
7181
|
+
)), audioPresets && audioPresets.length > 0 && /* @__PURE__ */ React10.createElement("label", { className: "block text-xs text-gray-300" }, "Audio", /* @__PURE__ */ React10.createElement(
|
|
7182
|
+
"select",
|
|
7183
|
+
{
|
|
7184
|
+
value: selectedAudioId,
|
|
7185
|
+
onChange: (event) => {
|
|
7186
|
+
setOverrideResources(null);
|
|
7187
|
+
setSelectedAudioId(event.target.value);
|
|
7188
|
+
},
|
|
7189
|
+
className: "mt-1 w-full bg-gray-700 text-white text-sm rounded px-2 py-1"
|
|
7190
|
+
},
|
|
7191
|
+
audioPresets.map((preset) => /* @__PURE__ */ React10.createElement("option", { key: preset.id, value: preset.id }, preset.name))
|
|
7192
|
+
)), /* @__PURE__ */ React10.createElement("label", { className: "block text-xs text-gray-300" }, "AR Mode", /* @__PURE__ */ React10.createElement(
|
|
7193
|
+
"select",
|
|
7194
|
+
{
|
|
7195
|
+
value: resolvedARMode,
|
|
7196
|
+
onChange: (event) => {
|
|
7197
|
+
const next = event.target.value;
|
|
7198
|
+
if (!arMode) {
|
|
7199
|
+
setInternalARMode(next);
|
|
7200
|
+
}
|
|
7201
|
+
attachModelRoot(next);
|
|
7202
|
+
onARModeChange?.(next);
|
|
7203
|
+
},
|
|
7204
|
+
className: "mt-1 w-full bg-gray-700 text-white text-sm rounded px-2 py-1"
|
|
7205
|
+
},
|
|
7206
|
+
/* @__PURE__ */ React10.createElement("option", { value: "overlay" /* Overlay */ }, "Overlay"),
|
|
7207
|
+
/* @__PURE__ */ React10.createElement("option", { value: "world-fixed" /* WorldFixed */ }, "World Fixed")
|
|
7208
|
+
)), /* @__PURE__ */ React10.createElement("label", { className: "block text-xs text-gray-300" }, "Camera", /* @__PURE__ */ React10.createElement(
|
|
7209
|
+
"select",
|
|
7210
|
+
{
|
|
7211
|
+
value: cameraFacing,
|
|
7212
|
+
onChange: (event) => {
|
|
7213
|
+
const next = event.target.value;
|
|
7214
|
+
setCameraFacing(next);
|
|
7215
|
+
cleanupAR();
|
|
7216
|
+
setupAR(next).catch(() => void 0);
|
|
7217
|
+
},
|
|
7218
|
+
className: "mt-1 w-full bg-gray-700 text-white text-sm rounded px-2 py-1"
|
|
7219
|
+
},
|
|
7220
|
+
/* @__PURE__ */ React10.createElement("option", { value: "environment" }, "Back"),
|
|
7221
|
+
/* @__PURE__ */ React10.createElement("option", { value: "user" }, "Front")
|
|
7222
|
+
))))
|
|
7223
|
+
);
|
|
6880
7224
|
});
|
|
6881
|
-
|
|
7225
|
+
MMDARApp.displayName = "MMDARApp";
|
|
6882
7226
|
|
|
6883
|
-
// src/mmd/ar/
|
|
6884
|
-
var
|
|
6885
|
-
|
|
6886
|
-
ARMode2["WorldFixed"] = "world-fixed";
|
|
6887
|
-
return ARMode2;
|
|
6888
|
-
})(ARMode || {});
|
|
7227
|
+
// src/mmd/ar/MMDARPlayer.tsx
|
|
7228
|
+
var MMDARPlayer = MMDARApp;
|
|
7229
|
+
MMDARPlayer.displayName = "MMDARPlayer";
|
|
6889
7230
|
|
|
6890
7231
|
// src/mmd/fx/HLSLToGLSLConverter.ts
|
|
6891
7232
|
var HLSLToGLSLConverter = class {
|
|
@@ -8972,6 +9313,6 @@ var FXThreePreview = ({
|
|
|
8972
9313
|
};
|
|
8973
9314
|
FXThreePreview.displayName = "FXThreePreview";
|
|
8974
9315
|
|
|
8975
|
-
export { ARMode, CheerButton, CheerParticles, ChoiceMenu, DialogueBox, FXParser, FXThreePreview, FXToThreeAdapter, FXViewer, HLSLToGLSLConverter, HistoryPanel, LoadingOverlay, LoadingScreen, LoopConfirmDialog, MMDARPlayer, MMDLightingDebugPanel, MMDMusicPlayer, MMDPlayerBase, MMDPlayerEnhanced, MMDPlayerEnhancedDebugInfo, MMDPlaylist, MMDPlaylistDebugInfo, MMDVisualNovel, MMDVisualNovelWithSelector, ModelSelectorSettings, MultiFXAdapter, MusicControls, PMXEditor2 as PMXEditor, PMXEditor as PMXEditorCore, PMXExporter, PMXViewer, PlaylistPanel, StartScreen, TrackInfo, addDefaultSphereTextures, checkModelSphereDefinition, checkSphereTextures, compareFXEffects, configureMaterialsForMMD, configureRendererForMMD, createMMDLights, diagnoseMaterialsMMD, exportFXToJSON, exportFXToMarkdown, extractTexturePaths, filterDefinesByPrefix, fullSphereDiagnostic, generateAllToonTextures, generateToonTexture, getColorParameters, getConfigSummaryText, getFeatureFlags, getTextureDefines, hasFeature, inspectMaterial, listAllMaterials, loadAmmo, printDiagnosticReport, printModelSphereInfo, printSphereDiagnostic, quickDiagnose, validateFXEffect };
|
|
9316
|
+
export { ARMode, CheerButton, CheerParticles, ChoiceMenu, DialogueBox, FXParser, FXThreePreview, FXToThreeAdapter, FXViewer, HLSLToGLSLConverter, HistoryPanel, LoadingOverlay, LoadingScreen, LoopConfirmDialog, MMDARApp, MMDARPlayer, MMDLightingDebugPanel, MMDMusicPlayer, MMDPlayerBase, MMDPlayerEnhanced, MMDPlayerEnhancedDebugInfo, MMDPlaylist, MMDPlaylistDebugInfo, MMDUploadPanel, MMDVisualNovel, MMDVisualNovelWithSelector, MMD_UPLOAD_CONFIGS, ModelSelectorSettings, MultiFXAdapter, MusicControls, PMXEditor2 as PMXEditor, PMXEditor as PMXEditorCore, PMXExporter, PMXViewer, PlaylistPanel, StartScreen, TrackInfo, addDefaultSphereTextures, checkModelSphereDefinition, checkSphereTextures, compareFXEffects, configureMaterialsForMMD, configureRendererForMMD, createMMDLights, diagnoseMaterialsMMD, exportFXToJSON, exportFXToMarkdown, extractTexturePaths, filterDefinesByPrefix, fullSphereDiagnostic, generateAllToonTextures, generateToonTexture, getColorParameters, getConfigSummaryText, getFeatureFlags, getTextureDefines, hasFeature, inspectMaterial, listAllMaterials, loadAmmo, printDiagnosticReport, printModelSphereInfo, printSphereDiagnostic, quickDiagnose, validateFXEffect };
|
|
8976
9317
|
//# sourceMappingURL=index.mjs.map
|
|
8977
9318
|
//# sourceMappingURL=index.mjs.map
|