sa2kit 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -94
- package/dist/AliyunOSSProvider-2UZRIGT3.mjs +6 -0
- package/dist/{AliyunOSSProvider-GQMSDJGZ.mjs.map → AliyunOSSProvider-2UZRIGT3.mjs.map} +1 -1
- package/dist/AliyunOSSProvider-XCTK3QQA.js +15 -0
- package/dist/{AliyunOSSProvider-7JLMJDXK.js.map → AliyunOSSProvider-XCTK3QQA.js.map} +1 -1
- package/dist/{chunk-3RFBUDRA.js → chunk-EXT3IKQA.js} +39 -6
- package/dist/chunk-EXT3IKQA.js.map +1 -0
- package/dist/{chunk-YVBU7QDJ.mjs → chunk-OHUE7EL6.mjs} +34 -5
- package/dist/chunk-OHUE7EL6.mjs.map +1 -0
- package/dist/mmd/admin/index.d.mts +1 -1
- package/dist/mmd/admin/index.d.ts +1 -1
- package/dist/mmd/admin/index.js +7 -1
- package/dist/mmd/admin/index.js.map +1 -1
- package/dist/mmd/admin/index.mjs +7 -1
- package/dist/mmd/admin/index.mjs.map +1 -1
- package/dist/mmd/index.d.mts +52 -6
- package/dist/mmd/index.d.ts +52 -6
- package/dist/mmd/index.js +276 -74
- package/dist/mmd/index.js.map +1 -1
- package/dist/mmd/index.mjs +277 -76
- package/dist/mmd/index.mjs.map +1 -1
- package/dist/mmd/server/index.d.mts +1 -1
- package/dist/mmd/server/index.d.ts +1 -1
- package/dist/{types-CsTSddwu.d.mts → types-DxYJqqes.d.mts} +34 -2
- package/dist/{types-CsTSddwu.d.ts → types-DxYJqqes.d.ts} +34 -2
- package/dist/universalFile/server/index.d.mts +15 -0
- package/dist/universalFile/server/index.d.ts +15 -0
- package/dist/universalFile/server/index.js +3 -3
- package/dist/universalFile/server/index.mjs +2 -2
- package/package.json +4 -1
- package/dist/AliyunOSSProvider-7JLMJDXK.js +0 -15
- package/dist/AliyunOSSProvider-GQMSDJGZ.mjs +0 -6
- package/dist/chunk-3RFBUDRA.js.map +0 -1
- package/dist/chunk-YVBU7QDJ.mjs.map +0 -1
package/dist/mmd/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '../chunk-BJTO5JO5.mjs';
|
|
2
2
|
import React6, { forwardRef, useRef, useEffect, useImperativeHandle, useState, useCallback } from 'react';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
-
import { OrbitControls, MMDLoader, MMDAnimationHelper } from 'three-stdlib';
|
|
4
|
+
import { UnrealBloomPass, OutlineEffect, EffectComposer, RenderPass, OrbitControls, MMDLoader, MMDAnimationHelper } from 'three-stdlib';
|
|
5
5
|
import { SkipBack, Pause, Play, SkipForward, Camera, Repeat, Repeat1, Shuffle, ListMusic, Music, X, Grid3x3, Settings, Minimize, Maximize, Video, Check, User, Image } from 'lucide-react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
|
|
@@ -138,8 +138,37 @@ async function waitForMaterialsReady(object, renderer, scene, camera) {
|
|
|
138
138
|
for (let i = 0; i < 3; i++) {
|
|
139
139
|
await new Promise((resolve) => {
|
|
140
140
|
requestAnimationFrame(() => {
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
try {
|
|
142
|
+
object.traverse((obj) => {
|
|
143
|
+
if (obj.isMesh) {
|
|
144
|
+
const mesh = obj;
|
|
145
|
+
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
146
|
+
const hasMorphAttributes = mesh.geometry.morphAttributes && Object.keys(mesh.geometry.morphAttributes).length > 0;
|
|
147
|
+
materials.forEach((m) => {
|
|
148
|
+
if (!hasMorphAttributes) {
|
|
149
|
+
m.morphTargets = false;
|
|
150
|
+
if (mesh.geometry.morphAttributes) {
|
|
151
|
+
mesh.geometry.morphAttributes = {};
|
|
152
|
+
}
|
|
153
|
+
if (mesh.morphTargetInfluences) {
|
|
154
|
+
mesh.morphTargetInfluences = [];
|
|
155
|
+
}
|
|
156
|
+
if (mesh.morphTargetDictionary) {
|
|
157
|
+
mesh.morphTargetDictionary = {};
|
|
158
|
+
}
|
|
159
|
+
m.needsUpdate = true;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
if (mesh.updateMorphTargets) {
|
|
163
|
+
mesh.updateMorphTargets();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
renderer.render(scene, camera);
|
|
168
|
+
console.log(`[MMDPlayerBase] Warmup render ${i + 1}/3`);
|
|
169
|
+
} catch (renderError) {
|
|
170
|
+
console.warn("[MMDPlayerBase] Warmup render failed (shader error?), skipping...", renderError);
|
|
171
|
+
}
|
|
143
172
|
resolve();
|
|
144
173
|
});
|
|
145
174
|
});
|
|
@@ -167,10 +196,15 @@ var MMDPlayerBase = forwardRef((props, ref) => {
|
|
|
167
196
|
className,
|
|
168
197
|
style
|
|
169
198
|
} = props;
|
|
199
|
+
const renderEffect = props.renderEffect || stage.renderEffect || "default";
|
|
200
|
+
const outlineOptions = { ...stage.outlineOptions, ...props.outlineOptions };
|
|
201
|
+
const bloomOptions = { ...stage.bloomOptions, ...props.bloomOptions };
|
|
170
202
|
const containerRef = useRef(null);
|
|
171
203
|
const sceneRef = useRef(null);
|
|
172
204
|
const cameraRef = useRef(null);
|
|
173
205
|
const rendererRef = useRef(null);
|
|
206
|
+
const outlineEffectRef = useRef(null);
|
|
207
|
+
const composerRef = useRef(null);
|
|
174
208
|
const controlsRef = useRef(null);
|
|
175
209
|
const helperRef = useRef(null);
|
|
176
210
|
const axesHelperRef = useRef(null);
|
|
@@ -378,10 +412,28 @@ var MMDPlayerBase = forwardRef((props, ref) => {
|
|
|
378
412
|
}
|
|
379
413
|
container.appendChild(renderer.domElement);
|
|
380
414
|
rendererRef.current = renderer;
|
|
415
|
+
const effect = new OutlineEffect(renderer, {
|
|
416
|
+
defaultThickness: outlineOptions.thickness ?? 3e-3,
|
|
417
|
+
defaultColor: new THREE.Color(outlineOptions.color ?? "#000000").toArray(),
|
|
418
|
+
defaultAlpha: 1,
|
|
419
|
+
defaultKeepAlive: true
|
|
420
|
+
});
|
|
421
|
+
outlineEffectRef.current = effect;
|
|
422
|
+
const composer = new EffectComposer(renderer);
|
|
423
|
+
const renderPass = new RenderPass(scene, camera);
|
|
424
|
+
composer.addPass(renderPass);
|
|
425
|
+
const bloomPass = new UnrealBloomPass(
|
|
426
|
+
new THREE.Vector2(width, height),
|
|
427
|
+
bloomOptions.strength ?? 1,
|
|
428
|
+
bloomOptions.radius ?? 0.4,
|
|
429
|
+
bloomOptions.threshold ?? 0.8
|
|
430
|
+
);
|
|
431
|
+
composer.addPass(bloomPass);
|
|
432
|
+
composerRef.current = composer;
|
|
381
433
|
const ambientLight = new THREE.AmbientLight(16777215, stage.ambientLightIntensity ?? 0.5);
|
|
382
434
|
scene.add(ambientLight);
|
|
383
435
|
const dirLight = new THREE.DirectionalLight(16777215, stage.directionalLightIntensity ?? 0.8);
|
|
384
|
-
dirLight.position.set(
|
|
436
|
+
dirLight.position.set(0, 10, 0);
|
|
385
437
|
if (stage.enableShadow !== false) {
|
|
386
438
|
dirLight.castShadow = true;
|
|
387
439
|
dirLight.shadow.mapSize.width = mobileOptimization.enabled ? 1024 : 2048;
|
|
@@ -416,6 +468,9 @@ var MMDPlayerBase = forwardRef((props, ref) => {
|
|
|
416
468
|
cameraRef.current.aspect = w / h;
|
|
417
469
|
cameraRef.current.updateProjectionMatrix();
|
|
418
470
|
rendererRef.current.setSize(w, h);
|
|
471
|
+
if (composerRef.current) {
|
|
472
|
+
composerRef.current.setSize(w, h);
|
|
473
|
+
}
|
|
419
474
|
};
|
|
420
475
|
const resizeObserver = new ResizeObserver(onResize);
|
|
421
476
|
resizeObserver.observe(container);
|
|
@@ -423,7 +478,11 @@ var MMDPlayerBase = forwardRef((props, ref) => {
|
|
|
423
478
|
onResize();
|
|
424
479
|
console.log("[MMDPlayerBase] Starting render loop (animation paused)");
|
|
425
480
|
animate();
|
|
426
|
-
console.log("[MMDPlayerBase] Start loading resources...",
|
|
481
|
+
console.log("[MMDPlayerBase] Start loading resources...", {
|
|
482
|
+
model: resources.modelPath,
|
|
483
|
+
stage: resources.stageModelPath,
|
|
484
|
+
motion: resources.motionPath
|
|
485
|
+
});
|
|
427
486
|
const loader = new MMDLoader();
|
|
428
487
|
const helper = new MMDAnimationHelper({
|
|
429
488
|
afterglow: 2
|
|
@@ -596,51 +655,67 @@ var MMDPlayerBase = forwardRef((props, ref) => {
|
|
|
596
655
|
(err) => console.error("Failed to load audio:", err)
|
|
597
656
|
);
|
|
598
657
|
}
|
|
599
|
-
|
|
600
|
-
|
|
658
|
+
const stagePaths = Array.isArray(resources.stageModelPath) ? resources.stageModelPath : resources.stageModelPath ? [resources.stageModelPath] : [];
|
|
659
|
+
for (const stagePath of stagePaths) {
|
|
601
660
|
try {
|
|
602
|
-
|
|
661
|
+
console.log(`[MMDPlayerBase] Loading stage from: ${stagePath}`);
|
|
662
|
+
const stageMesh = await new Promise((resolve, reject) => {
|
|
603
663
|
loader.load(
|
|
604
|
-
|
|
664
|
+
stagePath,
|
|
605
665
|
(mesh2) => resolve(mesh2),
|
|
606
|
-
|
|
666
|
+
(xhr) => {
|
|
667
|
+
if (xhr.lengthComputable) {
|
|
668
|
+
const percent = xhr.loaded / xhr.total * 100;
|
|
669
|
+
if (Math.round(percent) % 20 === 0) console.log(`[MMDPlayerBase] Stage loading: ${percent.toFixed(1)}%`);
|
|
670
|
+
}
|
|
671
|
+
},
|
|
607
672
|
(err) => reject(err)
|
|
608
673
|
);
|
|
609
674
|
});
|
|
610
675
|
if (checkCancelled()) return;
|
|
611
|
-
console.log(
|
|
612
|
-
stageMesh.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
676
|
+
console.log(`[MMDPlayerBase] Stage model loaded: ${stagePath}`, stageMesh);
|
|
677
|
+
stageMesh.traverse((child) => {
|
|
678
|
+
if (child instanceof THREE.Mesh) {
|
|
679
|
+
child.castShadow = true;
|
|
680
|
+
child.receiveShadow = true;
|
|
681
|
+
const mesh2 = child;
|
|
682
|
+
const materials = Array.isArray(mesh2.material) ? mesh2.material : [mesh2.material];
|
|
683
|
+
materials.forEach((m, idx) => {
|
|
684
|
+
if (m.morphTargets) {
|
|
685
|
+
m.morphTargets = false;
|
|
686
|
+
m.needsUpdate = true;
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
if (mesh2.geometry.morphAttributes) {
|
|
690
|
+
mesh2.geometry.morphAttributes = {};
|
|
691
|
+
}
|
|
692
|
+
if (mesh2.morphTargetInfluences) {
|
|
693
|
+
mesh2.morphTargetInfluences = [];
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
try {
|
|
698
|
+
await waitForMaterialsReady(stageMesh, renderer, scene, camera);
|
|
699
|
+
} catch (e) {
|
|
700
|
+
console.warn(`[MMDPlayerBase] Warmup error for stage ${stagePath}:`, e);
|
|
701
|
+
}
|
|
619
702
|
if (checkCancelled()) return;
|
|
620
|
-
console.log("[MMDPlayerBase] \u2705 Stage materials and textures loaded");
|
|
621
703
|
scene.add(stageMesh);
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
animation: stageAnimation
|
|
635
|
-
});
|
|
636
|
-
console.log("[MMDPlayerBase] \u2705 Stage motion bound successfully");
|
|
637
|
-
},
|
|
638
|
-
void 0,
|
|
639
|
-
(err) => console.error("Failed to load stage motion:", err)
|
|
640
|
-
);
|
|
704
|
+
const stageBox = new THREE.Box3().setFromObject(stageMesh);
|
|
705
|
+
const stageSize = stageBox.getSize(new THREE.Vector3());
|
|
706
|
+
if (stageSize.length() < 1) {
|
|
707
|
+
stageMesh.scale.multiplyScalar(100);
|
|
708
|
+
} else if (stageSize.y < 5) {
|
|
709
|
+
stageMesh.scale.multiplyScalar(10);
|
|
710
|
+
}
|
|
711
|
+
console.log(`[MMDPlayerBase] \u2705 Stage added: ${stagePath}`);
|
|
712
|
+
if (resources.stageMotionPath) {
|
|
713
|
+
loader.loadAnimation(resources.stageMotionPath, stageMesh, (anim) => {
|
|
714
|
+
if (!checkCancelled()) helper.add(stageMesh, { animation: anim });
|
|
715
|
+
});
|
|
641
716
|
}
|
|
642
717
|
} catch (err) {
|
|
643
|
-
console.error(
|
|
718
|
+
console.error(`Failed to load stage ${stagePath}:`, err);
|
|
644
719
|
}
|
|
645
720
|
}
|
|
646
721
|
if (checkCancelled()) return;
|
|
@@ -1018,6 +1093,13 @@ ${errorMessage}
|
|
|
1018
1093
|
}
|
|
1019
1094
|
if (rendererRef.current) {
|
|
1020
1095
|
try {
|
|
1096
|
+
if (composerRef.current) {
|
|
1097
|
+
composerRef.current.passes.forEach((pass) => {
|
|
1098
|
+
if (pass.dispose) pass.dispose();
|
|
1099
|
+
});
|
|
1100
|
+
composerRef.current = null;
|
|
1101
|
+
}
|
|
1102
|
+
outlineEffectRef.current = null;
|
|
1021
1103
|
const renderer = rendererRef.current;
|
|
1022
1104
|
if (renderer.renderLists) {
|
|
1023
1105
|
renderer.renderLists.dispose();
|
|
@@ -1084,6 +1166,17 @@ ${errorMessage}
|
|
|
1084
1166
|
audioRef.current.setLoop(loop);
|
|
1085
1167
|
}
|
|
1086
1168
|
}, [loop]);
|
|
1169
|
+
useEffect(() => {
|
|
1170
|
+
if (outlineEffectRef.current) ;
|
|
1171
|
+
if (composerRef.current) {
|
|
1172
|
+
const bloomPass = composerRef.current.passes.find((p) => p instanceof UnrealBloomPass);
|
|
1173
|
+
if (bloomPass) {
|
|
1174
|
+
bloomPass.strength = bloomOptions.strength ?? 1;
|
|
1175
|
+
bloomPass.radius = bloomOptions.radius ?? 0.4;
|
|
1176
|
+
bloomPass.threshold = bloomOptions.threshold ?? 0.8;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}, [bloomOptions.strength, bloomOptions.radius, bloomOptions.threshold]);
|
|
1087
1180
|
useEffect(() => {
|
|
1088
1181
|
if (!isReadyRef.current) return;
|
|
1089
1182
|
if (sceneRef.current) {
|
|
@@ -1132,7 +1225,15 @@ ${errorMessage}
|
|
|
1132
1225
|
latestCallbacks.current.onEnded?.();
|
|
1133
1226
|
}
|
|
1134
1227
|
}
|
|
1135
|
-
|
|
1228
|
+
const useOutline = renderEffect === "outline" || renderEffect === "outline+bloom";
|
|
1229
|
+
const useBloom = renderEffect === "bloom" || renderEffect === "outline+bloom";
|
|
1230
|
+
if (useBloom && composerRef.current) {
|
|
1231
|
+
composerRef.current.render();
|
|
1232
|
+
} else if (useOutline && outlineEffectRef.current) {
|
|
1233
|
+
outlineEffectRef.current.render(sceneRef.current, cameraRef.current);
|
|
1234
|
+
} else {
|
|
1235
|
+
rendererRef.current.render(sceneRef.current, cameraRef.current);
|
|
1236
|
+
}
|
|
1136
1237
|
}
|
|
1137
1238
|
};
|
|
1138
1239
|
return /* @__PURE__ */ React6.createElement(
|
|
@@ -2827,6 +2928,8 @@ var MMDVisualNovel = forwardRef(
|
|
|
2827
2928
|
const [pendingNodeIndex, setPendingNodeIndex] = useState(null);
|
|
2828
2929
|
const [showChoices, setShowChoices] = useState(false);
|
|
2829
2930
|
const [isCameraManual, setIsCameraManual] = useState(false);
|
|
2931
|
+
const [variables, setVariables] = useState({});
|
|
2932
|
+
const [activeEffect, setActiveEffect] = useState(null);
|
|
2830
2933
|
const playerRef = useRef(null);
|
|
2831
2934
|
const containerRef = useRef(null);
|
|
2832
2935
|
const autoTimerRef = useRef(null);
|
|
@@ -2834,6 +2937,7 @@ var MMDVisualNovel = forwardRef(
|
|
|
2834
2937
|
const isStartedRef = useRef(autoStart);
|
|
2835
2938
|
const lastAnimationTimeRef = useRef(0);
|
|
2836
2939
|
const isVmdFinishedRef = useRef(false);
|
|
2940
|
+
const effectTimerRef = useRef(null);
|
|
2837
2941
|
const currentNode = nodes[currentNodeIndex];
|
|
2838
2942
|
const currentDialogue = currentNode?.dialogues[currentDialogueIndex] || null;
|
|
2839
2943
|
const addToHistory = useCallback((dialogue, nodeIndex, dialogueIndex) => {
|
|
@@ -2848,32 +2952,17 @@ var MMDVisualNovel = forwardRef(
|
|
|
2848
2952
|
}
|
|
2849
2953
|
]);
|
|
2850
2954
|
}, []);
|
|
2851
|
-
const
|
|
2852
|
-
if (!
|
|
2853
|
-
if (
|
|
2854
|
-
clearTimeout(
|
|
2855
|
-
autoTimerRef.current = null;
|
|
2955
|
+
const triggerEffect = useCallback((effect) => {
|
|
2956
|
+
if (!effect) return;
|
|
2957
|
+
if (effectTimerRef.current) {
|
|
2958
|
+
clearTimeout(effectTimerRef.current);
|
|
2856
2959
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
typingCompleteRef.current = false;
|
|
2864
|
-
} else if (currentNode.choices && currentNode.choices.length > 0) {
|
|
2865
|
-
setShowChoices(true);
|
|
2866
|
-
} else {
|
|
2867
|
-
const nextNodeIndex = currentNodeIndex + 1;
|
|
2868
|
-
if (nextNodeIndex < nodes.length) {
|
|
2869
|
-
goToNode(nextNodeIndex);
|
|
2870
|
-
} else if (loop) {
|
|
2871
|
-
goToNode(0);
|
|
2872
|
-
} else {
|
|
2873
|
-
onScriptComplete?.();
|
|
2874
|
-
}
|
|
2875
|
-
}
|
|
2876
|
-
}, [currentNode, currentDialogueIndex, currentNodeIndex, nodes.length, loop, addToHistory, onDialogueChange, onScriptComplete]);
|
|
2960
|
+
setActiveEffect(effect);
|
|
2961
|
+
effectTimerRef.current = setTimeout(() => {
|
|
2962
|
+
setActiveEffect(null);
|
|
2963
|
+
effectTimerRef.current = null;
|
|
2964
|
+
}, effect.duration || 1e3);
|
|
2965
|
+
}, []);
|
|
2877
2966
|
const goToNode = useCallback(
|
|
2878
2967
|
(nodeIndex, force = false) => {
|
|
2879
2968
|
if (nodeIndex < 0 || nodeIndex >= nodes.length) return;
|
|
@@ -2912,8 +3001,52 @@ var MMDVisualNovel = forwardRef(
|
|
|
2912
3001
|
}, 100);
|
|
2913
3002
|
}, 300);
|
|
2914
3003
|
},
|
|
2915
|
-
[nodes, isTransitioning, addToHistory, onNodeChange, onDialogueChange, currentNodeIndex
|
|
3004
|
+
[nodes, isTransitioning, addToHistory, onNodeChange, onDialogueChange, currentNodeIndex]
|
|
2916
3005
|
);
|
|
3006
|
+
const triggerNodeTransition = useCallback(() => {
|
|
3007
|
+
if (!currentNode) return;
|
|
3008
|
+
let nextNodeIndex = currentNodeIndex + 1;
|
|
3009
|
+
if (currentNode.nextCondition) {
|
|
3010
|
+
const { key, map, defaultIndex } = currentNode.nextCondition;
|
|
3011
|
+
const val = variables[key];
|
|
3012
|
+
if (val !== void 0 && map[val] !== void 0) {
|
|
3013
|
+
nextNodeIndex = map[val];
|
|
3014
|
+
console.log(`[MMDVisualNovel] Branching: ${key}=${val} -> node ${nextNodeIndex}`);
|
|
3015
|
+
} else {
|
|
3016
|
+
nextNodeIndex = defaultIndex;
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
if (nextNodeIndex < nodes.length && nextNodeIndex >= 0) {
|
|
3020
|
+
goToNode(nextNodeIndex);
|
|
3021
|
+
} else if (loop) {
|
|
3022
|
+
goToNode(0);
|
|
3023
|
+
} else {
|
|
3024
|
+
onScriptComplete?.();
|
|
3025
|
+
}
|
|
3026
|
+
}, [currentNode, currentNodeIndex, nodes.length, loop, variables, goToNode, onScriptComplete]);
|
|
3027
|
+
const goToNextDialogue = useCallback(() => {
|
|
3028
|
+
if (!currentNode) return;
|
|
3029
|
+
if (currentDialogue?.choices && currentDialogue.choices.length > 0 && !showChoices) {
|
|
3030
|
+
setShowChoices(true);
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
if (autoTimerRef.current) {
|
|
3034
|
+
clearTimeout(autoTimerRef.current);
|
|
3035
|
+
autoTimerRef.current = null;
|
|
3036
|
+
}
|
|
3037
|
+
const nextDialogueIndex = currentDialogueIndex + 1;
|
|
3038
|
+
if (nextDialogueIndex < currentNode.dialogues.length && currentNode?.dialogues[nextDialogueIndex] !== void 0) {
|
|
3039
|
+
const nextDialogue = currentNode.dialogues[nextDialogueIndex];
|
|
3040
|
+
setCurrentDialogueIndex(nextDialogueIndex);
|
|
3041
|
+
addToHistory(nextDialogue, currentNodeIndex, nextDialogueIndex);
|
|
3042
|
+
onDialogueChange?.(nextDialogue, nextDialogueIndex, currentNodeIndex);
|
|
3043
|
+
typingCompleteRef.current = false;
|
|
3044
|
+
} else if (currentNode.choices && currentNode.choices.length > 0) {
|
|
3045
|
+
setShowChoices(true);
|
|
3046
|
+
} else {
|
|
3047
|
+
triggerNodeTransition();
|
|
3048
|
+
}
|
|
3049
|
+
}, [currentNode, currentDialogue, currentDialogueIndex, currentNodeIndex, nodes.length, loop, addToHistory, onDialogueChange, onScriptComplete, showChoices, variables, goToNode, triggerNodeTransition]);
|
|
2917
3050
|
const goToDialogue = useCallback(
|
|
2918
3051
|
(dialogueIndex) => {
|
|
2919
3052
|
if (!currentNode) return;
|
|
@@ -2957,6 +3090,11 @@ var MMDVisualNovel = forwardRef(
|
|
|
2957
3090
|
}
|
|
2958
3091
|
return void 0;
|
|
2959
3092
|
}, [currentDialogue, handleTypingComplete]);
|
|
3093
|
+
useEffect(() => {
|
|
3094
|
+
if (currentDialogue?.effect) {
|
|
3095
|
+
triggerEffect(currentDialogue.effect);
|
|
3096
|
+
}
|
|
3097
|
+
}, [currentNodeIndex, currentDialogueIndex, triggerEffect]);
|
|
2960
3098
|
const toggleAutoMode = useCallback(() => {
|
|
2961
3099
|
setIsAutoMode((prev) => !prev);
|
|
2962
3100
|
}, []);
|
|
@@ -2992,12 +3130,17 @@ var MMDVisualNovel = forwardRef(
|
|
|
2992
3130
|
getCurrentNodeIndex: () => currentNodeIndex,
|
|
2993
3131
|
getCurrentDialogueIndex: () => currentDialogueIndex,
|
|
2994
3132
|
getHistory: () => history,
|
|
3133
|
+
getVariables: () => variables,
|
|
3134
|
+
setVariable: (key, value) => {
|
|
3135
|
+
setVariables((prev) => ({ ...prev, [key]: value }));
|
|
3136
|
+
},
|
|
2995
3137
|
setAutoMode: setIsAutoMode,
|
|
2996
3138
|
skipTyping: () => {
|
|
2997
3139
|
typingCompleteRef.current = true;
|
|
2998
|
-
}
|
|
3140
|
+
},
|
|
3141
|
+
triggerEffect
|
|
2999
3142
|
}),
|
|
3000
|
-
[goToNode, goToDialogue, currentNodeIndex, currentDialogueIndex, history]
|
|
3143
|
+
[goToNode, goToDialogue, currentNodeIndex, currentDialogueIndex, history, triggerEffect]
|
|
3001
3144
|
);
|
|
3002
3145
|
useEffect(() => {
|
|
3003
3146
|
if (autoStart && currentNode && currentNode.dialogues.length > 0 && history.length === 0 && currentNode?.dialogues[0] !== void 0) {
|
|
@@ -3009,6 +3152,9 @@ var MMDVisualNovel = forwardRef(
|
|
|
3009
3152
|
if (autoTimerRef.current) {
|
|
3010
3153
|
clearTimeout(autoTimerRef.current);
|
|
3011
3154
|
}
|
|
3155
|
+
if (effectTimerRef.current) {
|
|
3156
|
+
clearTimeout(effectTimerRef.current);
|
|
3157
|
+
}
|
|
3012
3158
|
};
|
|
3013
3159
|
}, []);
|
|
3014
3160
|
if (!currentNode) {
|
|
@@ -3081,6 +3227,38 @@ var MMDVisualNovel = forwardRef(
|
|
|
3081
3227
|
}
|
|
3082
3228
|
)
|
|
3083
3229
|
),
|
|
3230
|
+
activeEffect && /* @__PURE__ */ React6.createElement(
|
|
3231
|
+
"div",
|
|
3232
|
+
{
|
|
3233
|
+
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
3234
|
+
style: { zIndex: 999 }
|
|
3235
|
+
},
|
|
3236
|
+
activeEffect.type === "flash" && /* @__PURE__ */ React6.createElement(
|
|
3237
|
+
"div",
|
|
3238
|
+
{
|
|
3239
|
+
className: "h-full w-full",
|
|
3240
|
+
style: {
|
|
3241
|
+
backgroundColor: activeEffect.color || "white",
|
|
3242
|
+
animation: `flash-anim ${activeEffect.duration || 500}ms ease-out forwards`
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
),
|
|
3246
|
+
activeEffect.type === "gif" && activeEffect.url && /* @__PURE__ */ React6.createElement(
|
|
3247
|
+
"img",
|
|
3248
|
+
{
|
|
3249
|
+
src: activeEffect.url,
|
|
3250
|
+
alt: "effect",
|
|
3251
|
+
className: activeEffect.position === "full" ? "h-full w-full object-cover" : "max-h-full max-w-full"
|
|
3252
|
+
}
|
|
3253
|
+
),
|
|
3254
|
+
/* @__PURE__ */ React6.createElement("style", null, `
|
|
3255
|
+
@keyframes flash-anim {
|
|
3256
|
+
0% { opacity: 0; }
|
|
3257
|
+
25% { opacity: 1; }
|
|
3258
|
+
100% { opacity: 0; }
|
|
3259
|
+
}
|
|
3260
|
+
`)
|
|
3261
|
+
),
|
|
3084
3262
|
/* @__PURE__ */ React6.createElement(
|
|
3085
3263
|
LoadingOverlay,
|
|
3086
3264
|
{
|
|
@@ -3152,18 +3330,41 @@ var MMDVisualNovel = forwardRef(
|
|
|
3152
3330
|
}
|
|
3153
3331
|
}
|
|
3154
3332
|
),
|
|
3155
|
-
showChoices && currentNode.choices && /* @__PURE__ */ React6.createElement(
|
|
3333
|
+
showChoices && (currentDialogue?.choices || currentNode.choices) && /* @__PURE__ */ React6.createElement(
|
|
3156
3334
|
ChoiceMenu,
|
|
3157
3335
|
{
|
|
3158
|
-
choices: currentNode.choices,
|
|
3336
|
+
choices: currentDialogue?.choices || currentNode.choices,
|
|
3159
3337
|
theme: dialogueTheme,
|
|
3160
3338
|
onSelect: (choice) => {
|
|
3339
|
+
if (choice.setVariable) {
|
|
3340
|
+
const { key, value } = choice.setVariable;
|
|
3341
|
+
setVariables((prev) => ({ ...prev, [key]: value }));
|
|
3342
|
+
console.log(`[MMDVisualNovel] Variable set: ${key} = ${value}`);
|
|
3343
|
+
}
|
|
3161
3344
|
choice.onSelect?.();
|
|
3162
|
-
if (choice.
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3345
|
+
if (choice.effect) {
|
|
3346
|
+
triggerEffect(choice.effect);
|
|
3347
|
+
}
|
|
3348
|
+
setShowChoices(false);
|
|
3349
|
+
if (choice.nextNodeIndex !== void 0) {
|
|
3350
|
+
if (choice.nextNodeIndex === currentNodeIndex) {
|
|
3351
|
+
goToDialogue(choice.nextDialogueIndex || 0);
|
|
3352
|
+
} else {
|
|
3353
|
+
goToNode(choice.nextNodeIndex, true);
|
|
3354
|
+
}
|
|
3355
|
+
} else if (currentDialogue?.choices) {
|
|
3356
|
+
const nextIdx = currentDialogueIndex + 1;
|
|
3357
|
+
if (currentNode && nextIdx < currentNode.dialogues.length) {
|
|
3358
|
+
const nextDialogue = currentNode.dialogues[nextIdx];
|
|
3359
|
+
if (nextDialogue) {
|
|
3360
|
+
setCurrentDialogueIndex(nextIdx);
|
|
3361
|
+
addToHistory(nextDialogue, currentNodeIndex, nextIdx);
|
|
3362
|
+
onDialogueChange?.(nextDialogue, nextIdx, currentNodeIndex);
|
|
3363
|
+
typingCompleteRef.current = false;
|
|
3364
|
+
}
|
|
3365
|
+
} else {
|
|
3366
|
+
triggerNodeTransition();
|
|
3367
|
+
}
|
|
3167
3368
|
}
|
|
3168
3369
|
}
|
|
3169
3370
|
}
|
|
@@ -3582,6 +3783,6 @@ var MMDMusicPlayer = forwardRef(
|
|
|
3582
3783
|
);
|
|
3583
3784
|
MMDMusicPlayer.displayName = "MMDMusicPlayer";
|
|
3584
3785
|
|
|
3585
|
-
export { DialogueBox, HistoryPanel, LoadingOverlay, LoadingScreen, MMDMusicPlayer, MMDPlayerBase, MMDPlayerEnhanced, MMDPlayerEnhancedDebugInfo, MMDPlaylist, MMDPlaylistDebugInfo, MMDVisualNovel, MusicControls, PlaylistPanel, StartScreen, TrackInfo, loadAmmo };
|
|
3786
|
+
export { ChoiceMenu, DialogueBox, HistoryPanel, LoadingOverlay, LoadingScreen, MMDMusicPlayer, MMDPlayerBase, MMDPlayerEnhanced, MMDPlayerEnhancedDebugInfo, MMDPlaylist, MMDPlaylistDebugInfo, MMDVisualNovel, MusicControls, PlaylistPanel, StartScreen, TrackInfo, loadAmmo };
|
|
3586
3787
|
//# sourceMappingURL=index.mjs.map
|
|
3587
3788
|
//# sourceMappingURL=index.mjs.map
|