UX: karaktere tiklayinca siradaki soze gec, blok numarasi gostergesi

- Karaktere tek tikla: o kisinin bir sonraki repligine atlar ve oynatir
  (oncesinde cift tik sadece ilk sozune gidiyordu)
- Sag ustte kucuk #blokNo gostergesi (hangi replikte oldugunu gormek icin)
- Kaan/Marissa koltuklari hafif ice alindi (-1.6/1.6 -> -1.36/1.36)
- Ipucu metni guncellendi

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
yilsem
2026-07-04 07:29:24 +03:00
co-authored by Claude Sonnet 5
parent 926682117b
commit 122790ac91
+19 -6
View File
@@ -62,6 +62,7 @@
<button data-m="orig" class="on">🔊 Orijinal</button>
<button data-m="tr">🇹🇷 Türkçe</button>
</div>
<span id="lineId" style="pointer-events:auto;font-size:9px;color:#484f58;margin-left:8px">#—</span>
</div>
<div id="legend"><b>Masadaki kişiler</b><div id="legendRows"></div></div>
<div id="subtitle">
@@ -77,7 +78,7 @@
<button class="btn" id="next" title="Sonraki konuşma"></button>
<span id="time">00:00 / 00:00</span>
<div class="spacer"></div>
<span id="hint">Zaman çizelgesine tıkla/sürükle · fareyle sahneyi döndür · çift tık kişi→ilk sözü</span>
<span id="hint">Zaman çizelgesine tıkla/sürükle · fareyle sahneyi döndür · kişiye tıkla → sıradaki sözü</span>
</div>
</div>
<div id="loadErr" style="display:none;position:fixed;inset:0;z-index:999;background:#0d1117;color:#e6edf3;
@@ -104,7 +105,7 @@ function showLoadErr(msg){
if(typeof MEET==='undefined'){ showLoadErr('data.js yüklenemedi veya bozuk (MEET tanımsız)'); throw new Error('MEET tanımsız — data.js yüklenemedi'); }
const ROLES=MEET.roles, TL=MEET.TL;
const POS3D={
"Kaan":{x:-1.6,z:2.3,stand:false}, "Marissa":{x:1.6,z:2.3,stand:false},
"Kaan":{x:-1.36,z:2.3,stand:false}, "Marissa":{x:1.36,z:2.3,stand:false},
"Dolandırıcı (D-)":{x:-1.6,z:-2.3,stand:false}, "Uzlaşmacı (U)":{x:0.4,z:-2.3,stand:false},
"Yaşlı adam (V)":{x:-3.7,z:0,stand:false}, "Lider Uzlaşmacı (L.U)":{x:3.7,z:0,stand:false},
"Kayınvalide":{x:3.3,z:-2.6,stand:true}
@@ -249,6 +250,7 @@ let lastRole=null;
function highlight(role){ if(role===lastRole)return; lastRole=role; for(const r in chars){ const on=(r===role); chars[r].active=on; chars[r].ring.visible=on; chars[r].bulb.visible=on; chars[r].halo.visible=on; if(!on)chars[r].blight.intensity=0; } }
const fmt=function(s){s=Math.max(0,s|0);return String(s/60|0).padStart(2,'0')+':'+String(s%60).padStart(2,'0');};
const sub=document.getElementById('subtitle'),sW=document.getElementById('subWho'),sO=document.getElementById('subOrig'),sT=document.getElementById('subTr');
const lineIdEl=document.getElementById('lineId');
function update(){
const a=A(), T=curTL(), dur=curDur();
document.getElementById('time').textContent=fmt(a.currentTime)+' / '+fmt(dur);
@@ -257,7 +259,8 @@ function update(){
let badge=(mode==='tr'&&!TR_READY())?' <span class="badge">ses hazırlanıyor</span>':'';
sW.innerHTML=(SHORT[b.rol]||b.rol)+badge; sW.style.color=(ROLES[b.rol]&&ROLES[b.rol].renk)||'#fff';
sO.textContent=b.orig; sT.textContent=b.tr; sub.style.opacity=1;
} else { highlight(null); sub.style.opacity=.6; }
lineIdEl.textContent='#'+i;
} else { highlight(null); sub.style.opacity=.6; lineIdEl.textContent='#—'; }
drawTL();
}
ao.addEventListener('timeupdate',function(){if(mode==='orig'||!TR_READY())update();});
@@ -280,14 +283,24 @@ document.getElementById('langToggle').addEventListener('click',function(e){
fitTL(); update(); if(wasPlaying){A().play();playBtn.textContent='⏸';}
});
renderer.domElement.addEventListener('dblclick',function(ev){
const roleNextIdx={};
function linesForRole(role){ return curTL().filter(function(x){return x.rol===role;}); }
renderer.domElement.addEventListener('click',function(ev){
const rc=new THREE.Raycaster(), m=new THREE.Vector2((ev.clientX/innerWidth)*2-1,-(ev.clientY/innerHeight)*2+1);
rc.setFromCamera(m,camera);
const gs=Object.keys(chars).map(function(r){return chars[r].grp;});
const hit=rc.intersectObjects(gs,true)[0]; if(!hit)return;
let g=hit.object; while(g.parent&&gs.indexOf(g)<0)g=g.parent;
const role=Object.keys(chars).find(function(r){return chars[r].grp===g;});
const T=curTL(), b=T.find(function(x){return x.rol===role;}); if(b){A().currentTime=b.t;update();}
const role=Object.keys(chars).find(function(r){return chars[r].grp===g;}); if(!role)return;
const lines=linesForRole(role); if(!lines.length)return;
let idx=roleNextIdx[role]||0;
if(idx>=lines.length)idx=0;
const b=lines[idx];
const a=A();
a.currentTime=Math.max(0,b.t-0.1);
roleNextIdx[role]=idx+1;
update();
a.play(); playBtn.textContent='⏸';
});
function loop(){