Files
RothenburgAR/Assets/RothenburgAR/Scripts/UI/DetailsPanelBehaviour.cs

191 lines
6.5 KiB
C#

using System;
using RothenburgAR.Common;
using RothenburgAR.PointOfInterest;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System.Threading;
namespace RothenburgAR.UI
{
public class DetailsPanelBehaviour : MonoBehaviour
{
public TextMeshProUGUI DetailsText;
public ScrollRect DetailsTextScrollRect;
public DetailsModelBehaviour DetailsModel;
public GameObject IconLoading;
public GameObject Icon3D;
private void Start()
{
gameObject.SetActive(false);
}
public bool HasModel
{
get { return _currentDisplayedModelGo != null; }
}
private GameObject _currentDisplayedModelGo;
public void SetText(TextElement el)
{
SetText(el.GetTextByLanguage(LanguageManager.Instance.CurrentLanguageKey));
}
public void SetText(String el)
{
DetailsText.text = el;
// Scroll to top
DetailsTextScrollRect.normalizedPosition = new Vector2(0, 1);
}
public void SetModelFromPoi(PoiData data)
{
if (!data.HasModelDescription) return;
StartCoroutine("SetModelCoroutine", data);
}
public IEnumerator SetModelCoroutine(PoiData data)
{
if (!data.IsModelLoaded)
{
StartCoroutine(data.LoadModel());
DetailsModel.gameObject.SetActive(true);
Icon3D.SetActive(true);
IconLoading.SetActive(true);
while (!data.IsModelLoaded)
{
// display loading icon or sth idk
IconLoading.transform.Rotate(new Vector3(0, 0, 1), -3f);
yield return new WaitForSecondsRealtime(.01f);
}
}
try
{
SetModel(data.InstantiateModelPrefab());
}
catch (Exception)
{
// ignore, just do not display an object
RemoveModel();
}
}
public void SetModel(GameObject modelGo)
{
modelGo.transform.SetParent(UIManager.Instance.UIObjectCamera.transform, false);
var meshFilter = modelGo.GetComponentInChildren<MeshFilter>();
if (meshFilter == null) throw new Exception("No MeshFilter in Object!");
var mesh = meshFilter.mesh;
if (mesh == null) throw new Exception("No Mesh in Model!");
//TODO remove when model metadata rotation is no longer a thing
mesh.RecalculateBounds();
var scale = 1f / Mathf.Max(mesh.bounds.size.x, mesh.bounds.size.y, mesh.bounds.size.z);
modelGo.transform.localScale = new Vector3(scale, scale, scale);
modelGo.transform.localPosition = mesh.bounds.center * scale + new Vector3(0, 0, 1.8f);
_currentDisplayedModelGo = modelGo;
DetailsModel.CurrentModel = _currentDisplayedModelGo;
DetailsModel.gameObject.SetActive(true);
Icon3D.SetActive(false);
IconLoading.SetActive(false);
}
public void RemoveModel()
{
DetailsModel.gameObject.SetActive(false);
DetailsModel.CurrentModel = null;
if (HasModel)
{
Destroy(_currentDisplayedModelGo);
_currentDisplayedModelGo = null;
Icon3D.SetActive(false);
IconLoading.SetActive(false);
}
}
public void UpdateOpeningAnimation(Vector3 position)
{
float duration = .4f;
var scale = DisplayManager.Instance.GetComponent<RectTransform>().localScale.x;
Vector3 screenMiddle = new Vector3(Screen.width / scale, Screen.height / scale, 0) * 0.5f;
Vector3 startPos = Camera.main.WorldToScreenPoint(position) / scale - screenMiddle;
Vector3 endPos = -screenMiddle + new Vector3(25, 25, 0);
float startScale = 0.05f;
float endScale = 1;
var anim = GetComponent<Animation>();
var clip = new AnimationClip
{
legacy = true,
name = "DetailsOpen"
};
// inTangent and outTangent are the curve's angles to and from this keyframe in radians.
// outTangent for all the first keyframe of all curves are set to directly point at the second frame,
// effectively disabling the easing and making it a linear motion.
// beware: setters for Keyframe.inTangent and Keyframe.outTangent seem to not work.
var curvePosX = new AnimationCurve();
curvePosX.AddKey(new Keyframe(0f, startPos.x, 0f, (endPos.x - startPos.x) / duration));
curvePosX.AddKey(new Keyframe(duration, endPos.x));
var curvePosY = new AnimationCurve();
curvePosY.AddKey(new Keyframe(0f, startPos.y, 0f, (endPos.y - startPos.y) / duration));
curvePosY.AddKey(new Keyframe(duration, endPos.y));
clip.SetCurve(string.Empty, typeof(Transform), "localPosition.x", curvePosX);
clip.SetCurve(string.Empty, typeof(Transform), "localPosition.y", curvePosY);
var curveScaleX = new AnimationCurve();
curveScaleX.AddKey(new Keyframe(0f, startScale, 0f, (endScale - startScale) / duration));
curveScaleX.AddKey(new Keyframe(duration, endScale));
var curveScaleY = new AnimationCurve();
curveScaleY.AddKey(new Keyframe(0f, startScale, 0f, (endScale - startScale) / duration));
curveScaleY.AddKey(new Keyframe(duration, endScale));
clip.SetCurve(string.Empty, typeof(Transform), "localScale.x", curveScaleX);
clip.SetCurve(string.Empty, typeof(Transform), "localScale.y", curveScaleY);
anim.AddClip(clip, clip.name);
anim.Play(clip.name);
}
public void OnDetailsPanelDrag(BaseEventData data)
{
DetailsModel.RotateModelByDrag(data as PointerEventData);
}
public void OnDetailsPanelPointerDown(BaseEventData data)
{
DetailsModel.BeginRotateModelByDrag(data as PointerEventData);
}
public void OnDetailsPanelEndDrag(BaseEventData data)
{
DetailsModel.EndRotateModelByDrag(data as PointerEventData);
}
private void OnDestroy()
{
RemoveModel();
}
}
}