sa2kit 1.6.2 → 1.6.3

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 (50) hide show
  1. package/dist/audioDetection/index.js.map +1 -1
  2. package/dist/audioDetection/index.mjs.map +1 -1
  3. package/dist/{chunk-5XUE72Y3.mjs → chunk-6LEA37ZM.mjs} +2 -2
  4. package/dist/{chunk-5XUE72Y3.mjs.map → chunk-6LEA37ZM.mjs.map} +1 -1
  5. package/dist/chunk-EBP7AE6F.js +167 -0
  6. package/dist/chunk-EBP7AE6F.js.map +1 -0
  7. package/dist/chunk-MBG4DBGP.mjs +154 -0
  8. package/dist/chunk-MBG4DBGP.mjs.map +1 -0
  9. package/dist/{chunk-DQVPZTVC.js → chunk-QKXKXAAV.js} +2 -2
  10. package/dist/{chunk-DQVPZTVC.js.map → chunk-QKXKXAAV.js.map} +1 -1
  11. package/dist/imageCrop/index.js.map +1 -1
  12. package/dist/imageCrop/index.mjs.map +1 -1
  13. package/dist/index-DtLpANUB.d.mts +70 -0
  14. package/dist/index-DtLpANUB.d.ts +70 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/mmd/admin/index.d.mts +1 -1
  18. package/dist/mmd/admin/index.d.ts +1 -1
  19. package/dist/mmd/index.d.mts +16 -2
  20. package/dist/mmd/index.d.ts +16 -2
  21. package/dist/mmd/index.js +280 -130
  22. package/dist/mmd/index.js.map +1 -1
  23. package/dist/mmd/index.mjs +280 -130
  24. package/dist/mmd/index.mjs.map +1 -1
  25. package/dist/mmd/server/index.d.mts +1 -1
  26. package/dist/mmd/server/index.d.ts +1 -1
  27. package/dist/music/index.d.mts +30 -0
  28. package/dist/music/index.d.ts +30 -0
  29. package/dist/music/index.js +458 -0
  30. package/dist/music/index.js.map +1 -0
  31. package/dist/music/index.mjs +427 -0
  32. package/dist/music/index.mjs.map +1 -0
  33. package/dist/music/server/index.d.mts +1 -0
  34. package/dist/music/server/index.d.ts +1 -0
  35. package/dist/music/server/index.js +29 -0
  36. package/dist/music/server/index.js.map +1 -0
  37. package/dist/music/server/index.mjs +4 -0
  38. package/dist/music/server/index.mjs.map +1 -0
  39. package/dist/testYourself/admin/index.js +3 -3
  40. package/dist/testYourself/admin/index.mjs +1 -1
  41. package/dist/testYourself/index.js +7 -7
  42. package/dist/testYourself/index.js.map +1 -1
  43. package/dist/testYourself/index.mjs +2 -2
  44. package/dist/testYourself/index.mjs.map +1 -1
  45. package/dist/{types-DxYJqqes.d.mts → types-B60F7EZZ.d.mts} +16 -1
  46. package/dist/{types-DxYJqqes.d.ts → types-B60F7EZZ.d.ts} +16 -1
  47. package/dist/universalFile/server/index.js +5 -5
  48. package/dist/universalFile/server/index.mjs +1 -1
  49. package/package.json +32 -19
  50. package/tailwind.animations.js +5 -0
package/dist/mmd/index.js CHANGED
@@ -224,6 +224,7 @@ var MMDPlayerBase = React6.forwardRef((props, ref) => {
224
224
  const renderEffect = props.renderEffect || stage.renderEffect || "default";
225
225
  const outlineOptions = { ...stage.outlineOptions, ...props.outlineOptions };
226
226
  const bloomOptions = { ...stage.bloomOptions, ...props.bloomOptions };
227
+ const toonOptions = { ...stage.toonOptions, ...props.toonOptions };
227
228
  const containerRef = React6.useRef(null);
228
229
  const sceneRef = React6.useRef(null);
229
230
  const cameraRef = React6.useRef(null);
@@ -421,6 +422,11 @@ var MMDPlayerBase = React6.forwardRef((props, ref) => {
421
422
  const pixelRatio = mobileOptimization.enabled ? mobileOptimization.pixelRatio || Math.min(window.devicePixelRatio, 2) : window.devicePixelRatio;
422
423
  renderer.setPixelRatio(pixelRatio);
423
424
  console.log("[MMDPlayerBase] Pixel ratio set to:", pixelRatio);
425
+ if (renderEffect.includes("outline") || toonOptions.enabled) {
426
+ renderer.toneMapping = THREE__namespace.NoToneMapping;
427
+ } else {
428
+ renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping;
429
+ }
424
430
  if (checkCancelled()) {
425
431
  renderer.dispose();
426
432
  return;
@@ -588,6 +594,41 @@ var MMDPlayerBase = React6.forwardRef((props, ref) => {
588
594
  }
589
595
  }
590
596
  const enablePhysics = stage.enablePhysics !== false && !mobileOptimization.disablePhysics;
597
+ mesh.traverse((obj) => {
598
+ if (obj instanceof THREE__namespace.Mesh || obj instanceof THREE__namespace.SkinnedMesh) {
599
+ const materials = Array.isArray(obj.material) ? obj.material : [obj.material];
600
+ materials.forEach((m) => {
601
+ if (!m.userData) m.userData = {};
602
+ if (!m.userData.outlineParameters) {
603
+ m.userData.outlineParameters = {
604
+ thickness: outlineOptions.thickness ?? 3e-3,
605
+ color: new THREE__namespace.Color(outlineOptions.color ?? "#000000").toArray(),
606
+ alpha: 1,
607
+ visible: true,
608
+ keepAlive: true
609
+ };
610
+ } else {
611
+ if (outlineOptions.thickness !== void 0) {
612
+ m.userData.outlineParameters.thickness = outlineOptions.thickness;
613
+ }
614
+ if (outlineOptions.color !== void 0) {
615
+ m.userData.outlineParameters.color = new THREE__namespace.Color(outlineOptions.color).toArray();
616
+ }
617
+ }
618
+ if (m instanceof THREE__namespace.MeshPhongMaterial) {
619
+ if (toonOptions.enabled !== false && (toonOptions.enabled || renderEffect.includes("outline"))) {
620
+ m.shininess = toonOptions.shininess ?? 0;
621
+ m.specular.setScalar(0);
622
+ if (toonOptions.forceHardShading && m.toonMap) {
623
+ m.toonMap.magFilter = THREE__namespace.NearestFilter;
624
+ m.toonMap.minFilter = THREE__namespace.NearestFilter;
625
+ m.toonMap.needsUpdate = true;
626
+ }
627
+ }
628
+ }
629
+ });
630
+ }
631
+ });
591
632
  helper.add(mesh, {
592
633
  animation,
593
634
  physics: enablePhysics
@@ -717,6 +758,22 @@ var MMDPlayerBase = React6.forwardRef((props, ref) => {
717
758
  if (mesh2.morphTargetInfluences) {
718
759
  mesh2.morphTargetInfluences = [];
719
760
  }
761
+ materials.forEach((m) => {
762
+ if (!m.userData) m.userData = {};
763
+ m.userData.outlineParameters = {
764
+ thickness: outlineOptions.thickness ?? 3e-3,
765
+ color: new THREE__namespace.Color(outlineOptions.color ?? "#000000").toArray(),
766
+ alpha: 1,
767
+ visible: true,
768
+ keepAlive: true
769
+ };
770
+ if (m instanceof THREE__namespace.MeshPhongMaterial) {
771
+ if (toonOptions.enabled !== false && (toonOptions.enabled || renderEffect.includes("outline"))) {
772
+ m.shininess = toonOptions.shininess ?? 0;
773
+ m.specular.setScalar(0);
774
+ }
775
+ }
776
+ });
720
777
  }
721
778
  });
722
779
  try {
@@ -1192,7 +1249,27 @@ ${errorMessage}
1192
1249
  }
1193
1250
  }, [loop]);
1194
1251
  React6.useEffect(() => {
1195
- if (outlineEffectRef.current) ;
1252
+ if (outlineEffectRef.current) {
1253
+ outlineEffectRef.current.defaultThickness = outlineOptions.thickness ?? 3e-3;
1254
+ outlineEffectRef.current.defaultColor = new THREE__namespace.Color(outlineOptions.color ?? "#000000").toArray();
1255
+ if (sceneRef.current) {
1256
+ sceneRef.current.traverse((obj) => {
1257
+ if (obj instanceof THREE__namespace.Mesh || obj instanceof THREE__namespace.SkinnedMesh) {
1258
+ const materials = Array.isArray(obj.material) ? obj.material : [obj.material];
1259
+ materials.forEach((m) => {
1260
+ if (m.userData && m.userData.outlineParameters) {
1261
+ if (outlineOptions.thickness !== void 0) {
1262
+ m.userData.outlineParameters.thickness = outlineOptions.thickness;
1263
+ }
1264
+ if (outlineOptions.color !== void 0) {
1265
+ m.userData.outlineParameters.color = new THREE__namespace.Color(outlineOptions.color).toArray();
1266
+ }
1267
+ }
1268
+ });
1269
+ }
1270
+ });
1271
+ }
1272
+ }
1196
1273
  if (composerRef.current) {
1197
1274
  const bloomPass = composerRef.current.passes.find((p) => p instanceof threeStdlib.UnrealBloomPass);
1198
1275
  if (bloomPass) {
@@ -1201,7 +1278,28 @@ ${errorMessage}
1201
1278
  bloomPass.threshold = bloomOptions.threshold ?? 0.8;
1202
1279
  }
1203
1280
  }
1204
- }, [bloomOptions.strength, bloomOptions.radius, bloomOptions.threshold]);
1281
+ }, [outlineOptions.thickness, outlineOptions.color, bloomOptions.strength, bloomOptions.radius, bloomOptions.threshold]);
1282
+ React6.useEffect(() => {
1283
+ if (!sceneRef.current) return;
1284
+ sceneRef.current.traverse((obj) => {
1285
+ if (obj instanceof THREE__namespace.Mesh || obj instanceof THREE__namespace.SkinnedMesh) {
1286
+ const materials = Array.isArray(obj.material) ? obj.material : [obj.material];
1287
+ materials.forEach((m) => {
1288
+ if (m instanceof THREE__namespace.MeshPhongMaterial) {
1289
+ if (toonOptions.enabled !== false && (toonOptions.enabled || renderEffect.includes("outline"))) {
1290
+ m.shininess = toonOptions.shininess ?? 0;
1291
+ m.specular.setScalar(0);
1292
+ if (toonOptions.forceHardShading && m.toonMap) {
1293
+ m.toonMap.magFilter = THREE__namespace.NearestFilter;
1294
+ m.toonMap.minFilter = THREE__namespace.NearestFilter;
1295
+ m.toonMap.needsUpdate = true;
1296
+ }
1297
+ }
1298
+ }
1299
+ });
1300
+ }
1301
+ });
1302
+ }, [toonOptions.enabled, toonOptions.shininess, toonOptions.forceHardShading, renderEffect]);
1205
1303
  React6.useEffect(() => {
1206
1304
  if (!isReadyRef.current) return;
1207
1305
  if (sceneRef.current) {
@@ -2610,164 +2708,207 @@ var LoadingScreen = ({
2610
2708
  return reactDom.createPortal(content, portalContainer);
2611
2709
  };
2612
2710
  LoadingScreen.displayName = "LoadingScreen";
2711
+ var VNModal = ({ title, show, onClose, children }) => {
2712
+ if (!show) return null;
2713
+ return /* @__PURE__ */ React6__default.default.createElement(
2714
+ "div",
2715
+ {
2716
+ className: "fixed inset-0 flex items-center justify-center bg-black/40 backdrop-blur-xl z-[1000000] pointer-events-auto transition-all animate-in fade-in zoom-in-95 duration-300",
2717
+ onClick: onClose
2718
+ },
2719
+ /* @__PURE__ */ React6__default.default.createElement(
2720
+ "div",
2721
+ {
2722
+ className: "w-full max-w-lg mx-4 p-8 rounded-[2.5rem] border border-white/40 shadow-[0_20px_80px_rgba(0,0,0,0.4)] relative overflow-hidden",
2723
+ style: {
2724
+ background: "linear-gradient(135deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.15))",
2725
+ backdropFilter: "blur(40px) saturate(200%)",
2726
+ WebkitBackdropFilter: "blur(40px) saturate(200%)"
2727
+ },
2728
+ onClick: (e) => e.stopPropagation()
2729
+ },
2730
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute -top-24 -right-24 w-64 h-64 bg-cyan-400/20 rounded-full blur-3xl pointer-events-none" }),
2731
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute -bottom-24 -left-24 w-64 h-64 bg-pink-400/20 rounded-full blur-3xl pointer-events-none" }),
2732
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex items-center justify-between mb-8 relative" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React6__default.default.createElement("h2", { className: "text-2xl font-bold text-white tracking-wider drop-shadow-lg" }, title), /* @__PURE__ */ React6__default.default.createElement("div", { className: "h-1.5 w-16 bg-white/60 rounded-full mt-2 shadow-[0_0_10px_rgba(255,255,255,0.5)]" })), /* @__PURE__ */ React6__default.default.createElement(
2733
+ "button",
2734
+ {
2735
+ onClick: onClose,
2736
+ className: "w-12 h-12 rounded-full flex items-center justify-center bg-white/10 hover:bg-white/30 text-white transition-all border border-white/20 shadow-inner"
2737
+ },
2738
+ "\u2715"
2739
+ )),
2740
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "text-white leading-relaxed max-h-[50vh] overflow-y-auto pr-4 custom-scrollbar relative font-medium" }, children),
2741
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "mt-10 flex justify-center relative" }, /* @__PURE__ */ React6__default.default.createElement(
2742
+ "button",
2743
+ {
2744
+ onClick: onClose,
2745
+ className: "px-14 py-3.5 rounded-2xl bg-white/20 hover:bg-white/40 text-white font-bold transition-all border border-white/50 shadow-[0_0_20px_rgba(255,255,255,0.2)] hover:scale-105 active:scale-95 tracking-[0.2em] uppercase text-sm"
2746
+ },
2747
+ "Confirm"
2748
+ ))
2749
+ )
2750
+ );
2751
+ };
2613
2752
  var StartScreen = ({
2614
2753
  showStartScreen = false,
2615
2754
  scriptName = "",
2616
- startText = "\u70B9\u51FB\u5F00\u59CB",
2755
+ startText = "\u5F00\u59CB\u6E38\u620F",
2756
+ settingsText = "\u6E38\u620F\u8BBE\u7F6E",
2757
+ aboutText = "\u5173\u4E8E\u4F5C\u54C1",
2617
2758
  onStart,
2618
2759
  className = ""
2619
2760
  }) => {
2620
2761
  const [isMounted, setIsMounted] = React6.useState(false);
2762
+ const [showSettings, setShowSettings] = React6.useState(false);
2763
+ const [showAbout, setShowAbout] = React6.useState(false);
2621
2764
  React6.useEffect(() => {
2622
2765
  setIsMounted(true);
2623
2766
  }, []);
2624
- console.log("[StartScreen] Render state:", {
2625
- showStartScreen,
2626
- scriptName,
2627
- isMounted
2628
- });
2629
- if (!isMounted) {
2630
- return null;
2631
- }
2632
- if (!showStartScreen) {
2633
- console.log("[StartScreen] Not showing, returning null");
2634
- return null;
2635
- }
2767
+ if (!isMounted) return null;
2768
+ if (!showStartScreen) return null;
2636
2769
  const content = /* @__PURE__ */ React6__default.default.createElement(
2637
2770
  "div",
2638
2771
  {
2639
- className: `fixed inset-0 w-screen h-screen flex items-center justify-center cursor-pointer ${className}`,
2772
+ className: `fixed inset-0 w-screen h-screen flex items-center justify-center overflow-hidden ${className}`,
2640
2773
  style: {
2641
2774
  zIndex: 999999,
2642
2775
  pointerEvents: "auto",
2643
- backgroundColor: "rgba(0, 0, 0, 0.5)",
2776
+ backgroundColor: "#050505",
2644
2777
  margin: 0,
2645
2778
  padding: 0
2646
- },
2647
- onClick: onStart
2779
+ }
2648
2780
  },
2649
- /* @__PURE__ */ React6__default.default.createElement(
2781
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute inset-0 w-full h-full overflow-hidden" }, /* @__PURE__ */ React6__default.default.createElement(
2650
2782
  "div",
2651
2783
  {
2652
- className: "absolute inset-0 w-full h-full pointer-events-none",
2784
+ className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[150vw] h-[150vw] opacity-40 pointer-events-none",
2653
2785
  style: {
2654
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.15))",
2655
- backdropFilter: "blur(40px) saturate(200%)",
2656
- WebkitBackdropFilter: "blur(40px) saturate(200%)"
2786
+ background: "radial-gradient(circle at center, rgba(57, 197, 187, 0.4) 0%, rgba(255, 182, 193, 0.2) 30%, transparent 70%)",
2787
+ filter: "blur(60px)",
2788
+ animation: "pulse 10s ease-in-out infinite"
2789
+ }
2790
+ }
2791
+ ), /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute inset-0 transition-opacity duration-1000" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute top-[-10%] left-[-10%] w-[60%] h-[60%] bg-cyan-500/10 rounded-full blur-[120px] animate-blob" }), /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute bottom-[-10%] right-[-10%] w-[60%] h-[60%] bg-purple-500/10 rounded-full blur-[120px] animate-blob animation-delay-2000" }), /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute top-[20%] right-[10%] w-[40%] h-[40%] bg-pink-500/10 rounded-full blur-[100px] animate-blob animation-delay-4000" })), /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute inset-0 opacity-60" }, [...Array(40)].map((_, i) => /* @__PURE__ */ React6__default.default.createElement(
2792
+ "div",
2793
+ {
2794
+ key: i,
2795
+ className: "absolute bg-white/40 rounded-full",
2796
+ style: {
2797
+ width: Math.random() * 3 + 1 + "px",
2798
+ height: Math.random() * 3 + 1 + "px",
2799
+ top: Math.random() * 100 + "%",
2800
+ left: Math.random() * 100 + "%",
2801
+ boxShadow: "0 0 10px rgba(255,255,255,0.5)",
2802
+ animation: `floatParticle ${Math.random() * 10 + 10}s linear infinite`,
2803
+ animationDelay: `-${Math.random() * 20}s`
2804
+ }
2805
+ }
2806
+ )))),
2807
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "relative z-10 w-full max-w-5xl mx-auto px-6 flex flex-col items-center" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "text-center mb-20 md:mb-32 group flex flex-col items-center" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "w-40 h-px bg-gradient-to-r from-transparent via-white/60 to-transparent mb-10 shadow-[0_0_15px_rgba(255,255,255,0.5)]" }), /* @__PURE__ */ React6__default.default.createElement(
2808
+ "h1",
2809
+ {
2810
+ className: "text-6xl md:text-8xl font-black text-white tracking-[0.15em] leading-tight select-none",
2811
+ style: {
2812
+ filter: "drop-shadow(0 0 20px rgba(255,255,255,0.3))",
2813
+ textShadow: "0 10px 30px rgba(0,0,0,0.5)"
2657
2814
  }
2658
2815
  },
2816
+ scriptName || "VISUAL NOVEL"
2817
+ ), /* @__PURE__ */ React6__default.default.createElement("div", { className: "mt-10 flex flex-col items-center gap-4" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "h-1 w-32 bg-white rounded-full opacity-80 shadow-[0_0_20px_rgba(255,255,255,0.8)]" }), /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-sm md:text-base tracking-[0.8em] text-white/60 font-medium uppercase translate-x-[0.4em]" }, "Adventure System"))), /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex flex-col gap-10 items-center w-full max-w-sm" }, /* @__PURE__ */ React6__default.default.createElement(
2818
+ "button",
2819
+ {
2820
+ onClick: onStart,
2821
+ className: "group relative w-full h-20 flex items-center justify-center transition-all duration-500 active:scale-95"
2822
+ },
2659
2823
  /* @__PURE__ */ React6__default.default.createElement(
2660
2824
  "div",
2661
2825
  {
2662
- className: "flex items-center justify-center flex-col inset-0 w-full h-full pointer-events-none",
2663
- style: {
2664
- background: `linear-gradient(45deg,
2665
- rgba(255, 182, 193, 0.25) 0%,
2666
- rgba(173, 216, 230, 0.25) 25%,
2667
- rgba(221, 160, 221, 0.25) 50%,
2668
- rgba(255, 218, 185, 0.25) 75%,
2669
- rgba(255, 182, 193, 0.25) 100%)`,
2670
- backgroundSize: "400% 400%",
2671
- animation: "gradientShift 15s ease infinite"
2672
- }
2673
- },
2674
- /* @__PURE__ */ React6__default.default.createElement(
2675
- "div",
2676
- {
2677
- className: "relative z-10 text-center px-16 py-14 rounded-3xl max-w-2xl mx-auto transform transition-all hover:scale-105",
2678
- style: {
2679
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.15))",
2680
- backdropFilter: "blur(24px)",
2681
- WebkitBackdropFilter: "blur(24px)",
2682
- border: "2px solid rgba(255, 255, 255, 0.3)",
2683
- boxShadow: `
2684
- 0 12px 48px rgba(255, 255, 255, 0.15),
2685
- 0 4px 16px rgba(255, 255, 255, 0.1),
2686
- inset 0 1px 0 rgba(255, 255, 255, 0.4)
2687
- `
2688
- }
2689
- },
2690
- /* @__PURE__ */ React6__default.default.createElement(
2691
- "div",
2692
- {
2693
- className: "absolute top-0 left-0 right-0 h-1 margin-auto",
2694
- style: {
2695
- background: "linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent)"
2696
- }
2697
- }
2698
- ),
2699
- /* @__PURE__ */ React6__default.default.createElement(
2700
- "h1",
2701
- {
2702
- className: "text-5xl font-bold text-white mb-8 relative",
2703
- style: {
2704
- textShadow: "0 4px 16px rgba(255, 255, 255, 0.3), 0 2px 8px rgba(0, 0, 0, 0.5)"
2705
- }
2706
- },
2707
- scriptName,
2708
- /* @__PURE__ */ React6__default.default.createElement(
2709
- "div",
2710
- {
2711
- className: "absolute -bottom-3 left-1/2 transform -translate-x-1/2 h-1 rounded-full",
2712
- style: {
2713
- width: "60%",
2714
- background: "linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent)"
2715
- }
2716
- }
2717
- )
2718
- ),
2719
- /* @__PURE__ */ React6__default.default.createElement(
2720
- "div",
2721
- {
2722
- className: "inline-block px-10 py-4 rounded-2xl font-bold text-xl text-white transition-all hover:scale-110 active:scale-95",
2723
- style: {
2724
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.25))",
2725
- backdropFilter: "blur(16px)",
2726
- WebkitBackdropFilter: "blur(16px)",
2727
- border: "2px solid rgba(255, 255, 255, 0.4)",
2728
- boxShadow: `
2729
- 0 8px 32px rgba(255, 255, 255, 0.2),
2730
- inset 0 1px 0 rgba(255, 255, 255, 0.5)
2731
- `,
2732
- textShadow: "0 2px 8px rgba(0, 0, 0, 0.3)",
2733
- animation: "pulse 2s ease-in-out infinite"
2734
- }
2735
- },
2736
- /* @__PURE__ */ React6__default.default.createElement("span", { className: "relative z-10" }, startText)
2737
- ),
2738
- /* @__PURE__ */ React6__default.default.createElement(
2739
- "div",
2740
- {
2741
- className: "absolute bottom-0 left-0 right-0 h-px",
2742
- style: {
2743
- background: "linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent)"
2744
- }
2745
- }
2746
- )
2747
- )
2748
- )
2749
- )
2826
+ className: "absolute inset-0 bg-white/10 backdrop-blur-2xl border-2 border-white/40 rounded-3xl transition-all duration-500 group-hover:bg-white/25 group-hover:border-white/70 group-hover:shadow-[0_0_50px_rgba(255,255,255,0.3)] group-hover:-inset-1"
2827
+ }
2828
+ ),
2829
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute inset-0 overflow-hidden rounded-3xl pointer-events-none" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-700 bg-gradient-to-r from-transparent via-white/20 to-transparent -skew-x-[25deg] -translate-x-[200%] group-hover:translate-x-[200%] transition-transform duration-1000 ease-in-out" })),
2830
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "relative flex items-center gap-6" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "w-3 h-3 rounded-full bg-cyan-400 animate-ping opacity-75" }), /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-2xl font-black text-white tracking-[0.4em] drop-shadow-md" }, startText), /* @__PURE__ */ React6__default.default.createElement("div", { className: "w-3 h-3 rounded-full bg-pink-400 animate-ping opacity-75" }))
2831
+ ), /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex gap-8 w-full justify-center" }, [
2832
+ { text: settingsText, onClick: () => setShowSettings(true), color: "rgba(57, 197, 187, 0.2)" },
2833
+ { text: aboutText, onClick: () => setShowAbout(true), color: "rgba(255, 182, 193, 0.2)" }
2834
+ ].map((btn, idx) => /* @__PURE__ */ React6__default.default.createElement(
2835
+ "button",
2836
+ {
2837
+ key: idx,
2838
+ onClick: btn.onClick,
2839
+ className: "group relative flex-1 h-14 flex items-center justify-center transition-all duration-300 active:scale-95 overflow-hidden rounded-2xl"
2840
+ },
2841
+ /* @__PURE__ */ React6__default.default.createElement(
2842
+ "div",
2843
+ {
2844
+ className: "absolute inset-0 bg-white/5 backdrop-blur-xl border border-white/20 transition-all duration-300 group-hover:bg-white/15 group-hover:border-white/40"
2845
+ }
2846
+ ),
2847
+ /* @__PURE__ */ React6__default.default.createElement(
2848
+ "div",
2849
+ {
2850
+ className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity",
2851
+ style: { background: btn.color }
2852
+ }
2853
+ ),
2854
+ /* @__PURE__ */ React6__default.default.createElement("span", { className: "relative text-sm md:text-base font-bold text-white/80 group-hover:text-white tracking-[0.25em] transition-colors uppercase" }, btn.text)
2855
+ ))))),
2856
+ /* @__PURE__ */ React6__default.default.createElement("div", { className: "fixed bottom-10 left-0 right-0 text-center pointer-events-none select-none" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "inline-block px-6 py-2 rounded-full bg-white/5 backdrop-blur-md border border-white/10" }, /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-[10px] md:text-xs text-white/30 tracking-[0.5em] font-light uppercase" }, "Ver 1.6.2 \u2014 ENGINE POWERED BY SA2KIT"))),
2857
+ /* @__PURE__ */ React6__default.default.createElement(VNModal, { title: settingsText, show: showSettings, onClose: () => setShowSettings(false) }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "space-y-8 py-4" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex justify-between items-center text-sm font-bold tracking-widest text-white/60" }, /* @__PURE__ */ React6__default.default.createElement("span", null, "MUSIC VOLUME"), /* @__PURE__ */ React6__default.default.createElement("span", null, "80%")), /* @__PURE__ */ React6__default.default.createElement("div", { className: "h-3 bg-white/10 rounded-full p-0.5 border border-white/10" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "h-full w-[80%] bg-gradient-to-r from-cyan-400 to-blue-500 rounded-full shadow-[0_0_15px_rgba(34,211,238,0.5)]" }))), /* @__PURE__ */ React6__default.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex justify-between items-center text-sm font-bold tracking-widest text-white/60" }, /* @__PURE__ */ React6__default.default.createElement("span", null, "TEXT SPEED"), /* @__PURE__ */ React6__default.default.createElement("span", null, "NORMAL")), /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex gap-3" }, ["SLOW", "NORMAL", "FAST"].map((s, i) => /* @__PURE__ */ React6__default.default.createElement("div", { key: s, className: `flex-1 py-3 rounded-xl border text-center text-xs font-bold transition-all cursor-pointer ${i === 1 ? "bg-white/20 border-white/60 text-white" : "bg-white/5 border-white/10 text-white/40 hover:bg-white/10 hover:border-white/30"}` }, s)))), /* @__PURE__ */ React6__default.default.createElement("div", { className: "pt-4 flex items-center justify-between opacity-50 italic text-xs border-t border-white/10" }, /* @__PURE__ */ React6__default.default.createElement("span", null, "Auto Save Enabled"), /* @__PURE__ */ React6__default.default.createElement("span", null, "Cloud Sync Active")))),
2858
+ /* @__PURE__ */ React6__default.default.createElement(VNModal, { title: aboutText, show: showAbout, onClose: () => setShowAbout(false) }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "space-y-8 py-4" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex items-center gap-6 p-6 rounded-3xl bg-white/5 border border-white/10" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "w-20 h-20 rounded-2xl bg-gradient-to-br from-cyan-400 via-blue-500 to-purple-600 flex items-center justify-center text-3xl font-black text-white shadow-[0_10px_30px_rgba(0,0,0,0.3)]" }, "S2"), /* @__PURE__ */ React6__default.default.createElement("div", null, /* @__PURE__ */ React6__default.default.createElement("h3", { className: "text-2xl font-black text-white tracking-tight" }, scriptName || "Project SA2"), /* @__PURE__ */ React6__default.default.createElement("p", { className: "text-xs font-bold text-white/40 tracking-widest mt-1 uppercase" }, "Visual Novel Experience"))), /* @__PURE__ */ React6__default.default.createElement("div", { className: "space-y-4 px-2" }, /* @__PURE__ */ React6__default.default.createElement("p", { className: "text-white/80 font-medium leading-relaxed" }, "\u91C7\u7528 sa2kit \u5F15\u64CE\u6784\u5EFA\u7684\u65B0\u4E00\u4EE3\u5B9E\u65F6 3D \u89C6\u89C9\u5C0F\u8BF4\u3002\u7ED3\u5408\u4E86 MMD \u5B9E\u65F6\u6E32\u67D3\u6280\u672F\u4E0E\u4EA4\u4E92\u5F0F\u5267\u60C5\u5206\u652F\u7CFB\u7EDF\uFF0C\u81F4\u529B\u4E8E\u6253\u9020\u6781\u81F4\u7684\u6C89\u6D78\u5F0F\u53D9\u4E8B\u4F53\u9A8C\u3002")), /* @__PURE__ */ React6__default.default.createElement("div", { className: "grid grid-cols-2 gap-4 pt-6 border-t border-white/10" }, /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-[10px] font-bold text-white/30 tracking-widest" }, "DEVELOPER"), /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-xs font-bold text-white/80" }, "SA2KIT TEAM")), /* @__PURE__ */ React6__default.default.createElement("div", { className: "flex flex-col gap-1 text-right" }, /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-[10px] font-bold text-white/30 tracking-widest" }, "ENGINE"), /* @__PURE__ */ React6__default.default.createElement("span", { className: "text-xs font-bold text-white/80" }, "THREE.JS / REACT"))))),
2859
+ /* @__PURE__ */ React6__default.default.createElement("style", null, `
2860
+ @keyframes floatParticle {
2861
+ from { transform: translateY(0) translateX(0); opacity: 0; }
2862
+ 20% { opacity: 1; }
2863
+ 80% { opacity: 1; }
2864
+ to { transform: translateY(-100vh) translateX(50px); opacity: 0; }
2865
+ }
2866
+ @keyframes blob {
2867
+ 0%, 100% { transform: scale(1); opacity: 0.1; }
2868
+ 50% { transform: scale(1.2); opacity: 0.2; }
2869
+ }
2870
+ .animate-blob {
2871
+ animation: blob 10s infinite;
2872
+ }
2873
+ .animation-delay-2000 {
2874
+ animation-delay: 2s;
2875
+ }
2876
+ .animation-delay-4000 {
2877
+ animation-delay: 4s;
2878
+ }
2879
+ .custom-scrollbar::-webkit-scrollbar {
2880
+ width: 6px;
2881
+ }
2882
+ .custom-scrollbar::-webkit-scrollbar-track {
2883
+ background: rgba(255, 255, 255, 0.05);
2884
+ border-radius: 10px;
2885
+ }
2886
+ .custom-scrollbar::-webkit-scrollbar-thumb {
2887
+ background: rgba(255, 255, 255, 0.3);
2888
+ border-radius: 10px;
2889
+ border: 2px solid transparent;
2890
+ background-clip: content-box;
2891
+ }
2892
+ `)
2750
2893
  );
2751
- let portalContainer = document.getElementById("start-screen-portal-root");
2752
- if (!portalContainer) {
2894
+ let portalContainer = typeof document !== "undefined" ? document.getElementById("start-screen-portal-root") : null;
2895
+ if (typeof document !== "undefined" && !portalContainer) {
2753
2896
  portalContainer = document.createElement("div");
2754
2897
  portalContainer.id = "start-screen-portal-root";
2755
2898
  document.body.appendChild(portalContainer);
2756
2899
  }
2757
- portalContainer.style.cssText = `
2758
- position: fixed;
2759
- top: 0;
2760
- left: 0;
2761
- right: 0;
2762
- bottom: 0;
2763
- width: 100vw;
2764
- height: 100vh;
2765
- margin: 0;
2766
- padding: 0;
2767
- overflow: hidden;
2768
- z-index: 999999;
2769
- pointer-events: none;
2770
- `.replace(/\s+/g, " ").trim();
2900
+ if (portalContainer) {
2901
+ portalContainer.style.cssText = `
2902
+ position: fixed;
2903
+ top: 0; left: 0; right: 0; bottom: 0;
2904
+ width: 100vw; height: 100vh;
2905
+ margin: 0; padding: 0;
2906
+ overflow: hidden;
2907
+ z-index: 999999;
2908
+ pointer-events: none;
2909
+ `.replace(/\s+/g, " ").trim();
2910
+ }
2911
+ if (!portalContainer) return content;
2771
2912
  return reactDom.createPortal(content, portalContainer);
2772
2913
  };
2773
2914
  StartScreen.displayName = "StartScreen";
@@ -2794,7 +2935,9 @@ var LoadingOverlay = ({
2794
2935
  showStartScreen = false,
2795
2936
  scriptName = "",
2796
2937
  loadingText = "\u6B63\u5728\u51C6\u5907\u573A\u666F\u4E2D...",
2797
- startText = "\u70B9\u51FB\u5F00\u59CB",
2938
+ startText = "\u5F00\u59CB\u6E38\u620F",
2939
+ settingsText = "\u6E38\u620F\u8BBE\u7F6E",
2940
+ aboutText = "\u5173\u4E8E\u4F5C\u54C1",
2798
2941
  onStart,
2799
2942
  className = ""
2800
2943
  }) => {
@@ -2811,6 +2954,8 @@ var LoadingOverlay = ({
2811
2954
  showStartScreen,
2812
2955
  scriptName,
2813
2956
  startText,
2957
+ settingsText,
2958
+ aboutText,
2814
2959
  onStart,
2815
2960
  className
2816
2961
  }
@@ -2925,6 +3070,9 @@ var MMDVisualNovel = React6.forwardRef(
2925
3070
  mobileOptimization,
2926
3071
  dialogueTheme,
2927
3072
  autoStart = false,
3073
+ startText,
3074
+ settingsText,
3075
+ aboutText,
2928
3076
  initialNodeIndex = 0,
2929
3077
  initialDialogueIndex = 0,
2930
3078
  onNodeChange,
@@ -3301,7 +3449,9 @@ var MMDVisualNovel = React6.forwardRef(
3301
3449
  showStartScreen: !isStarted,
3302
3450
  scriptName: script.name,
3303
3451
  loadingText: "\u6B63\u5728\u51C6\u5907\u573A\u666F\u4E2D...",
3304
- startText: "\u70B9\u51FB\u5F00\u59CB",
3452
+ startText,
3453
+ settingsText,
3454
+ aboutText,
3305
3455
  onStart: handleStart
3306
3456
  }
3307
3457
  ),