-
- {/* HEADER */}
-
-
-
-
-
-
- - ROBOT VISION -
- {isRecordingUI && ( - - MEREKAM... - - )} - {isPlayingUI && ( - - MEMUTAR ULANG... - - )} -
-
-
-
-
-
-
- {/* (KAMERA & TOUCH CONTROLLER INLINE) */}
-
-
-
-
- {/* KOLOM KANAN (STATUS) */}
-
-
-
- {/* TOUCH UI BARU SESUAI DESAIN */}
- {controlMode === 'touch' && (
-
-
-
- - Live Feed -
- {/* TOMBOL FULL-SCREEN */} - -
-
{ e.currentTarget.style.display = 'none'; }} />
-
-
-
- {/* SISI KIRI: Aksi dan Slider Kamera */}
-
- )}
-
- {/* 4 Tombol Aksi Berjejer */}
-
-
- {/* SISI KANAN: D-Pad Pergerakan Salib */}
-
-
-
-
-
-
-
- {/* Slider Kamera di Bawah Tombol Aksi */}
-
- Q
- { touchStateRef.current.pan = Number(e.currentTarget.value); }}
- onPointerUp={(e) => {
- e.currentTarget.value = "0";
- touchStateRef.current.pan = 0;
- }}
- onPointerLeave={(e) => {
- e.currentTarget.value = "0";
- touchStateRef.current.pan = 0;
- }}
- className="w-full accent-red-500"
- />
- E
-
-
- {/* MAJU */}
-
-
- {/* KIRI DAN KANAN */}
-
-
-
-
-
-
- {/* MUNDUR */}
-
-
-
+ {/* LOADING SCREEN */}
+
-
-
- {/* Tombol aksi cadangan untuk UI Desktop */}
- - Status Kontrol - {controlMode === 'gamepad' && ( )} -
- -
-
-
- {controlMode === 'touch' ? '📱 AKTIF: DUAL-PAD SENTUH' : controlMode === 'keyboard' ? '⌨️ AKTIF: W-A-S-D & Q-E' : gamepadStatus}
-
-
-
-
- Visualizer Posisi
-
-
-
-
-
-
-
-
- X: {steering.x}Y: {steering.y}
-
-
-
- ⚙️ L: {ticks.l}⚙️ R: {ticks.r}
-
-
-
- Panel Cadangan Aksi
-
-
-
-
-
-
-
+
+
- {/* OVERLAY LAYAR PENUH (FULL SCREEN) LAYOUT BARU */}
- {isFullscreen && (
-
+
+ Menghubungkan ke Robot...
-
-
{ e.currentTarget.style.display = 'none'; }}
- />
+ {/* HEADER LOGO */}
+
+
+
-
-
- {/* AREA KONTROL OVERLAY */}
-
-
- {/* SISI KIRI: Aksi dan Slider Kamera */}
-
- {/* 4 Tombol Aksi Berjejer */}
-
-
- {/* SISI KANAN: D-Pad Pergerakan Salib */}
-
-
-
-
-
-
-
- {/* Slider Kamera di Bawah Tombol Aksi */}
-
- Q
- { touchStateRef.current.pan = Number(e.currentTarget.value); }}
- onPointerUp={(e) => {
- e.currentTarget.value = "0";
- touchStateRef.current.pan = 0;
- }}
- onPointerLeave={(e) => {
- e.currentTarget.value = "0";
- touchStateRef.current.pan = 0;
- }}
- className="w-full accent-red-500"
- />
- E
-
-
- {/* MAJU */}
-
-
- {/* KIRI DAN KANAN */}
-
+ {/* MAIN CAMERA FEED & OVERLAY LAYOUT */}
+
-
-
-
-
- {/* MUNDUR */}
-
-
+
+ {/* Stream Kamera */}
+
{ e.currentTarget.style.display = 'none'; }} />
+
+ {/* Indikator Status Perekaman */}
+ {(isRecordingRef.current || isPlayingRef.current) && (
+
+
+ {/* FOOTER TEXT */}
+
);
}
\ No newline at end of file
+ {isRecordingRef.current && MEREKAM}
+ {isPlayingRef.current && MEMUTAR RUTE}
+
+ )}
+ {/* OVERLAY: TOP BAR */}
+
+
- )}
+ {/* OVERLAY: FULLSCREEN */}
+
+
+ {/* OVERLAY: BOTTOM LEFT (MOVEMENT CONTROLS) */}
+
+
+
+ {controlMode === 'pc-mobile' ? (
+
+
+ {/* OVERLAY: BOTTOM RIGHT (ACTION CONTROLS) */}
+
+
+
+ ) : (
+
+
+
+
+
+
+
+ )}
+
+
+ 0.1 ? 'bg-white text-slate-900 border-white' : 'bg-white/20 text-white border-white/50 backdrop-blur-sm'}`}>LT
+ 0.1 ? 'bg-white text-slate-900 border-white' : 'bg-white/20 text-white border-white/50 backdrop-blur-sm'}`}>RT
+
+
+ ←
+
+ →
+
+ {[
+ { action: 'RECORD', pc: 'V', gp: 'B', color: 'bg-red-500 shadow-[0_4px_0_#b91c1c]', activeColor: 'active:bg-red-600', gpState: gpVisuals.btnB },
+ { action: 'SAVE', pc: 'B', gp: 'Y', color: 'bg-amber-400 shadow-[0_4px_0_#d97706]', activeColor: 'active:bg-amber-500', gpState: gpVisuals.btnY },
+ { action: 'PLAY_FWD', pc: 'N', gp: 'A', color: 'bg-emerald-500 shadow-[0_4px_0_#047857]', activeColor: 'active:bg-emerald-600', gpState: gpVisuals.btnA },
+ { action: 'PLAY_REV', pc: 'M', gp: 'X', color: 'bg-blue-600 shadow-[0_4px_0_#1d4ed8]', activeColor: 'active:bg-blue-700', gpState: gpVisuals.btnX }
+ ].map((btn) => (
+
+
+
+ {btn.action === 'PLAY_FWD' ? 'PLAY' : btn.action === 'PLAY_REV' ? 'R-PLAY' : btn.action}
+
+
+
+ ))}
+