669 lines
18 KiB
C#
669 lines
18 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
using Vuforia;
|
|
using UnityEngine.UI;
|
|
|
|
[System.Serializable]
|
|
public class AtomMarkerInfo
|
|
{
|
|
public string markerName;
|
|
public ObserverBehaviour marker;
|
|
|
|
[TextArea]
|
|
public string description;
|
|
public string displayName;
|
|
public AudioClip audioClip;
|
|
|
|
[HideInInspector] public bool isTracked;
|
|
}
|
|
|
|
public class AtomCombinerManager : MonoBehaviour
|
|
{
|
|
[Header("Combinations")]
|
|
public AtomCombination[] combinations;
|
|
public float maxCombineDistance = 2f;
|
|
public float combineDelay = 0.5f;
|
|
|
|
[Header("Single Marker Info")]
|
|
public AtomMarkerInfo[] markerInfos;
|
|
|
|
[Header("UI")]
|
|
public TextMeshProUGUI txtNama;
|
|
public TextMeshProUGUI txtDeskripsi;
|
|
public TextMeshProUGUI txtInfomasiScan;
|
|
public UnityEngine.UI.Image imageNama;
|
|
public UnityEngine.UI.Image imageDes;
|
|
|
|
|
|
|
|
[Header("Audio")]
|
|
public AudioSource audioSource;
|
|
|
|
private int lastPlayedIndex = -1;
|
|
private bool isAudioPlayingFromMarker = false;
|
|
|
|
void Start()
|
|
{
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.markerA == null || combo.markerB == null || combo.resultObject == null)
|
|
{
|
|
Debug.LogError("[ERROR] Missing reference in combination");
|
|
continue;
|
|
}
|
|
|
|
combo.resultObject.SetActive(false);
|
|
|
|
var tempCombo = combo;
|
|
tempCombo.markerA.OnTargetStatusChanged += (behaviour, status) => { tempCombo.aTracked = IsTracked(status); };
|
|
tempCombo.markerB.OnTargetStatusChanged += (behaviour, status) => { tempCombo.bTracked = IsTracked(status); };
|
|
}
|
|
|
|
for (int i = 0; i < markerInfos.Length; i++)
|
|
{
|
|
int index = i;
|
|
markerInfos[i].marker.OnTargetStatusChanged += (behaviour, status) =>
|
|
{
|
|
markerInfos[index].isTracked = IsTracked(status);
|
|
};
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
bool anyCombinationActive = false;
|
|
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.aTracked && combo.bTracked)
|
|
{
|
|
float distance = Vector3.Distance(combo.markerA.transform.position, combo.markerB.transform.position); //JARAK PENGGABUNGAN PAKAI POSISI
|
|
|
|
if (distance <= maxCombineDistance)
|
|
{
|
|
combo.timer += Time.deltaTime;
|
|
|
|
if (combo.timer >= combineDelay && !combo.isCombined)
|
|
{
|
|
ActivateCombination(combo);
|
|
}
|
|
|
|
if (combo.isCombined)
|
|
{
|
|
UpdateResultPosition(combo);
|
|
anyCombinationActive = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (combo.isCombined)
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
}
|
|
|
|
//DIPERBARUI
|
|
if (!anyCombinationActive)
|
|
{
|
|
ResetAllCombinations();
|
|
|
|
bool singleMarkerFound = false;
|
|
|
|
foreach (var markerInfo in markerInfos)
|
|
{
|
|
if (markerInfo.isTracked)
|
|
{
|
|
ShowOnlyMarkerModel(markerInfo);
|
|
ShowMarkerInfo(markerInfo);
|
|
singleMarkerFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Cek apakah salah satu marker kombinasi terdeteksi
|
|
bool partialComboTracked = false;
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.aTracked || combo.bTracked)
|
|
{
|
|
partialComboTracked = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Tampilkan atau sembunyikan panel informasi sesuai kondisi
|
|
if (!singleMarkerFound && !partialComboTracked)
|
|
{
|
|
ShowScanInstruction(); // tampilkan petunjuk jika tidak ada marker apapun
|
|
StopAudioIfPlaying();
|
|
}
|
|
else
|
|
{
|
|
if (txtInfomasiScan != null)
|
|
txtInfomasiScan.gameObject.SetActive(false); // sembunyikan petunjuk
|
|
}
|
|
}
|
|
}
|
|
|
|
void ActivateCombination(AtomCombination combo)
|
|
{
|
|
foreach (var otherCombo in combinations)
|
|
{
|
|
if (otherCombo != combo)
|
|
{
|
|
ResetCombination(otherCombo);
|
|
}
|
|
}
|
|
|
|
combo.resultObject.SetActive(true);
|
|
combo.isCombined = true;
|
|
ShowMarkerModels(combo, false);
|
|
|
|
SetUI(combo.displayName, combo.description, true);
|
|
|
|
if (combo.audioClip != null)
|
|
{
|
|
if (audioSource.clip != combo.audioClip || !audioSource.isPlaying)
|
|
{
|
|
audioSource.clip = combo.audioClip;
|
|
audioSource.loop = true;
|
|
audioSource.Play();
|
|
}
|
|
lastPlayedIndex = System.Array.IndexOf(combinations, combo);
|
|
isAudioPlayingFromMarker = false;
|
|
}
|
|
}
|
|
/*void ActivateCombination(AtomCombination combo)
|
|
{
|
|
foreach (var otherCombo in combinations)
|
|
{
|
|
if (otherCombo != combo)
|
|
{
|
|
ResetCombination(otherCombo);
|
|
}
|
|
}
|
|
|
|
combo.resultObject.SetActive(true);
|
|
combo.isCombined = true;
|
|
ShowMarkerModels(combo, false);
|
|
|
|
SetUI(combo.displayName, combo.description, true);
|
|
|
|
if (combo.audioClip != null && (!audioSource.isPlaying || audioSource.clip != combo.audioClip))
|
|
{
|
|
audioSource.clip = combo.audioClip;
|
|
audioSource.Play();
|
|
lastPlayedIndex = System.Array.IndexOf(combinations, combo);
|
|
isAudioPlayingFromMarker = true;
|
|
}
|
|
}*/
|
|
|
|
void ResetCombination(AtomCombination combo)
|
|
{
|
|
combo.timer = 0f;
|
|
|
|
if (combo.isCombined)
|
|
{
|
|
combo.resultObject.SetActive(false);
|
|
combo.isCombined = false;
|
|
ShowMarkerModels(combo, true);
|
|
|
|
if (audioSource.clip == combo.audioClip)
|
|
{
|
|
audioSource.Stop();
|
|
audioSource.loop = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ResetAllCombinations()
|
|
{
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.isCombined)
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
|
|
lastPlayedIndex = -1;
|
|
}
|
|
|
|
void ShowScanInstruction()
|
|
{
|
|
SetUI("", "", false);
|
|
|
|
if (txtInfomasiScan != null)
|
|
txtInfomasiScan.gameObject.SetActive(true);
|
|
}
|
|
|
|
void SetUI(string nama, string deskripsi, bool showImages)
|
|
{
|
|
if (txtNama != null) txtNama.text = nama;
|
|
if (txtDeskripsi != null) txtDeskripsi.text = deskripsi;
|
|
|
|
if (imageNama != null) imageNama.gameObject.SetActive(showImages);
|
|
if (imageDes != null) imageDes.gameObject.SetActive(showImages);
|
|
|
|
if (txtInfomasiScan != null)
|
|
txtInfomasiScan.gameObject.SetActive(!showImages);
|
|
}
|
|
|
|
void ShowMarkerInfo(AtomMarkerInfo info)
|
|
{
|
|
SetUI(info.displayName, info.description, true);
|
|
|
|
if (info.audioClip != null && (!audioSource.isPlaying || audioSource.clip != info.audioClip))
|
|
{
|
|
audioSource.clip = info.audioClip;
|
|
audioSource.Play();
|
|
isAudioPlayingFromMarker = true;
|
|
}
|
|
}
|
|
|
|
void ShowOnlyMarkerModel(AtomMarkerInfo info)
|
|
{
|
|
HideAllMarkerModels();
|
|
|
|
foreach (Transform child in info.marker.transform)
|
|
{
|
|
child.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
void ShowMarkerModels(AtomCombination combo, bool show)
|
|
{
|
|
foreach (Transform child in combo.markerA.transform)
|
|
child.gameObject.SetActive(show);
|
|
|
|
foreach (Transform child in combo.markerB.transform)
|
|
child.gameObject.SetActive(show);
|
|
}
|
|
|
|
void HideAllMarkerModels()
|
|
{
|
|
foreach (var info in markerInfos)
|
|
{
|
|
foreach (Transform child in info.marker.transform)
|
|
{
|
|
child.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateResultPosition(AtomCombination combo)
|
|
{
|
|
if (Camera.main == null) return;
|
|
|
|
Vector3 midPoint = (combo.markerA.transform.position + combo.markerB.transform.position) / 2f;
|
|
combo.resultObject.transform.position = Vector3.Lerp(combo.resultObject.transform.position, midPoint, Time.deltaTime * 5f);
|
|
|
|
Vector3 lookDir = Camera.main.transform.position - combo.resultObject.transform.position;
|
|
lookDir.y = 0;
|
|
if (lookDir != Vector3.zero)
|
|
{
|
|
combo.resultObject.transform.rotation = Quaternion.LookRotation(lookDir);
|
|
}
|
|
}
|
|
|
|
bool IsTracked(TargetStatus status)
|
|
{
|
|
return status.Status == Status.TRACKED;
|
|
}
|
|
|
|
void StopAudioIfPlaying()
|
|
{
|
|
if (isAudioPlayingFromMarker && audioSource.isPlaying)
|
|
{
|
|
audioSource.Stop();
|
|
isAudioPlayingFromMarker = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*using UnityEngine;
|
|
using TMPro;
|
|
using Vuforia;
|
|
|
|
[System.Serializable]
|
|
public class AtomMarkerInfo
|
|
{
|
|
public string markerName;
|
|
public ObserverBehaviour marker;
|
|
|
|
[TextArea]
|
|
public string description;
|
|
public string displayName;
|
|
public AudioClip audioClip;
|
|
|
|
[HideInInspector] public bool isTracked;
|
|
}
|
|
|
|
public class AtomCombinerManager : MonoBehaviour
|
|
{
|
|
[Header("Combinations")]
|
|
public AtomCombination[] combinations;
|
|
public float maxCombineDistance = 2f;
|
|
public float combineDelay = 0.5f;
|
|
|
|
[Header("Single Marker Info")]
|
|
public AtomMarkerInfo[] markerInfos;
|
|
|
|
[Header("UI")]
|
|
public TextMeshProUGUI txtNama;
|
|
public TextMeshProUGUI txtDeskripsi;
|
|
|
|
[Header("Audio")]
|
|
public AudioSource audioSource;
|
|
|
|
*//*[Header("Panel UI")]
|
|
public GameObject panelPenanda; // Tambahan: Panel untuk prompt jika tidak ada marker
|
|
public GameObject panelDeskripsi; // Tambahan: Panel untuk deskripsi saat marker aktif*//*
|
|
|
|
private int lastPlayedIndex = -1;
|
|
|
|
void Start()
|
|
{
|
|
for (int i = 0; i < combinations.Length; i++)
|
|
{
|
|
var combo = combinations[i];
|
|
|
|
if (combo.markerA == null || combo.markerB == null || combo.resultObject == null)
|
|
{
|
|
Debug.LogError($"[ERROR] Missing reference in combination index {i}");
|
|
continue;
|
|
}
|
|
|
|
combo.resultObject.SetActive(false);
|
|
int index = i;
|
|
|
|
combo.markerA.OnTargetStatusChanged += (behaviour, status) =>
|
|
{
|
|
combinations[index].aTracked = IsTracked(status);
|
|
};
|
|
|
|
combo.markerB.OnTargetStatusChanged += (behaviour, status) =>
|
|
{
|
|
combinations[index].bTracked = IsTracked(status);
|
|
};
|
|
}
|
|
|
|
for (int i = 0; i < markerInfos.Length; i++)
|
|
{
|
|
int index = i;
|
|
markerInfos[i].marker.OnTargetStatusChanged += (behaviour, status) =>
|
|
{
|
|
markerInfos[index].isTracked = IsTracked(status);
|
|
};
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
bool anyCombinationActive = false;
|
|
|
|
for (int i = 0; i < combinations.Length; i++)
|
|
{
|
|
var combo = combinations[i];
|
|
bool bothTracked = combo.aTracked && combo.bTracked;
|
|
|
|
if (bothTracked)
|
|
{
|
|
float distance = Vector3.Distance(combo.markerA.transform.position, combo.markerB.transform.position);
|
|
Debug.Log($"[COMBO {i}] A tracked: {combo.aTracked}, B tracked: {combo.bTracked}, Distance: {distance}");
|
|
|
|
if (distance <= maxCombineDistance)
|
|
{
|
|
combo.timer += Time.deltaTime;
|
|
|
|
if (combo.timer >= combineDelay && !combo.isCombined)
|
|
{
|
|
ActivateCombination(combo, i);
|
|
}
|
|
|
|
if (combo.isCombined)
|
|
{
|
|
UpdateResultPosition(combo);
|
|
anyCombinationActive = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (combo.isCombined)
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!anyCombinationActive)
|
|
{
|
|
bool singleMarkerFound = false;
|
|
ResetAllCombinations();
|
|
|
|
foreach (var markerInfo in markerInfos)
|
|
{
|
|
if (markerInfo.isTracked)
|
|
{
|
|
ShowOnlyMarkerModel(markerInfo); // tampilkan hanya marker ini
|
|
ShowMarkerInfo(markerInfo);
|
|
singleMarkerFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!singleMarkerFound)
|
|
{
|
|
ClearUI();
|
|
}
|
|
}
|
|
|
|
*//* // Tambahan: Perbarui tampilan panel berdasarkan kondisi marker
|
|
UpdatePanels(anyCombinationActive);*//*
|
|
}
|
|
|
|
void ActivateCombination(AtomCombination combo, int index)
|
|
{
|
|
foreach (var otherCombo in combinations)
|
|
{
|
|
if (otherCombo != combo)
|
|
{
|
|
ResetCombination(otherCombo);
|
|
}
|
|
}
|
|
|
|
combo.resultObject.SetActive(true);
|
|
combo.isCombined = true;
|
|
ShowMarkerModels(combo, false);
|
|
Debug.Log($"[COMBINED] {combo.combinationName}");
|
|
|
|
if (txtNama != null) txtNama.text = combo.displayName;
|
|
if (txtDeskripsi != null) txtDeskripsi.text = combo.description;
|
|
|
|
if (combo.audioClip != null && (!audioSource.isPlaying || lastPlayedIndex != index))
|
|
{
|
|
audioSource.clip = combo.audioClip;
|
|
audioSource.Play();
|
|
lastPlayedIndex = index;
|
|
}
|
|
}
|
|
|
|
void ResetCombination(AtomCombination combo)
|
|
{
|
|
combo.timer = 0f;
|
|
|
|
if (combo.isCombined)
|
|
{
|
|
combo.resultObject.SetActive(false);
|
|
combo.isCombined = false;
|
|
ShowMarkerModels(combo, true);
|
|
Debug.Log($"[RESET] {combo.combinationName}");
|
|
}
|
|
}
|
|
|
|
void ResetAllCombinations()
|
|
{
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.isCombined)
|
|
{
|
|
ResetCombination(combo);
|
|
}
|
|
}
|
|
|
|
lastPlayedIndex = -1;
|
|
}
|
|
|
|
void ClearUI()
|
|
{
|
|
if (txtNama != null) txtNama.text = "";
|
|
if (txtDeskripsi != null) txtDeskripsi.text = "";
|
|
|
|
if (audioSource.isPlaying)
|
|
{
|
|
audioSource.Stop();
|
|
lastPlayedIndex = -1;
|
|
ResetAllCombinations();
|
|
}
|
|
|
|
HideAllMarkerModels();
|
|
}
|
|
|
|
void ShowMarkerModels(AtomCombination combo, bool show)
|
|
{
|
|
foreach (Transform child in combo.markerA.transform)
|
|
child.gameObject.SetActive(show);
|
|
|
|
foreach (Transform child in combo.markerB.transform)
|
|
child.gameObject.SetActive(show);
|
|
}
|
|
|
|
void HideAllMarkerModels()
|
|
{
|
|
foreach (var info in markerInfos)
|
|
{
|
|
foreach (Transform child in info.marker.transform)
|
|
{
|
|
child.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ShowOnlyMarkerModel(AtomMarkerInfo info)
|
|
{
|
|
HideAllMarkerModels();
|
|
|
|
foreach (Transform child in info.marker.transform)
|
|
{
|
|
child.gameObject.SetActive(true);
|
|
}
|
|
}
|
|
|
|
void UpdateResultPosition(AtomCombination combo)
|
|
{
|
|
if (Camera.main == null) return;
|
|
|
|
Vector3 midPoint = (combo.markerA.transform.position + combo.markerB.transform.position) / 2f;
|
|
combo.resultObject.transform.position = Vector3.Lerp(
|
|
combo.resultObject.transform.position,
|
|
midPoint,
|
|
Time.deltaTime * 5f
|
|
);
|
|
|
|
Vector3 lookDir = Camera.main.transform.position - combo.resultObject.transform.position;
|
|
lookDir.y = 0;
|
|
|
|
if (lookDir != Vector3.zero)
|
|
{
|
|
combo.resultObject.transform.rotation = Quaternion.LookRotation(lookDir);
|
|
}
|
|
}
|
|
|
|
void ShowMarkerInfo(AtomMarkerInfo info)
|
|
{
|
|
if (txtNama != null) txtNama.text = info.displayName;
|
|
if (txtDeskripsi != null) txtDeskripsi.text = info.description;
|
|
|
|
if (info.audioClip != null && (!audioSource.isPlaying || audioSource.clip != info.audioClip))
|
|
{
|
|
audioSource.clip = info.audioClip;
|
|
audioSource.Play();
|
|
}
|
|
}
|
|
|
|
bool IsTracked(TargetStatus status)
|
|
{
|
|
return status.Status == Status.TRACKED;
|
|
}
|
|
|
|
*//* // Tambahan: Fungsi untuk mengatur tampilan panel UI sesuai logika tabel
|
|
void UpdatePanels(bool adaKombinasiAktif)
|
|
{
|
|
bool markerTunggalAktif = false;
|
|
bool hanyaSatuMarkerKombinasi = false;
|
|
|
|
int markerKombinasiTerpantau = 0;
|
|
|
|
foreach (var marker in markerInfos)
|
|
{
|
|
if (marker.isTracked)
|
|
{
|
|
markerTunggalAktif = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
foreach (var combo in combinations)
|
|
{
|
|
if (combo.aTracked) markerKombinasiTerpantau++;
|
|
if (combo.bTracked) markerKombinasiTerpantau++;
|
|
}
|
|
|
|
hanyaSatuMarkerKombinasi = (markerKombinasiTerpantau == 1);
|
|
|
|
if (!adaKombinasiAktif && !markerTunggalAktif && !hanyaSatuMarkerKombinasi)
|
|
{
|
|
if (panelPenanda != null) panelPenanda.SetActive(true);
|
|
if (panelDeskripsi != null) panelDeskripsi.SetActive(false);
|
|
}
|
|
else if (adaKombinasiAktif)
|
|
{
|
|
if (panelPenanda != null) panelPenanda.SetActive(false);
|
|
if (panelDeskripsi != null) panelDeskripsi.SetActive(true);
|
|
}
|
|
else if (markerTunggalAktif)
|
|
{
|
|
if (panelPenanda != null) panelPenanda.SetActive(false);
|
|
if (panelDeskripsi != null) panelDeskripsi.SetActive(true);
|
|
}
|
|
else if (hanyaSatuMarkerKombinasi)
|
|
{
|
|
if (panelPenanda != null) panelPenanda.SetActive(false);
|
|
if (panelDeskripsi != null) panelDeskripsi.SetActive(false);
|
|
}
|
|
}*//*
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |