EVERYTHING
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BlockSpace.Voxels
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class BrowserButton : MonoBehaviour
|
||||
{
|
||||
private const float ButtonPressCooldown = 0.2f;
|
||||
|
||||
private const float ButtonShrinkDuration = 0.08f;
|
||||
|
||||
private const float ButtonSettleDuration = 0.12f;
|
||||
|
||||
private const float ButtonPressedScale = 0.84f;
|
||||
|
||||
private const float ButtonOvershootScale = 1.04f;
|
||||
|
||||
private const string ButtonThockResourcePath = "Thock";
|
||||
|
||||
[Header("Button")]
|
||||
[SerializeField]
|
||||
private Collider buttonCollider;
|
||||
|
||||
[SerializeField]
|
||||
private VRVoxelBrush voxelBrush;
|
||||
|
||||
[Header("Browser Login")]
|
||||
[SerializeField]
|
||||
private string loginUrl = "https://example.com/login";
|
||||
|
||||
[Header("Audio")]
|
||||
[SerializeField]
|
||||
private AudioClip buttonThockClip;
|
||||
|
||||
private readonly Dictionary<Transform, Vector3> buttonBaseScales = new Dictionary<Transform, Vector3>();
|
||||
|
||||
private readonly Dictionary<Transform, Coroutine> buttonAnimationCoroutines = new Dictionary<Transform, Coroutine>();
|
||||
|
||||
private bool insidePrevious;
|
||||
|
||||
private float nextButtonPressTime;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ResolveReferences();
|
||||
EnsureButtonAudioAssigned();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
ResetAllButtonScales();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
ResolveReferences();
|
||||
HandleButton();
|
||||
}
|
||||
|
||||
private void ResolveReferences()
|
||||
{
|
||||
if (buttonCollider == null)
|
||||
{
|
||||
buttonCollider = GetComponent<Collider>();
|
||||
}
|
||||
if (voxelBrush == null)
|
||||
{
|
||||
voxelBrush = ((VRVoxelBrush.Instance != null) ? VRVoxelBrush.Instance : Object.FindObjectOfType<VRVoxelBrush>());
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleButton()
|
||||
{
|
||||
bool flag = IsHandInside(buttonCollider, (voxelBrush != null) ? voxelBrush.LeftHandAnchor : null) || IsHandInside(buttonCollider, (voxelBrush != null) ? voxelBrush.RightHandAnchor : null);
|
||||
if (flag && !insidePrevious)
|
||||
{
|
||||
PlayButtonEnterAnimation(buttonCollider);
|
||||
if (Time.unscaledTime >= nextButtonPressTime)
|
||||
{
|
||||
nextButtonPressTime = Time.unscaledTime + 0.2f;
|
||||
PlayButtonClickFeedback(buttonCollider);
|
||||
OpenLoginUrl();
|
||||
}
|
||||
}
|
||||
insidePrevious = flag;
|
||||
}
|
||||
|
||||
private void OpenLoginUrl()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(loginUrl))
|
||||
{
|
||||
Debug.LogWarning("[BrowserLoginButton] Login URL is empty.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.OpenURL(loginUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayButtonEnterAnimation(Collider button)
|
||||
{
|
||||
if (!(button == null))
|
||||
{
|
||||
Transform transform = button.transform;
|
||||
if (!buttonBaseScales.TryGetValue(transform, out var value))
|
||||
{
|
||||
value = transform.localScale;
|
||||
buttonBaseScales.Add(transform, value);
|
||||
}
|
||||
if (buttonAnimationCoroutines.TryGetValue(transform, out var value2) && value2 != null)
|
||||
{
|
||||
StopCoroutine(value2);
|
||||
}
|
||||
transform.localScale = value;
|
||||
buttonAnimationCoroutines[transform] = StartCoroutine(AnimateButtonScale(transform, value));
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayButtonClickFeedback(Collider button)
|
||||
{
|
||||
if (!(buttonThockClip == null) && !(button == null))
|
||||
{
|
||||
AudioSource.PlayClipAtPoint(buttonThockClip, button.bounds.center, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator AnimateButtonScale(Transform buttonTransform, Vector3 baseScale)
|
||||
{
|
||||
Vector3 pressedScale = baseScale * 0.84f;
|
||||
Vector3 overshootScale = baseScale * 1.04f;
|
||||
float elapsed = 0f;
|
||||
while (elapsed < 0.08f)
|
||||
{
|
||||
if (buttonTransform == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
elapsed += Time.unscaledDeltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / 0.08f);
|
||||
buttonTransform.localScale = Vector3.LerpUnclamped(baseScale, pressedScale, t);
|
||||
yield return null;
|
||||
}
|
||||
elapsed = 0f;
|
||||
while (elapsed < 0.12f)
|
||||
{
|
||||
if (buttonTransform == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
elapsed += Time.unscaledDeltaTime;
|
||||
float num = Mathf.Clamp01(elapsed / 0.12f);
|
||||
float num2 = num * num * (3f - 2f * num);
|
||||
Vector3 localScale = ((num2 < 0.5f) ? Vector3.LerpUnclamped(pressedScale, overshootScale, num2 / 0.5f) : Vector3.LerpUnclamped(overshootScale, baseScale, (num2 - 0.5f) / 0.5f));
|
||||
buttonTransform.localScale = localScale;
|
||||
yield return null;
|
||||
}
|
||||
if (buttonTransform != null)
|
||||
{
|
||||
buttonTransform.localScale = baseScale;
|
||||
buttonAnimationCoroutines[buttonTransform] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetAllButtonScales()
|
||||
{
|
||||
foreach (KeyValuePair<Transform, Vector3> buttonBaseScale in buttonBaseScales)
|
||||
{
|
||||
if (buttonBaseScale.Key != null)
|
||||
{
|
||||
buttonBaseScale.Key.localScale = buttonBaseScale.Value;
|
||||
}
|
||||
}
|
||||
buttonAnimationCoroutines.Clear();
|
||||
}
|
||||
|
||||
private void EnsureButtonAudioAssigned()
|
||||
{
|
||||
if (buttonThockClip == null)
|
||||
{
|
||||
buttonThockClip = Resources.Load<AudioClip>("Thock");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsHandInside(Collider button, Transform handAnchor)
|
||||
{
|
||||
if (button == null || handAnchor == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector3 position = handAnchor.position;
|
||||
return (button.ClosestPoint(position) - position).sqrMagnitude <= 1E-06f;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user