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.
Files changed (335) hide show
  1. package/dist/UniversalFileService-C3WQAFOV.js +15 -0
  2. package/dist/{UniversalFileService-J6ET6KZK.js.map → UniversalFileService-C3WQAFOV.js.map} +1 -1
  3. package/dist/UniversalFileService-O3IEROBN.mjs +6 -0
  4. package/dist/{UniversalFileService-336GFY6N.mjs.map → UniversalFileService-O3IEROBN.mjs.map} +1 -1
  5. package/dist/ai/llm/index.d.mts +70 -0
  6. package/dist/ai/llm/index.d.ts +70 -0
  7. package/dist/ai/llm/index.js +54 -0
  8. package/dist/ai/llm/index.js.map +1 -0
  9. package/dist/ai/llm/index.mjs +5 -0
  10. package/dist/ai/llm/index.mjs.map +1 -0
  11. package/dist/ai/llm/ui/electron/index.d.mts +5 -0
  12. package/dist/ai/llm/ui/electron/index.d.ts +5 -0
  13. package/dist/ai/llm/ui/electron/index.js +21 -0
  14. package/dist/ai/llm/ui/electron/index.js.map +1 -0
  15. package/dist/ai/llm/ui/electron/index.mjs +8 -0
  16. package/dist/ai/llm/ui/electron/index.mjs.map +1 -0
  17. package/dist/ai/llm/ui/miniapp/index.d.mts +9 -0
  18. package/dist/ai/llm/ui/miniapp/index.d.ts +9 -0
  19. package/dist/ai/llm/ui/miniapp/index.js +107 -0
  20. package/dist/ai/llm/ui/miniapp/index.js.map +1 -0
  21. package/dist/ai/llm/ui/miniapp/index.mjs +101 -0
  22. package/dist/ai/llm/ui/miniapp/index.mjs.map +1 -0
  23. package/dist/ai/llm/ui/rn/index.d.mts +9 -0
  24. package/dist/ai/llm/ui/rn/index.d.ts +9 -0
  25. package/dist/ai/llm/ui/rn/index.js +249 -0
  26. package/dist/ai/llm/ui/rn/index.js.map +1 -0
  27. package/dist/ai/llm/ui/rn/index.mjs +243 -0
  28. package/dist/ai/llm/ui/rn/index.mjs.map +1 -0
  29. package/dist/ai/llm/ui/web/index.d.mts +15 -0
  30. package/dist/ai/llm/ui/web/index.d.ts +15 -0
  31. package/dist/ai/llm/ui/web/index.js +21 -0
  32. package/dist/ai/llm/ui/web/index.js.map +1 -0
  33. package/dist/ai/llm/ui/web/index.mjs +8 -0
  34. package/dist/ai/llm/ui/web/index.mjs.map +1 -0
  35. package/dist/ar/index.d.mts +7 -0
  36. package/dist/ar/index.d.ts +7 -0
  37. package/dist/ar/index.js +17 -0
  38. package/dist/ar/index.js.map +1 -0
  39. package/dist/ar/index.mjs +4 -0
  40. package/dist/ar/index.mjs.map +1 -0
  41. package/dist/auth/index.js +22 -22
  42. package/dist/auth/index.mjs +2 -2
  43. package/dist/auth/legacy/db/index.d.mts +5 -0
  44. package/dist/auth/legacy/db/index.d.ts +5 -0
  45. package/dist/auth/legacy/db/index.js +34 -0
  46. package/dist/auth/legacy/db/index.js.map +1 -0
  47. package/dist/auth/legacy/db/index.mjs +5 -0
  48. package/dist/auth/legacy/db/index.mjs.map +1 -0
  49. package/dist/auth/legacy/index.d.mts +51 -0
  50. package/dist/auth/legacy/index.d.ts +51 -0
  51. package/dist/auth/legacy/index.js +146 -0
  52. package/dist/auth/legacy/index.js.map +1 -0
  53. package/dist/auth/legacy/index.mjs +13 -0
  54. package/dist/auth/legacy/index.mjs.map +1 -0
  55. package/dist/auth/legacy/logic/index.d.mts +9 -0
  56. package/dist/auth/legacy/logic/index.d.ts +9 -0
  57. package/dist/auth/legacy/logic/index.js +18 -0
  58. package/dist/auth/legacy/logic/index.js.map +1 -0
  59. package/dist/auth/legacy/logic/index.mjs +5 -0
  60. package/dist/auth/legacy/logic/index.mjs.map +1 -0
  61. package/dist/auth/legacy/routes/index.d.mts +50 -0
  62. package/dist/auth/legacy/routes/index.d.ts +50 -0
  63. package/dist/auth/legacy/routes/index.js +34 -0
  64. package/dist/auth/legacy/routes/index.js.map +1 -0
  65. package/dist/auth/legacy/routes/index.mjs +5 -0
  66. package/dist/auth/legacy/routes/index.mjs.map +1 -0
  67. package/dist/auth/legacy/schema/index.d.mts +401 -0
  68. package/dist/auth/legacy/schema/index.d.ts +401 -0
  69. package/dist/auth/legacy/schema/index.js +29 -0
  70. package/dist/auth/legacy/schema/index.js.map +1 -0
  71. package/dist/auth/legacy/schema/index.mjs +4 -0
  72. package/dist/auth/legacy/schema/index.mjs.map +1 -0
  73. package/dist/auth/legacy/server/index.d.mts +15 -0
  74. package/dist/auth/legacy/server/index.d.ts +15 -0
  75. package/dist/auth/legacy/server/index.js +65 -0
  76. package/dist/auth/legacy/server/index.js.map +1 -0
  77. package/dist/auth/legacy/server/index.mjs +8 -0
  78. package/dist/auth/legacy/server/index.mjs.map +1 -0
  79. package/dist/auth/legacy/services/index.d.mts +40 -0
  80. package/dist/auth/legacy/services/index.d.ts +40 -0
  81. package/dist/auth/legacy/services/index.js +14 -0
  82. package/dist/auth/legacy/services/index.js.map +1 -0
  83. package/dist/auth/legacy/services/index.mjs +5 -0
  84. package/dist/auth/legacy/services/index.mjs.map +1 -0
  85. package/dist/auth/legacy/ui/miniapp/index.d.mts +10 -0
  86. package/dist/auth/legacy/ui/miniapp/index.d.ts +10 -0
  87. package/dist/auth/legacy/ui/miniapp/index.js +23 -0
  88. package/dist/auth/legacy/ui/miniapp/index.js.map +1 -0
  89. package/dist/auth/legacy/ui/miniapp/index.mjs +6 -0
  90. package/dist/auth/legacy/ui/miniapp/index.mjs.map +1 -0
  91. package/dist/auth/legacy/ui/web/index.d.mts +22 -0
  92. package/dist/auth/legacy/ui/web/index.d.ts +22 -0
  93. package/dist/auth/legacy/ui/web/index.js +31 -0
  94. package/dist/auth/legacy/ui/web/index.js.map +1 -0
  95. package/dist/auth/legacy/ui/web/index.mjs +6 -0
  96. package/dist/auth/legacy/ui/web/index.mjs.map +1 -0
  97. package/dist/booking-B0BM8grt.d.mts +141 -0
  98. package/dist/booking-CUy8u7Za.d.ts +141 -0
  99. package/dist/{bookingAdminService-Dmg7dC6V.d.mts → bookingAdminService-BNEDyw7U.d.mts} +1 -1
  100. package/dist/{bookingAdminService-B2QDjSHJ.d.ts → bookingAdminService-BtOtG96L.d.ts} +1 -1
  101. package/dist/calendar/index.d.mts +390 -237
  102. package/dist/calendar/index.d.ts +390 -237
  103. package/dist/calendar/index.js +3825 -3785
  104. package/dist/calendar/index.js.map +1 -1
  105. package/dist/calendar/index.mjs +3730 -3696
  106. package/dist/calendar/index.mjs.map +1 -1
  107. package/dist/calendar/routes/index.js +30 -327
  108. package/dist/calendar/routes/index.js.map +1 -1
  109. package/dist/calendar/routes/index.mjs +1 -323
  110. package/dist/calendar/routes/index.mjs.map +1 -1
  111. package/dist/calendar/server.d.mts +6 -0
  112. package/dist/calendar/server.d.ts +6 -0
  113. package/dist/calendar/server.js +41 -13
  114. package/dist/calendar/server.js.map +1 -1
  115. package/dist/calendar/server.mjs +2 -2
  116. package/dist/calendar/server.mjs.map +1 -1
  117. package/dist/{cart-D3o67Q3H.d.ts → cart-Cw3i0Dy6.d.ts} +1 -1
  118. package/dist/{cart-CcZ7rQyG.d.mts → cart-DLSbsihH.d.mts} +1 -1
  119. package/dist/chunk-24F7KUED.js +263 -0
  120. package/dist/chunk-24F7KUED.js.map +1 -0
  121. package/dist/{chunk-YMS6BPXS.js → chunk-27IUMDDK.js} +3 -3
  122. package/dist/{chunk-YMS6BPXS.js.map → chunk-27IUMDDK.js.map} +1 -1
  123. package/dist/chunk-37M6NZIF.js +279 -0
  124. package/dist/chunk-37M6NZIF.js.map +1 -0
  125. package/dist/chunk-3JMUNOUT.js +144 -0
  126. package/dist/chunk-3JMUNOUT.js.map +1 -0
  127. package/dist/chunk-3PFCOTJP.mjs +256 -0
  128. package/dist/chunk-3PFCOTJP.mjs.map +1 -0
  129. package/dist/{chunk-SKCMZYSQ.js → chunk-3YSRTVIY.js} +31 -15
  130. package/dist/chunk-3YSRTVIY.js.map +1 -0
  131. package/dist/{chunk-NZZZUMMX.mjs → chunk-57MVE5LL.mjs} +3 -3
  132. package/dist/{chunk-NZZZUMMX.mjs.map → chunk-57MVE5LL.mjs.map} +1 -1
  133. package/dist/{chunk-622Y6LTH.mjs → chunk-5BLZEVWK.mjs} +196 -468
  134. package/dist/chunk-5BLZEVWK.mjs.map +1 -0
  135. package/dist/{chunk-UVHPCLP6.js → chunk-5LCGOCKG.js} +5 -5
  136. package/dist/{chunk-UVHPCLP6.js.map → chunk-5LCGOCKG.js.map} +1 -1
  137. package/dist/chunk-6XUQ2B4K.js +219 -0
  138. package/dist/chunk-6XUQ2B4K.js.map +1 -0
  139. package/dist/{chunk-NCOXT7SK.js → chunk-77UEPWVQ.js} +4 -4
  140. package/dist/{chunk-NCOXT7SK.js.map → chunk-77UEPWVQ.js.map} +1 -1
  141. package/dist/chunk-C76U5FF4.mjs +10 -0
  142. package/dist/chunk-C76U5FF4.mjs.map +1 -0
  143. package/dist/chunk-CFM56MGO.mjs +35 -0
  144. package/dist/chunk-CFM56MGO.mjs.map +1 -0
  145. package/dist/{chunk-LJGJPAQ4.js → chunk-COOI6MT3.js} +2 -11
  146. package/dist/chunk-COOI6MT3.js.map +1 -0
  147. package/dist/chunk-CPSFYP34.mjs +140 -0
  148. package/dist/chunk-CPSFYP34.mjs.map +1 -0
  149. package/dist/chunk-D22QBOCM.mjs +336 -0
  150. package/dist/chunk-D22QBOCM.mjs.map +1 -0
  151. package/dist/chunk-DA4QV64P.mjs +35 -0
  152. package/dist/chunk-DA4QV64P.mjs.map +1 -0
  153. package/dist/{chunk-FVDPGX6A.mjs → chunk-DWJLOHAE.mjs} +2 -11
  154. package/dist/chunk-DWJLOHAE.mjs.map +1 -0
  155. package/dist/chunk-EKDLZND6.js +275 -0
  156. package/dist/chunk-EKDLZND6.js.map +1 -0
  157. package/dist/chunk-EKQPFZXQ.js +12 -0
  158. package/dist/chunk-EKQPFZXQ.js.map +1 -0
  159. package/dist/chunk-ERAAB5VG.js +324 -0
  160. package/dist/chunk-ERAAB5VG.js.map +1 -0
  161. package/dist/chunk-ESLY72VI.mjs +175 -0
  162. package/dist/chunk-ESLY72VI.mjs.map +1 -0
  163. package/dist/chunk-FGQGWW73.js +38 -0
  164. package/dist/chunk-FGQGWW73.js.map +1 -0
  165. package/dist/chunk-FXQOXLDE.js +120 -0
  166. package/dist/chunk-FXQOXLDE.js.map +1 -0
  167. package/dist/chunk-FZELCJR7.mjs +19 -0
  168. package/dist/chunk-FZELCJR7.mjs.map +1 -0
  169. package/dist/{chunk-HHVDOIPV.js → chunk-H3P2PGZL.js} +3 -3
  170. package/dist/{chunk-HHVDOIPV.js.map → chunk-H3P2PGZL.js.map} +1 -1
  171. package/dist/chunk-HBQMN5QM.mjs +10 -0
  172. package/dist/chunk-HBQMN5QM.mjs.map +1 -0
  173. package/dist/chunk-ITRIXMXF.mjs +862 -0
  174. package/dist/chunk-ITRIXMXF.mjs.map +1 -0
  175. package/dist/chunk-IUWSCUDC.js +4 -0
  176. package/dist/chunk-IUWSCUDC.js.map +1 -0
  177. package/dist/chunk-JCKCKRC2.js +50 -0
  178. package/dist/chunk-JCKCKRC2.js.map +1 -0
  179. package/dist/chunk-L7GQNY54.mjs +286 -0
  180. package/dist/chunk-L7GQNY54.mjs.map +1 -0
  181. package/dist/{chunk-ZRWED7Q6.js → chunk-LDVJ7URJ.js} +235 -520
  182. package/dist/chunk-LDVJ7URJ.js.map +1 -0
  183. package/dist/{chunk-WK3HTUID.js → chunk-MLP74E3O.js} +609 -1643
  184. package/dist/chunk-MLP74E3O.js.map +1 -0
  185. package/dist/chunk-NAX4TUT7.js +182 -0
  186. package/dist/chunk-NAX4TUT7.js.map +1 -0
  187. package/dist/chunk-NW4EN4YI.mjs +213 -0
  188. package/dist/chunk-NW4EN4YI.mjs.map +1 -0
  189. package/dist/{chunk-7CMGQX3S.mjs → chunk-OX6VMQDU.mjs} +14 -13
  190. package/dist/chunk-OX6VMQDU.mjs.map +1 -0
  191. package/dist/chunk-P3QMT3AY.mjs +44 -0
  192. package/dist/chunk-P3QMT3AY.mjs.map +1 -0
  193. package/dist/chunk-PJ4KYAQZ.mjs +631 -0
  194. package/dist/chunk-PJ4KYAQZ.mjs.map +1 -0
  195. package/dist/chunk-PLSEAREM.js +345 -0
  196. package/dist/chunk-PLSEAREM.js.map +1 -0
  197. package/dist/{chunk-EGJPS7OL.mjs → chunk-QZU4UJZG.mjs} +3 -3
  198. package/dist/{chunk-EGJPS7OL.mjs.map → chunk-QZU4UJZG.mjs.map} +1 -1
  199. package/dist/chunk-RJVR33ME.mjs +3 -0
  200. package/dist/chunk-RJVR33ME.mjs.map +1 -0
  201. package/dist/chunk-SYBHDB2D.js +650 -0
  202. package/dist/chunk-SYBHDB2D.js.map +1 -0
  203. package/dist/chunk-TVKVM7JT.js +21 -0
  204. package/dist/chunk-TVKVM7JT.js.map +1 -0
  205. package/dist/{chunk-UZB4IO3T.mjs → chunk-UTB72ZJ7.mjs} +415 -1449
  206. package/dist/chunk-UTB72ZJ7.mjs.map +1 -0
  207. package/dist/chunk-V5HE6IYN.js +12 -0
  208. package/dist/chunk-V5HE6IYN.js.map +1 -0
  209. package/dist/chunk-V7EVKD5G.mjs +116 -0
  210. package/dist/chunk-V7EVKD5G.mjs.map +1 -0
  211. package/dist/chunk-VGPR3KLR.js +872 -0
  212. package/dist/chunk-VGPR3KLR.js.map +1 -0
  213. package/dist/chunk-VS7WATQD.js +255 -0
  214. package/dist/chunk-VS7WATQD.js.map +1 -0
  215. package/dist/chunk-VSP7XJT5.mjs +272 -0
  216. package/dist/chunk-VSP7XJT5.mjs.map +1 -0
  217. package/dist/{chunk-SNBILYSH.mjs → chunk-VTKAIOP5.mjs} +5 -5
  218. package/dist/{chunk-SNBILYSH.mjs.map → chunk-VTKAIOP5.mjs.map} +1 -1
  219. package/dist/chunk-VULJUXTF.mjs +267 -0
  220. package/dist/chunk-VULJUXTF.mjs.map +1 -0
  221. package/dist/chunk-XAHM6B3V.js +44 -0
  222. package/dist/chunk-XAHM6B3V.js.map +1 -0
  223. package/dist/chunk-YSF5YISM.mjs +248 -0
  224. package/dist/chunk-YSF5YISM.mjs.map +1 -0
  225. package/dist/{chunk-OFYBMMWT.mjs → chunk-YYJEVAJI.mjs} +3 -3
  226. package/dist/{chunk-OFYBMMWT.mjs.map → chunk-YYJEVAJI.mjs.map} +1 -1
  227. package/dist/components/index.d.mts +1 -0
  228. package/dist/components/index.d.ts +1 -0
  229. package/dist/components/index.js +182 -181
  230. package/dist/components/index.mjs +4 -3
  231. package/dist/{booking-BXtkG2ns.d.mts → index-Bi666jIm.d.mts} +1 -139
  232. package/dist/{booking-BXtkG2ns.d.ts → index-Bi666jIm.d.ts} +1 -139
  233. package/dist/index-DNKZ7-R_.d.mts +184 -0
  234. package/dist/index-DNKZ7-R_.d.ts +184 -0
  235. package/dist/index.d.mts +4 -1
  236. package/dist/index.d.ts +4 -1
  237. package/dist/index.js +285 -229
  238. package/dist/index.js.map +1 -1
  239. package/dist/index.mjs +15 -10
  240. package/dist/index.mjs.map +1 -1
  241. package/dist/mikuFusionGame/index.js +3 -3
  242. package/dist/mikuFusionGame/index.mjs +2 -2
  243. package/dist/mmd/index.d.mts +67 -9
  244. package/dist/mmd/index.d.ts +67 -9
  245. package/dist/mmd/index.js +969 -625
  246. package/dist/mmd/index.js.map +1 -1
  247. package/dist/mmd/index.mjs +969 -628
  248. package/dist/mmd/index.mjs.map +1 -1
  249. package/dist/portfolio/index.js +10 -9
  250. package/dist/portfolio/index.mjs +5 -4
  251. package/dist/qqbot/index.d.mts +2 -0
  252. package/dist/qqbot/index.d.ts +2 -0
  253. package/dist/qqbot/index.js +21 -0
  254. package/dist/qqbot/index.js.map +1 -0
  255. package/dist/qqbot/index.mjs +4 -0
  256. package/dist/qqbot/index.mjs.map +1 -0
  257. package/dist/qqbot/server/index.d.mts +91 -0
  258. package/dist/qqbot/server/index.d.ts +91 -0
  259. package/dist/qqbot/server/index.js +21 -0
  260. package/dist/qqbot/server/index.js.map +1 -0
  261. package/dist/qqbot/server/index.mjs +4 -0
  262. package/dist/qqbot/server/index.mjs.map +1 -0
  263. package/dist/qqbot/ui/web/index.d.mts +10 -0
  264. package/dist/qqbot/ui/web/index.d.ts +10 -0
  265. package/dist/qqbot/ui/web/index.js +105 -0
  266. package/dist/qqbot/ui/web/index.js.map +1 -0
  267. package/dist/qqbot/ui/web/index.mjs +99 -0
  268. package/dist/qqbot/ui/web/index.mjs.map +1 -0
  269. package/dist/screenReceiver/index.d.mts +78 -0
  270. package/dist/screenReceiver/index.d.ts +78 -0
  271. package/dist/screenReceiver/index.js +17 -0
  272. package/dist/screenReceiver/index.js.map +1 -0
  273. package/dist/screenReceiver/index.mjs +4 -0
  274. package/dist/screenReceiver/index.mjs.map +1 -0
  275. package/dist/screenReceiver/server/index.d.mts +36 -0
  276. package/dist/screenReceiver/server/index.d.ts +36 -0
  277. package/dist/screenReceiver/server/index.js +160 -0
  278. package/dist/screenReceiver/server/index.js.map +1 -0
  279. package/dist/screenReceiver/server/index.mjs +157 -0
  280. package/dist/screenReceiver/server/index.mjs.map +1 -0
  281. package/dist/showmasterpiece/db/index.js +42 -42
  282. package/dist/showmasterpiece/db/index.mjs +1 -1
  283. package/dist/showmasterpiece/index.d.mts +8 -6
  284. package/dist/showmasterpiece/index.d.ts +8 -6
  285. package/dist/showmasterpiece/index.js +142 -130
  286. package/dist/showmasterpiece/index.js.map +1 -1
  287. package/dist/showmasterpiece/index.mjs +18 -6
  288. package/dist/showmasterpiece/index.mjs.map +1 -1
  289. package/dist/showmasterpiece/logic/index.d.mts +9 -17
  290. package/dist/showmasterpiece/logic/index.d.ts +9 -17
  291. package/dist/showmasterpiece/logic/index.js +35 -34
  292. package/dist/showmasterpiece/logic/index.mjs +3 -2
  293. package/dist/showmasterpiece/logic/miniapp/index.d.mts +15 -0
  294. package/dist/showmasterpiece/logic/miniapp/index.d.ts +15 -0
  295. package/dist/showmasterpiece/logic/miniapp/index.js +42 -0
  296. package/dist/showmasterpiece/logic/miniapp/index.js.map +1 -0
  297. package/dist/showmasterpiece/logic/miniapp/index.mjs +5 -0
  298. package/dist/showmasterpiece/logic/miniapp/index.mjs.map +1 -0
  299. package/dist/showmasterpiece/server/index.js +42 -42
  300. package/dist/showmasterpiece/server/index.mjs +1 -1
  301. package/dist/showmasterpiece/ui/miniapp/index.d.mts +5 -2
  302. package/dist/showmasterpiece/ui/miniapp/index.d.ts +5 -2
  303. package/dist/showmasterpiece/ui/miniapp/index.js +83 -55
  304. package/dist/showmasterpiece/ui/miniapp/index.js.map +1 -1
  305. package/dist/showmasterpiece/ui/miniapp/index.mjs +83 -55
  306. package/dist/showmasterpiece/ui/miniapp/index.mjs.map +1 -1
  307. package/dist/showmasterpiece/ui/web/index.d.mts +3 -2
  308. package/dist/showmasterpiece/ui/web/index.d.ts +3 -2
  309. package/dist/showmasterpiece/ui/web/index.js +44 -33
  310. package/dist/showmasterpiece/ui/web/index.mjs +16 -5
  311. package/dist/testYourself/index.js +13 -13
  312. package/dist/testYourself/index.mjs +2 -2
  313. package/dist/types-B-hOccQw.d.mts +122 -0
  314. package/dist/types-B8rGXc4e.d.mts +38 -0
  315. package/dist/types-Cg89HGz2.d.ts +38 -0
  316. package/dist/types-CvKvpyN8.d.mts +48 -0
  317. package/dist/types-CvKvpyN8.d.ts +48 -0
  318. package/dist/types-Dy6x2gJW.d.ts +122 -0
  319. package/dist/universalFile/server/index.js +11 -11
  320. package/dist/universalFile/server/index.mjs +4 -4
  321. package/package.json +106 -1
  322. package/dist/UniversalFileService-336GFY6N.mjs +0 -6
  323. package/dist/UniversalFileService-J6ET6KZK.js +0 -15
  324. package/dist/chunk-622Y6LTH.mjs.map +0 -1
  325. package/dist/chunk-7CMGQX3S.mjs.map +0 -1
  326. package/dist/chunk-FVDPGX6A.mjs.map +0 -1
  327. package/dist/chunk-GVVS4IMM.mjs +0 -302
  328. package/dist/chunk-GVVS4IMM.mjs.map +0 -1
  329. package/dist/chunk-LJGJPAQ4.js.map +0 -1
  330. package/dist/chunk-SKCMZYSQ.js.map +0 -1
  331. package/dist/chunk-UZB4IO3T.mjs.map +0 -1
  332. package/dist/chunk-WC5QFO3T.js +0 -314
  333. package/dist/chunk-WC5QFO3T.js.map +0 -1
  334. package/dist/chunk-WK3HTUID.js.map +0 -1
  335. package/dist/chunk-ZRWED7Q6.js.map +0 -1
@@ -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 { OutlineEffect, OrbitControls, MMDLoader, MMDAnimationHelper } from 'three-stdlib';
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
- console.log("[MMDVisualNovel] VMD not finished, showing confirmation");
5342
+ log("VMD not finished, showing confirmation");
5138
5343
  setPendingNodeIndex(nodeIndex);
5139
5344
  return;
5140
5345
  }
5141
- console.log("[MMDVisualNovel] Transitioning to node " + nodeIndex);
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
- console.log("[MMDVisualNovel] Transition to node " + nodeIndex + " completed, waiting for model load");
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
- console.log("[MMDVisualNovel] Branching: " + key + "=" + val + " -> node " + nextNodeIndex);
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
- console.log("[MMDVisualNovel] \u5230\u8FBE\u6700\u540E\u4E00\u4E2A\u8282\u70B9\uFF0C\u663E\u793A\u5FAA\u73AF\u786E\u8BA4\u5BF9\u8BDD\u6846");
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
- console.log("[MMDVisualNovel] \u5FEB\u8FDB\u5230\u6700\u540E\uFF0C\u663E\u793A\u5FAA\u73AF\u786E\u8BA4\u5BF9\u8BDD\u6846");
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
- console.log("[MMDVisualNovel] \u56DE\u5230\u5F00\u59CB\u9875\u9762");
5509
+ log("Back to start screen");
5305
5510
  }, [initialNodeIndex, initialDialogueIndex]);
5306
5511
  const handleCheer = useCallback(() => {
5307
- console.log("[MMDVisualNovel] \u89E6\u53D1\u5E94\u63F4\u6548\u679C");
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
- console.log("[MMDVisualNovel] \u91CD\u65B0\u5F00\u59CB\u5FAA\u73AF");
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
- console.log("[MMDVisualNovel] MMDPlayerBase onLoad called");
5587
+ log("MMDPlayerBase onLoad");
5383
5588
  setIsLoading(false);
5384
5589
  if (isStartedRef.current) {
5385
- console.log("[MMDVisualNovel] Game already started, triggering play");
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
- console.log("[MMDVisualNovel] MMDPlayerBase onPlay called");
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
- console.log("[MMDVisualNovel] VMD finished/looped, marking as finished");
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
- console.log("[MMDVisualNovel] VMD ended, marking as finished");
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
- const shouldShow = isStarted && isAnimationPlaying && currentDialogue && !showHistory && !showChoices && !showLoopConfirm;
5479
- console.log("[MMDVisualNovel] DialogueBox render condition:", {
5480
- isStarted,
5481
- isAnimationPlaying,
5482
- hasDialogue: !!currentDialogue,
5483
- showHistory,
5484
- showChoices,
5485
- showLoopConfirm,
5486
- shouldShow,
5487
- dialogue: currentDialogue
5488
- });
5489
- return shouldShow ? /* @__PURE__ */ React10.createElement(
5490
- DialogueBox,
5491
- {
5492
- dialogue: currentDialogue,
5493
- theme: dialogueTheme,
5494
- isTyping,
5495
- isAutoMode,
5496
- onClick: handleDialogueClick,
5497
- onSkipTyping: () => {
5498
- typingCompleteRef.current = true;
5499
- },
5500
- onToggleAuto: toggleAutoMode,
5501
- onOpenHistory: () => setShowHistory(true),
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
- console.log("[MMDVisualNovel] Variable set: " + key + " = " + value);
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
- ...node,
5709
- resources: {
5710
- ...node.resources,
5711
- // 覆盖人物模型路径
5712
- modelPath: selectedCharacterPath,
5713
- // 覆盖场景模型路径
5714
- stageModelPath: selectedStagePath
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
- if (typeof window !== "undefined") {
6302
- window.THREE = THREE2;
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 MMDARPlayer = forwardRef(({
6305
- width = 800,
6306
- height = 600,
6307
- onReady,
6308
- onError
6309
- }, ref) => {
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 modelRef = useRef();
6321
- const [state, setState] = useState({
6322
- isLoading: true,
6323
- cameraReady: false,
6324
- arReady: false,
6325
- error: null,
6326
- showSettings: false,
6327
- modelPlaced: false,
6328
- markerDetected: false,
6329
- selectedModel: "sphere",
6330
- selectedMotion: "idle",
6331
- selectedAudio: "none",
6332
- cameraFacing: "environment",
6333
- markerType: "barcode",
6334
- showWireframe: false,
6335
- lightingEnabled: true,
6336
- quality: "medium"
6337
- });
6338
- const gyroDataRef = useRef({ alpha: 0, beta: 0, gamma: 0 });
6339
- const initializeThreeJS = useCallback(() => {
6340
- try {
6341
- const scene = new THREE2.Scene();
6342
- sceneRef.current = scene;
6343
- const camera = new THREE2.Camera();
6344
- cameraRef.current = camera;
6345
- scene.add(camera);
6346
- const renderer = new THREE2.WebGLRenderer({
6347
- canvas: canvasRef.current,
6348
- antialias: true,
6349
- alpha: true
6350
- });
6351
- renderer.setSize(width, height);
6352
- renderer.setClearColor(0, 0);
6353
- rendererRef.current = renderer;
6354
- console.log("Three.js initialized successfully");
6355
- return true;
6356
- } catch (error) {
6357
- console.error("Failed to initialize Three.js:", error);
6358
- setState((prev) => ({ ...prev, error: "Three.js \u521D\u59CB\u5316\u5931\u8D25" }));
6359
- return false;
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
- }, [width, height]);
6362
- const requestCameraPermission = useCallback(async () => {
6363
- try {
6364
- console.log("Checking camera support...");
6365
- if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
6366
- throw new Error("\u60A8\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u6444\u50CF\u5934\u8BBF\u95EE");
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
- console.log("Camera API supported, checking permissions...");
6369
- if (navigator.permissions) {
6370
- try {
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
- console.log("Requesting camera access...");
6386
- const cameraPromise = navigator.mediaDevices.getUserMedia({
6387
- video: {
6388
- width: { ideal: width },
6389
- height: { ideal: height },
6390
- facingMode: "environment"
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
- const timeoutPromise = new Promise((_, reject) => {
6395
- setTimeout(() => reject(new Error("Camera access timeout - \u8BF7\u68C0\u67E5\u6444\u50CF\u5934\u6743\u9650")), 1e4);
6396
- });
6397
- const testStream = await Promise.race([cameraPromise, timeoutPromise]);
6398
- console.log("Camera access granted, stopping test stream...");
6399
- testStream.getTracks().forEach((track) => track.stop());
6400
- console.log("Camera permission granted successfully");
6401
- return true;
6402
- } catch (error) {
6403
- console.error("Camera permission denied:", error);
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 placeModel = useCallback(() => {
6456
- if (!markerRootRef.current || !modelRootRef.current || !sceneRef.current) {
6457
- console.error("Cannot place model: missing required references");
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
- if (modelRef.current) {
6462
- modelRootRef.current.remove(modelRef.current);
6463
- }
6464
- const model = createModel(state.selectedModel);
6465
- modelRef.current = model;
6466
- modelRootRef.current.position.copy(markerRootRef.current.position);
6467
- modelRootRef.current.quaternion.copy(markerRootRef.current.quaternion);
6468
- modelRootRef.current.add(model);
6469
- modelRootRef.current.visible = true;
6470
- setState((prev) => ({ ...prev, modelPlaced: true }));
6471
- console.log("Model placed successfully at marker position");
6472
- } catch (error) {
6473
- console.error("Failed to place model:", error);
6474
- setState((prev) => ({ ...prev, error: "\u653E\u7F6E\u6A21\u578B\u5931\u8D25" }));
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
- }, [state.selectedModel, createModel]);
6477
- const handleARSettingChange = useCallback((setting, value) => {
6478
- setState((prev) => ({ ...prev, [setting]: value }));
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
- const takePhoto = useCallback(() => {
6486
- if (!rendererRef.current || !sceneRef.current || !cameraRef.current) {
6487
- console.error("Cannot take photo: missing required references");
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
- try {
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
- throw new Error("Cannot create canvas context");
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
- rendererRef.current.render(sceneRef.current, cameraRef.current);
6499
- const rendererCanvas = rendererRef.current.domElement;
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
- canvas.toBlob((blob) => {
6507
- if (blob) {
6508
- const url = URL.createObjectURL(blob);
6509
- const a = document.createElement("a");
6510
- a.href = url;
6511
- a.download = "ar-photo-" + Date.now() + ".png";
6512
- document.body.appendChild(a);
6513
- a.click();
6514
- document.body.removeChild(a);
6515
- URL.revokeObjectURL(url);
6516
- console.log("Photo saved successfully");
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
- console.log("Getting THREEx...");
6544
- const THREEx = window.THREEx;
6545
- if (!THREEx) {
6546
- console.error("THREEx not found, available window properties:", Object.keys(window).filter((key) => key.toLowerCase().includes("ar") || key.toLowerCase().includes("three")));
6547
- throw new Error("THREEx not found after AR.js loaded");
6548
- }
6549
- console.log("THREEx loaded successfully:", Object.keys(THREEx));
6550
- console.log("THREEx loaded, requesting camera permission...");
6551
- const hasPermission = await requestCameraPermission();
6552
- if (!hasPermission) {
6553
- console.log("Camera permission denied");
6554
- return false;
6555
- }
6556
- console.log("Camera permission granted, initializing AR Toolkit Source...");
6557
- const arToolkitSource = new THREEx.ArToolkitSource({
6558
- sourceType: "webcam",
6559
- sourceWidth: width,
6560
- sourceHeight: height,
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
- if (modelRef.current && state.modelPlaced) {
6649
- modelRef.current.rotation.y += 0.01;
7027
+ }, [cameraConfig?.facingMode, cameraFacing, cleanupAR, setupAR]);
7028
+ useEffect(() => {
7029
+ if (!modelPresets.find((preset) => preset.id === selectedModelId)) {
7030
+ setSelectedModelId(modelPresets[0]?.id ?? "");
6650
7031
  }
6651
- rendererRef.current.render(sceneRef.current, cameraRef.current);
6652
- }, [state.markerDetected]);
7032
+ }, [modelPresets, selectedModelId]);
6653
7033
  useEffect(() => {
6654
- const initialize = async () => {
6655
- try {
6656
- setState((prev) => ({ ...prev, isLoading: true, error: null }));
6657
- if (!initializeThreeJS()) return;
6658
- await initializeAR();
6659
- if (window.DeviceOrientationEvent) {
6660
- const handleOrientation = (event) => {
6661
- gyroDataRef.current = {
6662
- alpha: event.alpha || 0,
6663
- beta: event.beta || 0,
6664
- gamma: event.gamma || 0
6665
- };
6666
- if (state.modelPlaced && modelRef.current) {
6667
- }
6668
- };
6669
- window.addEventListener("deviceorientation", handleOrientation);
6670
- const cleanupGyro = () => {
6671
- window.removeEventListener("deviceorientation", handleOrientation);
6672
- };
6673
- window.__gyroCleanup = cleanupGyro;
6674
- }
6675
- render();
6676
- } catch (error) {
6677
- console.error("Initialization failed:", error);
6678
- setState((prev) => ({
6679
- ...prev,
6680
- error: "\u7EC4\u4EF6\u521D\u59CB\u5316\u5931\u8D25",
6681
- isLoading: false
6682
- }));
6683
- onError?.("\u7EC4\u4EF6\u521D\u59CB\u5316\u5931\u8D25");
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 (arToolkitSourceRef.current) {
6692
- if (arToolkitSourceRef.current.domElement?.srcObject) {
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 (window.__gyroCleanup) {
6699
- window.__gyroCleanup();
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
- }, [initializeThreeJS, initializeAR, render, onError]);
6703
- return /* @__PURE__ */ React10.createElement("div", { ref: containerRef, className: "relative w-full h-full bg-gray-900 overflow-hidden" }, /* @__PURE__ */ React10.createElement(
6704
- Script,
6705
- {
6706
- src: "https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js",
6707
- strategy: "afterInteractive",
6708
- onLoad: () => {
6709
- console.log("AR.js script loaded, checking THREEx...");
6710
- const checkTHREEx = () => {
6711
- if (window.THREEx) {
6712
- console.log("THREEx found! Properties:", Object.keys(window.THREEx));
6713
- window.__arjs_ready = true;
6714
- console.log("AR.js and THREEx ready!");
6715
- } else {
6716
- console.log("THREEx not ready yet, checking window object:", Object.keys(window).filter((key) => key.includes("THREEx") || key.includes("AR")));
6717
- setTimeout(checkTHREEx, 100);
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
- value: state.selectedAudio,
6813
- onChange: (e) => setState((prev) => ({ ...prev, selectedAudio: e.target.value })),
6814
- className: "w-full px-3 py-2 bg-gray-700 rounded border border-gray-600 text-sm"
7108
+ ref: containerRef,
7109
+ className: clsx("relative w-full h-full overflow-hidden bg-black", className),
7110
+ style
6815
7111
  },
6816
- /* @__PURE__ */ React10.createElement("option", { value: "none" }, "\u{1F507} \u65E0\u97F3\u4E50"),
6817
- /* @__PURE__ */ React10.createElement("option", { value: "bgm1" }, "\u{1F3B5} \u80CC\u666F\u97F3\u4E50 1"),
6818
- /* @__PURE__ */ React10.createElement("option", { value: "bgm2" }, "\u{1F3B6} \u80CC\u666F\u97F3\u4E50 2")
6819
- )))), /* @__PURE__ */ React10.createElement("div", null, /* @__PURE__ */ React10.createElement("h4", { className: "font-semibold mb-2 text-red-300" }, "\u{1F3AE} \u63A7\u5236\u64CD\u4F5C"), /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React10.createElement(
6820
- "button",
6821
- {
6822
- onClick: () => {
6823
- if (modelRootRef.current) {
6824
- modelRootRef.current.visible = false;
6825
- }
6826
- if (markerRootRef.current) {
6827
- markerRootRef.current.visible = true;
6828
- }
6829
- setState((prev) => ({ ...prev, modelPlaced: false, markerDetected: false }));
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
- className: "w-full px-3 py-2 bg-blue-600 hover:bg-blue-700 rounded transition-colors text-sm"
6832
- },
6833
- "\u{1F504} \u91CD\u65B0\u8BBE\u7F6E\u6807\u8BB0\u70B9"
6834
- ), /* @__PURE__ */ React10.createElement(
6835
- "button",
6836
- {
6837
- onClick: () => {
6838
- if (modelRootRef.current) {
6839
- modelRootRef.current.clear();
6840
- modelRootRef.current.visible = false;
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
- className: "w-full px-3 py-2 bg-red-600 hover:bg-red-700 rounded transition-colors text-sm"
6855
- },
6856
- "\u{1F5D1}\uFE0F \u6E05\u9664\u6240\u6709"
6857
- ))))), /* @__PURE__ */ React10.createElement("div", { className: "absolute bottom-4 left-4 right-4 flex justify-center space-x-4" }, /* @__PURE__ */ React10.createElement(
6858
- "button",
6859
- {
6860
- onClick: () => setState((prev) => ({ ...prev, showSettings: !prev.showSettings })),
6861
- className: "px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-lg transition-colors"
6862
- },
6863
- "\u2699\uFE0F \u8BBE\u7F6E"
6864
- ), !state.modelPlaced && /* @__PURE__ */ React10.createElement(
6865
- "button",
6866
- {
6867
- onClick: placeModel,
6868
- disabled: !state.markerDetected,
6869
- className: clsx("px-6 py-2 rounded-lg transition-colors", state.markerDetected ? "bg-green-600 hover:bg-green-700 text-white" : "bg-gray-500 text-gray-300 cursor-not-allowed")
6870
- },
6871
- "\u{1F4CD} \u653E\u7F6E\u6A21\u578B"
6872
- ), state.modelPlaced && /* @__PURE__ */ React10.createElement(
6873
- "button",
6874
- {
6875
- onClick: takePhoto,
6876
- className: "px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
6877
- },
6878
- "\u{1F4F8} \u62CD\u7167"
6879
- )), /* @__PURE__ */ React10.createElement("div", { className: "absolute top-4 right-4 flex space-x-2" }, /* @__PURE__ */ React10.createElement("div", { className: clsx("w-3 h-3 rounded-full", state.cameraReady ? "bg-green-400" : "bg-red-400"), title: "\u6444\u50CF\u5934" }), /* @__PURE__ */ React10.createElement("div", { className: clsx("w-3 h-3 rounded-full", state.arReady ? "bg-green-400" : "bg-red-400"), title: "AR" }), /* @__PURE__ */ React10.createElement("div", { className: clsx("w-3 h-3 rounded-full", window.DeviceOrientationEvent ? "bg-purple-400" : "bg-gray-400"), title: "\u9640\u87BA\u4EEA" }), /* @__PURE__ */ React10.createElement("div", { className: clsx("w-3 h-3 rounded-full", state.markerDetected ? "bg-blue-400" : "bg-gray-400"), title: "\u6807\u8BB0\u68C0\u6D4B" }), /* @__PURE__ */ React10.createElement("div", { className: clsx("w-3 h-3 rounded-full", state.modelPlaced && modelRootRef.current?.visible ? "bg-green-400" : "bg-yellow-400"), title: "\u6A21\u578B" }))));
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
- MMDARPlayer.displayName = "MMDARPlayer";
7225
+ MMDARApp.displayName = "MMDARApp";
6882
7226
 
6883
- // src/mmd/ar/types.ts
6884
- var ARMode = /* @__PURE__ */ ((ARMode2) => {
6885
- ARMode2["Overlay"] = "overlay";
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