using UnityEngine; using UnityEngine.UI; using System.Collections; public class SettingsManager : MonoBehaviour { [Header("ANIMASI MEKAR (Spacing)")] public VerticalLayoutGroup layoutGroup; public AnimationCurve bounceCurve; public float spacingTerbuka = 15f; public float spacingTertutup = -120f; // Isi negatif dari tinggi tombolmu (misal -120) private bool isSettingsOpen = false; [Header("ANIMASI GEAR (TOMBOL)")] public RectTransform gearButtonRect; public AnimationCurve gearRotationCurve; public float gearRotateAngle = -180f; public float gearScalePunch = 0.2f; [Header("UI GAMBAR TOMBOL")] public Image imageTombolMusic; public Sprite gambarMusicOn, gambarMusicOff; public Image imageTombolSFX; public Sprite gambarSFXOn, gambarSFXOff; [Header("PANEL INFO")] public GameObject panelInfo; void Start() { // Setup Tampilan Awal UI if(layoutGroup) layoutGroup.spacing = spacingTertutup; if(panelInfo) panelInfo.SetActive(false); RefreshTampilanMusic(); RefreshTampilanSFX(); } // ========================================== // LOGIKA BUKA TUTUP MENU // ========================================== public void ToggleSettings() { isSettingsOpen = !isSettingsOpen; StopAllCoroutines(); // Jalankan Animasi Mekar StartCoroutine(AnimateAccordion(isSettingsOpen)); // Jalankan Animasi Gear if (gearButtonRect) StartCoroutine(AnimateGearEffect()); // Putar suara klik kalau ada (Pake Audio Manager) if (Audio.instance) Audio.instance.PlayButtonSound(); } // ========================================== // LOGIKA MUSIK // ========================================== public void ToggleMusic() { bool isOn = PlayerPrefs.GetInt("MusicState", 1) == 1; PlayerPrefs.SetInt("MusicState", isOn ? 0 : 1); PlayerPrefs.Save(); RefreshTampilanMusic(); // Panggil Audio Manager buat update suara asli (Biar lagu mati/nyala) if (Audio.instance) Audio.instance.UpdateMuteState(); } void RefreshTampilanMusic() { bool isOn = PlayerPrefs.GetInt("MusicState", 1) == 1; if (imageTombolMusic) imageTombolMusic.sprite = isOn ? gambarMusicOn : gambarMusicOff; } // ========================================== // LOGIKA SFX // ========================================== public void ToggleSFX() { bool isOn = PlayerPrefs.GetInt("SFXState", 1) == 1; PlayerPrefs.SetInt("SFXState", isOn ? 0 : 1); PlayerPrefs.Save(); RefreshTampilanSFX(); // Panggil Audio Manager buat update suara asli (Biar sfx mati/nyala) if (Audio.instance) Audio.instance.UpdateMuteState(); } void RefreshTampilanSFX() { bool isOn = PlayerPrefs.GetInt("SFXState", 1) == 1; if (imageTombolSFX) imageTombolSFX.sprite = isOn ? gambarSFXOn : gambarSFXOff; } // ========================================== // ANIMASI (Gear & Accordion) // ========================================== IEnumerator AnimateGearEffect() { float timer = 0; float duration = 0.5f; float startZ = gearButtonRect.localEulerAngles.z; // Pakai logika penjumlahan float biasa biar Unity gak males muter (karena 0 dan 360 dianggap sama di Quaternion) float targetZ = startZ + gearRotateAngle; Vector3 defaultScale = Vector3.one; while (timer < duration) { timer += Time.deltaTime; float t = timer / duration; // 1. ROTASI float curveValue = gearRotationCurve.Evaluate(t); // Pakai LerpUnclamped pada angka biasa (bukan Quaternion) float currentZ = Mathf.LerpUnclamped(startZ, targetZ, curveValue); gearButtonRect.localRotation = Quaternion.Euler(0, 0, currentZ); // 2. SCALE (POP) float scalePop = Mathf.Sin(t * Mathf.PI) * gearScalePunch; gearButtonRect.localScale = defaultScale + new Vector3(scalePop, scalePop, 0); yield return null; } gearButtonRect.localRotation = Quaternion.Euler(0, 0, targetZ); gearButtonRect.localScale = defaultScale; } IEnumerator AnimateAccordion(bool open) { float timer = 0; float duration = 0.4f; float startSpacing = layoutGroup.spacing; float targetSpacing = open ? spacingTerbuka : spacingTertutup; while (timer < duration) { timer += Time.deltaTime; float t = timer / duration; float curveValue = bounceCurve.Evaluate(t); float currentSpacing = Mathf.LerpUnclamped(startSpacing, targetSpacing, curveValue); layoutGroup.spacing = currentSpacing; LayoutRebuilder.ForceRebuildLayoutImmediate(layoutGroup.GetComponent()); yield return null; } layoutGroup.spacing = targetSpacing; } // ========================================== // FUNGSI PANEL INFO & DOWNLOAD // ========================================== public void BukaInfo() { if(panelInfo) panelInfo.SetActive(true); // Opsional: Kalau mau Settings nutup otomatis pas buka info, uncomment baris bawah: // if(isSettingsOpen) ToggleSettings(); } public void TutupInfo() { if(panelInfo) panelInfo.SetActive(false); } public void BukaLinkMarker() { // GANTI LINK INI DENGAN LINK GOOGLE DRIVE KAMU YANG ASLI Application.OpenURL("https://drive.google.com/drive/folders/1Re0uyahA5GZs0nKJuijLtY039AXagxQ5?usp=sharing"); } }