using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.InputSystem; using TMPro; // WAJIB TAMBAH INI using Vuforia; public class BookPageManager : MonoBehaviour { [System.Serializable] public class MoleculeSlot { public string name; public GameObject model; [HideInInspector] public Vector3 originalPos; [HideInInspector] public Quaternion originalRot; [HideInInspector] public Vector3 originalScale; } public List moleculeSlots; [Header("UI References")] public GameObject panelInfo; // Tarik Panel Info ke sini public TextMeshProUGUI textNamaMolekul; // Tarik Teks Nama ke sini [Header("Focus Settings")] public Vector3 centerOffset = new Vector3(0, 0.05f, 0); public float focusScaleMultiplier = 2.5f; public float transitionSpeed = 5f; private int focusedIndex = -1; private bool isTransitioning = false; private ObserverBehaviour mObserverBehaviour; void Awake() { mObserverBehaviour = GetComponent(); } void Start() { foreach (var slot in moleculeSlots) { if (slot.model != null) { slot.originalPos = slot.model.transform.localPosition; slot.originalRot = slot.model.transform.localRotation; slot.originalScale = slot.model.transform.localScale; } } } public bool IsTracked() { return mObserverBehaviour != null && (mObserverBehaviour.TargetStatus.Status == Status.TRACKED || mObserverBehaviour.TargetStatus.Status == Status.EXTENDED_TRACKED); } void Update() { // PENTING: Update UI setiap frame untuk mengecek kondisi tracking UpdateUI(); if (isTransitioning) return; if (Pointer.current != null && Pointer.current.press.wasPressedThisFrame) { if (Camera.main == null) return; Vector2 touchPosition = Pointer.current.position.ReadValue(); Ray ray = Camera.main.ScreenPointToRay(touchPosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { for (int i = 0; i < moleculeSlots.Count; i++) { if (moleculeSlots[i].model != null) { if (hit.transform.IsChildOf(moleculeSlots[i].model.transform)) { if (focusedIndex == -1) FocusMolecule(i); else ResetMolecules(); break; } } } } } } // --- LOGIKA BARU: UPDATE UI --- void UpdateUI() { if (panelInfo == null || textNamaMolekul == null) return; // Jika halaman buku sedang di-scan DAN ada molekul yang difokuskan if (IsTracked() && focusedIndex != -1) { panelInfo.SetActive(true); textNamaMolekul.text = moleculeSlots[focusedIndex].name; } else { // Cek apakah Manager sedang menampilkan sesuatu. // Jika tidak, baru panel dimatikan agar tidak bentrok. // Untuk amannya, kita matikan panel jika tracking buku hilang atau tidak ada fokus. if (focusedIndex == -1 || !IsTracked()) { // Kita biarkan saja jika ingin panel hilang otomatis saat ResetMolecules atau Tracking Lost // Namun panel akan dikontrol ulang oleh Manager.cs jika kartu di-scan } } } void FocusMolecule(int index) { focusedIndex = index; StartCoroutine(TransitionMolecule(index, true)); } public void ResetMolecules() { if (focusedIndex != -1) { StartCoroutine(TransitionMolecule(focusedIndex, false)); focusedIndex = -1; // Matikan panel saat reset if (panelInfo != null) panelInfo.SetActive(false); } } IEnumerator TransitionMolecule(int index, bool focusing) { isTransitioning = true; GameObject target = moleculeSlots[index].model; Vector3 targetPos = focusing ? centerOffset : moleculeSlots[index].originalPos; Vector3 targetScale = focusing ? (moleculeSlots[index].originalScale * focusScaleMultiplier) : moleculeSlots[index].originalScale; Quaternion targetRot = focusing ? Quaternion.identity : moleculeSlots[index].originalRot; if (focusing) { foreach (var slot in moleculeSlots) if (slot != moleculeSlots[index] && slot.model != null) slot.model.SetActive(false); } float t = 0; Vector3 startPos = target.transform.localPosition; Vector3 startScale = target.transform.localScale; Quaternion startRot = target.transform.localRotation; while (t < 1f) { t += Time.deltaTime * transitionSpeed; target.transform.localPosition = Vector3.Lerp(startPos, targetPos, t); target.transform.localScale = Vector3.Lerp(startScale, targetScale, t); target.transform.localRotation = Quaternion.Lerp(startRot, targetRot, t); yield return null; } if (!focusing) { foreach (var slot in moleculeSlots) if (slot.model != null) slot.model.SetActive(true); } isTransitioning = false; } public GameObject GetFocusedMolecule() { if (focusedIndex != -1) return moleculeSlots[focusedIndex].model; return null; } }