MIF_E31230101/Assets/Script Manager/MenuCeritaDuaDialogControll...

426 lines
11 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using TMPro;
public class MenuCeritaDuaDialogController : MonoBehaviour
{
[Header("Dialog Atas")]
public Image imageAvatarAtas;
public TMP_Text textNamaAtas;
public TMP_Text textDialogAtas;
public CanvasGroup canvasDialogAtas;
public RectTransform rectDialogAtas;
[Header("Dialog Bawah")]
public Image imageAvatarBawah;
public TMP_Text textNamaBawah;
public TMP_Text textDialogBawah;
public CanvasGroup canvasDialogBawah;
public RectTransform rectDialogBawah;
[Header("Tombol")]
public Button buttonSebelumnya;
public Button buttonSelanjutnya;
public CanvasGroup canvasButtonSebelumnya;
public CanvasGroup canvasButtonSelanjutnya;
public RectTransform rectButtonSebelumnya;
public RectTransform rectButtonSelanjutnya;
[Header("Pengaturan Animasi")]
public float kecepatanKetik = 0.03f;
public float durasiMuncul = 0.2f;
public float alphaTombolAktif = 1f;
public float alphaTombolNonaktif = 0.45f;
[Header("Data Cerita")]
public DialogCerita[] daftarCerita;
private int indexCerita = 0;
// false = sedang berada di dialog atas
// true = sedang berada di dialog bawah
private bool sedangDialogBawah = false;
private bool sedangAnimasi = false;
private bool skipAnimasi = false;
private Coroutine coroutineAktif;
private Vector3 scaleNormal = Vector3.one;
private Vector3 scaleKecil = new Vector3(0.85f, 0.85f, 0.85f);
private Vector3 scaleTombolTekan = new Vector3(0.92f, 0.92f, 0.92f);
private void Start()
{
TampilkanCeritaBaru();
}
public void Selanjutnya()
{
if (!BisaSelanjutnya())
{
return;
}
if (rectButtonSelanjutnya != null)
{
StartCoroutine(AnimasiKlikTombol(rectButtonSelanjutnya));
}
// Jika animasi sedang berjalan, klik hanya untuk skip animasi
if (sedangAnimasi)
{
SkipAnimasiDialog();
return;
}
if (!sedangDialogBawah)
{
// Dari dialog atas lanjut ke dialog bawah
sedangDialogBawah = true;
JalankanCoroutine(TampilkanDialogBawah());
}
else
{
// Dari dialog bawah lanjut ke cerita berikutnya
if (indexCerita < daftarCerita.Length - 1)
{
indexCerita++;
sedangDialogBawah = false;
TampilkanCeritaBaru();
}
}
UpdateTombol();
}
public void Sebelumnya()
{
if (!BisaSebelumnya())
{
return;
}
if (rectButtonSebelumnya != null)
{
StartCoroutine(AnimasiKlikTombol(rectButtonSebelumnya));
}
// Jika animasi sedang berjalan dan tombol sebelumnya memang aktif,
// klik hanya untuk skip animasi
if (sedangAnimasi)
{
SkipAnimasiDialog();
return;
}
if (sedangDialogBawah)
{
// Dari dialog bawah kembali ke dialog atas
sedangDialogBawah = false;
SembunyikanDialogBawah();
}
else
{
// Dari dialog atas kembali ke cerita sebelumnya
if (indexCerita > 0)
{
indexCerita--;
sedangDialogBawah = true;
TampilkanCeritaSebelumnyaLengkap();
}
}
UpdateTombol();
}
public void KembaliKeMenuBelajar()
{
SceneManager.LoadScene("Menu Belajar");
}
private void TampilkanCeritaBaru()
{
if (daftarCerita == null || daftarCerita.Length == 0)
{
Debug.LogWarning("Data cerita belum diisi.");
return;
}
JalankanCoroutine(TampilkanDialogAtas());
UpdateTombol();
}
private IEnumerator TampilkanDialogAtas()
{
sedangAnimasi = true;
skipAnimasi = false;
UpdateTombol();
DialogCerita data = daftarCerita[indexCerita];
textNamaAtas.text = data.namaKarakterAtas;
textDialogAtas.text = "";
if (data.avatarAtas != null)
{
imageAvatarAtas.sprite = data.avatarAtas;
}
// Saat mulai cerita baru, dialog bawah disembunyikan dulu
canvasDialogBawah.alpha = 0;
textNamaBawah.text = "";
textDialogBawah.text = "";
canvasDialogAtas.alpha = 0;
rectDialogAtas.localScale = scaleKecil;
yield return StartCoroutine(FadeDanScale(canvasDialogAtas, rectDialogAtas, durasiMuncul));
yield return StartCoroutine(KetikTeks(textDialogAtas, data.dialogAtas));
textDialogAtas.text = data.dialogAtas;
canvasDialogAtas.alpha = 1;
rectDialogAtas.localScale = scaleNormal;
sedangAnimasi = false;
skipAnimasi = false;
UpdateTombol();
}
private IEnumerator TampilkanDialogBawah()
{
sedangAnimasi = true;
skipAnimasi = false;
UpdateTombol();
DialogCerita data = daftarCerita[indexCerita];
textNamaBawah.text = data.namaKarakterBawah;
textDialogBawah.text = "";
if (data.avatarBawah != null)
{
imageAvatarBawah.sprite = data.avatarBawah;
}
canvasDialogBawah.alpha = 0;
rectDialogBawah.localScale = scaleKecil;
yield return StartCoroutine(FadeDanScale(canvasDialogBawah, rectDialogBawah, durasiMuncul));
yield return StartCoroutine(KetikTeks(textDialogBawah, data.dialogBawah));
textDialogBawah.text = data.dialogBawah;
canvasDialogBawah.alpha = 1;
rectDialogBawah.localScale = scaleNormal;
sedangAnimasi = false;
skipAnimasi = false;
UpdateTombol();
}
private void SkipAnimasiDialog()
{
skipAnimasi = true;
DialogCerita data = daftarCerita[indexCerita];
if (!sedangDialogBawah)
{
textDialogAtas.text = data.dialogAtas;
canvasDialogAtas.alpha = 1;
rectDialogAtas.localScale = scaleNormal;
}
else
{
textDialogBawah.text = data.dialogBawah;
canvasDialogBawah.alpha = 1;
rectDialogBawah.localScale = scaleNormal;
}
}
private void TampilkanCeritaSebelumnyaLengkap()
{
if (daftarCerita == null || daftarCerita.Length == 0)
{
return;
}
HentikanCoroutineAktif();
DialogCerita data = daftarCerita[indexCerita];
textNamaAtas.text = data.namaKarakterAtas;
textDialogAtas.text = data.dialogAtas;
if (data.avatarAtas != null)
{
imageAvatarAtas.sprite = data.avatarAtas;
}
canvasDialogAtas.alpha = 1;
rectDialogAtas.localScale = scaleNormal;
textNamaBawah.text = data.namaKarakterBawah;
textDialogBawah.text = data.dialogBawah;
if (data.avatarBawah != null)
{
imageAvatarBawah.sprite = data.avatarBawah;
}
canvasDialogBawah.alpha = 1;
rectDialogBawah.localScale = scaleNormal;
sedangAnimasi = false;
skipAnimasi = false;
UpdateTombol();
}
private void SembunyikanDialogBawah()
{
canvasDialogBawah.alpha = 0;
textNamaBawah.text = "";
textDialogBawah.text = "";
UpdateTombol();
}
private IEnumerator FadeDanScale(CanvasGroup canvasGroup, RectTransform rectTransform, float durasi)
{
float waktu = 0f;
while (waktu < durasi)
{
if (skipAnimasi)
{
canvasGroup.alpha = 1;
rectTransform.localScale = scaleNormal;
yield break;
}
waktu += Time.deltaTime;
float t = waktu / durasi;
canvasGroup.alpha = Mathf.Lerp(0, 1, t);
rectTransform.localScale = Vector3.Lerp(scaleKecil, scaleNormal, t);
yield return null;
}
canvasGroup.alpha = 1;
rectTransform.localScale = scaleNormal;
}
private IEnumerator KetikTeks(TMP_Text targetText, string isiTeks)
{
targetText.text = "";
foreach (char huruf in isiTeks)
{
if (skipAnimasi)
{
targetText.text = isiTeks;
yield break;
}
targetText.text += huruf;
yield return new WaitForSeconds(kecepatanKetik);
}
targetText.text = isiTeks;
}
private IEnumerator AnimasiKlikTombol(RectTransform rectTombol)
{
rectTombol.localScale = scaleTombolTekan;
yield return new WaitForSeconds(0.08f);
rectTombol.localScale = scaleNormal;
}
private void JalankanCoroutine(IEnumerator coroutine)
{
HentikanCoroutineAktif();
coroutineAktif = StartCoroutine(coroutine);
}
private void HentikanCoroutineAktif()
{
if (coroutineAktif != null)
{
StopCoroutine(coroutineAktif);
coroutineAktif = null;
}
}
private bool BisaSebelumnya()
{
// Tombol sebelumnya aktif hanya jika:
// 1. Sudah bukan cerita pertama, atau
// 2. Sedang berada di dialog bawah.
// Di awal cerita dan dialog atas sedang animasi, tombol tetap nonaktif.
return indexCerita > 0 || sedangDialogBawah;
}
private bool BisaSelanjutnya()
{
// Tombol selanjutnya aktif jika:
// 1. Belum cerita terakhir, atau
// 2. Masih berada di dialog atas, atau
// 3. Sedang animasi untuk skip.
return indexCerita < daftarCerita.Length - 1 || !sedangDialogBawah || sedangAnimasi;
}
private void UpdateTombol()
{
bool sebelumnyaAktif = BisaSebelumnya();
bool selanjutnyaAktif = BisaSelanjutnya();
if (buttonSebelumnya != null)
{
buttonSebelumnya.interactable = sebelumnyaAktif;
}
if (buttonSelanjutnya != null)
{
buttonSelanjutnya.interactable = selanjutnyaAktif;
}
if (canvasButtonSebelumnya != null)
{
canvasButtonSebelumnya.alpha = sebelumnyaAktif ? alphaTombolAktif : alphaTombolNonaktif;
canvasButtonSebelumnya.blocksRaycasts = sebelumnyaAktif;
canvasButtonSebelumnya.interactable = sebelumnyaAktif;
}
if (canvasButtonSelanjutnya != null)
{
canvasButtonSelanjutnya.alpha = selanjutnyaAktif ? alphaTombolAktif : alphaTombolNonaktif;
canvasButtonSelanjutnya.blocksRaycasts = selanjutnyaAktif;
canvasButtonSelanjutnya.interactable = selanjutnyaAktif;
}
}
}
[System.Serializable]
public class DialogCerita
{
[Header("Dialog Atas")]
public string namaKarakterAtas;
[TextArea(2, 4)]
public string dialogAtas;
public Sprite avatarAtas;
[Header("Dialog Bawah")]
public string namaKarakterBawah;
[TextArea(2, 4)]
public string dialogBawah;
public Sprite avatarBawah;
}