/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal
{
using UnityEngine;
using UnityEngine.EventSystems;
/// A controller for handling multi screens.
public class MultiScreenController : MonoBehaviour, ISystemButtonStateProvider
{
private SystemButtonState m_SystemButtonState = new SystemButtonState();
private ISystemButtonStateReceiver m_Receiver;
/// System defined button.
[SerializeField]
private NRButton Trigger;
/// The application.
[SerializeField]
private NRButton App;
/// The home.
[SerializeField]
private NRButton Home;
public void BindReceiver(ISystemButtonStateReceiver receiver)
{
this.m_Receiver = receiver;
InitSystemButtonEvent();
}
/// Initializes the system button event.
private void InitSystemButtonEvent()
{
Trigger.TriggerEvent += OnBtnTrigger;
App.TriggerEvent += OnBtnTrigger;
Home.TriggerEvent += OnBtnTrigger;
}
/// Executes the 'button trigger' action.
/// The key.
/// The go.
/// Information describing the racast.
private void OnBtnTrigger(string key, GameObject go, RaycastResult racastInfo)
{
if (key.Equals(NRButton.Enter))
{
if (go == App.gameObject)
{
m_SystemButtonState.buttons[0] = true;
}
if (go == Trigger.gameObject)
{
m_SystemButtonState.buttons[1] = true;
}
if (go == Home.gameObject)
{
m_SystemButtonState.buttons[2] = true;
}
}
else if (key.Equals(NRButton.Exit))
{
if (go == App.gameObject)
{
m_SystemButtonState.buttons[0] = false;
}
if (go == Trigger.gameObject)
{
m_SystemButtonState.buttons[1] = false;
}
if (go == Home.gameObject)
{
m_SystemButtonState.buttons[2] = false;
}
}
if (go == Trigger.gameObject
&& (key.Equals(NRButton.Hover) || key.Equals(NRButton.Enter)))
{
CalculateTouchPos(go, racastInfo);
}
else
{
m_SystemButtonState.touch_x = 0f;
m_SystemButtonState.touch_y = 0f;
}
this.m_Receiver?.OnDataReceived(m_SystemButtonState);
}
/// Calculates the touch position.
/// The go.
/// Information describing the racast.
private void CalculateTouchPos(GameObject go, RaycastResult racastInfo)
{
RectTransform rect = go.GetComponent();
Vector3[] v = new Vector3[4];
rect.GetWorldCorners(v);
var touchToCenter = racastInfo.worldPosition - go.transform.position;
var rightToCenter = (v[3] - v[0]) * 0.5f;
var topToCenter = (v[1] - v[0]) * 0.5f;
var halfWidth = (v[3] - v[0]).magnitude * 0.5f;
var halfHeight = (v[1] - v[0]).magnitude * 0.5f;
var alpha = Vector3.Angle(rightToCenter, touchToCenter);
var touchToX = (touchToCenter * Mathf.Cos(alpha * Mathf.PI / 180)).magnitude;
var touchToY = (touchToCenter * Mathf.Sin(alpha * Mathf.PI / 180)).magnitude;
bool x_forward = Vector3.Dot(touchToCenter, rightToCenter) > 0;
bool y_forward = Vector3.Dot(touchToCenter, topToCenter) > 0;
var touchx = touchToX > halfWidth ? (x_forward ? 1f : -1f) : (x_forward ? touchToX / halfWidth : -touchToX / halfWidth);
var touchy = touchToY > halfHeight ? (y_forward ? 1f : -1f) : (y_forward ? touchToY / halfHeight : -touchToY / halfHeight);
m_SystemButtonState.touch_x = touchx;
m_SystemButtonState.touch_y = touchy;
}
#if UNITY_EDITOR
/// Executes the 'disable' action.
private void OnDisable()
{
if (!NRInput.EmulateVirtualDisplayInEditor)
ClearSystemButtonState();
}
/// Clears the system button state.
private void ClearSystemButtonState()
{
}
#endif
}
}