fix skill
This commit is contained in:
31
src/App.jsx
31
src/App.jsx
@@ -20,6 +20,10 @@ export default function App() {
|
|||||||
const [timeScale, setTimeScale] = useState(100);
|
const [timeScale, setTimeScale] = useState(100);
|
||||||
const [camSpeed, setCamSpeed] = useState(0.05);
|
const [camSpeed, setCamSpeed] = useState(0.05);
|
||||||
const [vrmModel, setVrmModel] = useState('ai.vrm');
|
const [vrmModel, setVrmModel] = useState('ai.vrm');
|
||||||
|
const [lang, setLang] = useState('ja');
|
||||||
|
const langRef = useRef('ja');
|
||||||
|
const voiceIndexRef = useRef(0);
|
||||||
|
const voicePattern = ['normal','normal','normal','normal','normal','normal','normal','normal','skill','skill'];
|
||||||
const actionIndexRef = useRef(0);
|
const actionIndexRef = useRef(0);
|
||||||
const teleportIndexRef = useRef(0);
|
const teleportIndexRef = useRef(0);
|
||||||
const countRef = useRef(0);
|
const countRef = useRef(0);
|
||||||
@@ -28,11 +32,25 @@ export default function App() {
|
|||||||
return onAdminChange((v) => setIsAdmin(v));
|
return onAdminChange((v) => setIsAdmin(v));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleLangChange = useCallback((v) => { setLang(v); langRef.current = v; }, []);
|
||||||
|
|
||||||
|
const playSkillVoice = useCallback(() => {
|
||||||
|
const type = voicePattern[voiceIndexRef.current % voicePattern.length];
|
||||||
|
voiceIndexRef.current += 1;
|
||||||
|
const suffix = langRef.current === 'en' ? '_en' : '';
|
||||||
|
const file = `${import.meta.env.BASE_URL}voice/ai/${type}_1${suffix}.mp3`;
|
||||||
|
const audio = new Audio(file);
|
||||||
|
audio.volume = 0.7;
|
||||||
|
audio.play().catch(() => {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const playAnim = useCallback((name) => {
|
const playAnim = useCallback((name) => {
|
||||||
countRef.current += 1;
|
countRef.current += 1;
|
||||||
setAnimState({ name, count: countRef.current });
|
setAnimState({ name, count: countRef.current });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const doSkillRef = useRef(null);
|
||||||
|
|
||||||
const handleKey = useCallback((e) => {
|
const handleKey = useCallback((e) => {
|
||||||
if (e.code === 'Escape') {
|
if (e.code === 'Escape') {
|
||||||
setView(view === 'nasa' ? 'avatar' : 'nasa');
|
setView(view === 'nasa' ? 'avatar' : 'nasa');
|
||||||
@@ -53,8 +71,7 @@ export default function App() {
|
|||||||
teleportIndexRef.current = idx + 1;
|
teleportIndexRef.current = idx + 1;
|
||||||
} else if (e.code === 'KeyS') {
|
} else if (e.code === 'KeyS') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
playAnim('skill');
|
doSkillRef.current?.();
|
||||||
setVrmModel(prev => prev === 'ai.vrm' ? 'ai_mode.vrm' : 'ai.vrm');
|
|
||||||
}
|
}
|
||||||
}, [playAnim, view]);
|
}, [playAnim, view]);
|
||||||
|
|
||||||
@@ -93,10 +110,16 @@ export default function App() {
|
|||||||
teleportIndexRef.current = idx + 1;
|
teleportIndexRef.current = idx + 1;
|
||||||
}, [playAnim]);
|
}, [playAnim]);
|
||||||
|
|
||||||
|
const skillCoolRef = useRef(0);
|
||||||
const doSkill = useCallback(() => {
|
const doSkill = useCallback(() => {
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - skillCoolRef.current < 3000) return;
|
||||||
|
skillCoolRef.current = now;
|
||||||
playAnim('skill');
|
playAnim('skill');
|
||||||
|
playSkillVoice();
|
||||||
setVrmModel(prev => prev === 'ai.vrm' ? 'ai_mode.vrm' : 'ai.vrm');
|
setVrmModel(prev => prev === 'ai.vrm' ? 'ai_mode.vrm' : 'ai.vrm');
|
||||||
}, [playAnim]);
|
}, [playAnim, playSkillVoice]);
|
||||||
|
doSkillRef.current = doSkill;
|
||||||
|
|
||||||
const appStartRef = useRef(Date.now());
|
const appStartRef = useRef(Date.now());
|
||||||
const lastSwitchRef = useRef(0);
|
const lastSwitchRef = useRef(0);
|
||||||
@@ -179,6 +202,8 @@ export default function App() {
|
|||||||
camSpeed={camSpeed}
|
camSpeed={camSpeed}
|
||||||
onCamSpeedChange={setCamSpeed}
|
onCamSpeedChange={setCamSpeed}
|
||||||
onSkill={doSkill}
|
onSkill={doSkill}
|
||||||
|
lang={lang}
|
||||||
|
onLangChange={handleLangChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,14 @@ export default function VrmCharacter({ selectedAnimation: animState, vrmModel =
|
|||||||
const vrm = gltf.userData.vrm;
|
const vrm = gltf.userData.vrm;
|
||||||
vrmRef.current = vrm;
|
vrmRef.current = vrm;
|
||||||
VRMUtils.removeUnnecessaryJoints(vrm.scene);
|
VRMUtils.removeUnnecessaryJoints(vrm.scene);
|
||||||
|
// SpringBone: centerをRotatingStage(親group)に設定し、回転に追従させる
|
||||||
|
const sbm = vrm.springBoneManager;
|
||||||
|
if (sbm) {
|
||||||
|
const stageGroup = vrm.scene.parent;
|
||||||
|
sbm.joints?.forEach(joint => {
|
||||||
|
if (stageGroup) joint.center = stageGroup;
|
||||||
|
});
|
||||||
|
}
|
||||||
vrm.humanoid.resetPose();
|
vrm.humanoid.resetPose();
|
||||||
vrm.scene.rotation.y = Math.PI;
|
vrm.scene.rotation.y = Math.PI;
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const btnStyle = {
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, onCamSpeedChange, onSkill }) {
|
export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, onCamSpeedChange, onSkill, lang, onLangChange }) {
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div style={containerStyle}>
|
||||||
<div>
|
<div>
|
||||||
@@ -77,8 +77,19 @@ export default function ControlPanel({ timeScale, onTimeScaleChange, camSpeed, o
|
|||||||
style={sliderStyle}
|
style={sliderStyle}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button style={btnStyle} onClick={() => onSkill?.()}>
|
<button
|
||||||
Skill
|
style={{ ...btnStyle, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
|
||||||
|
onClick={() => onSkill?.()}
|
||||||
|
>
|
||||||
|
<img src={`${import.meta.env.BASE_URL}icon/dot.svg`} alt="" style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: 0.7 }} />
|
||||||
|
<span>Skill</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
style={{ ...btnStyle, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
|
||||||
|
onClick={() => onLangChange?.(lang === 'ja' ? 'en' : 'ja')}
|
||||||
|
>
|
||||||
|
<img src={`${import.meta.env.BASE_URL}icon/language.svg`} alt="" style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: 0.7 }} />
|
||||||
|
<span>{lang?.toUpperCase()}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user