diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-05 14:51:36 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-05 14:51:36 +0900 |
| commit | 257516e2bde90e65439d01f19434cd2d9d5a03f7 (patch) | |
| tree | cab680958a6bb1249c288d5974b083cfa9de1f3f /public/bluebey-studio/src/panel.js | |
| parent | 1bf7ee115176bc366315a90ab31740e6cd968744 (diff) | |
bluebey-studio: 帽子切替のエラー修正とGLB帽子インポート、閉じ目の目線範囲・まつげ位置を調整
帽子切替時にトラバース中でハルを外して子がundefinedになる不具合を修正。GLBの帽子モデルを読み込めるようにし、なしで解除できるようにした。閉じ目の目線範囲を通常並みに広げ、まつげを上まぶたの外側へ配置。
Diffstat (limited to 'public/bluebey-studio/src/panel.js')
| -rw-r--r-- | public/bluebey-studio/src/panel.js | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/public/bluebey-studio/src/panel.js b/public/bluebey-studio/src/panel.js index 2b762f1..093386f 100644 --- a/public/bluebey-studio/src/panel.js +++ b/public/bluebey-studio/src/panel.js @@ -1674,15 +1674,41 @@ export function buildPanel(app, root) { /* ------------------------------------------------------------- 帽子 */ const hatSection = section(tabView, '帽子'); - hatSection.add(hint('ぶるべーの頭に帽子をかぶせます。もう一度「なし」を選ぶと外れます。')); + hatSection.add(hint('ぶるべーの頭に帽子をかぶせます。「なし」を選ぶと外れます。')); const hatSegment = segmented({ label: '帽子', options: HAT_LIBRARY.map((hat) => ({ value: hat.id, label: hat.label })), value: 'none', - onChange: (value) => { state.face.hat.kind = value; app.actions.refresh('all'); }, + onChange: (value) => { + state.face.hat.kind = value; + // Picking one of the built-in hats (including なし) also clears any GLB hat + // the user imported, so なし really removes the hat. + state.face.hat.custom = false; + app.actions.refresh('all'); + }, }); hatSection.add(hatSegment.el); - syncers.push(() => hatSegment.set(state.face.hat?.kind ?? 'none')); + syncers.push(() => hatSegment.set(state.face.hat?.custom === true ? 'none' : (state.face.hat?.kind ?? 'none'))); + + // 帽子モデル(GLB)の取り込み。頭に乗るよう自動で位置と大きさを合わせる。 + const hatFilePicker = h('input', { type: 'file', accept: '.glb,.gltf,model/gltf-binary,model/gltf+json', style: { display: 'none' } }); + hatFilePicker.addEventListener('change', async () => { + const file = hatFilePicker.files?.[0]; + hatFilePicker.value = ''; + if (!file) return; + try { + await app.actions.loadHatModel(file); + toast(`帽子「${file.name}」を読み込みました`); + } catch (error) { + console.error(error); + toast('帽子モデルを読み込めませんでした(GLBをお使いください)'); + } + }); + hatSection.add(hatFilePicker); + hatSection.add(buttons({ + items: [{ id: 'hatfile', label: '帽子モデルを読み込む(GLB)', onClick: () => hatFilePicker.click() }], + })); + hatSection.add(hint('GLBの帽子を頭に乗せます。大きさと位置は自動で合わせます。')); const hatBox = details(hatSection.body, '位置と傾き'); const hatSliders = { |
