/* * VideoKit * Copyright © 2026 Yusuf Olokoba. All Rights Reserved. */ namespace VideoKit.UI { using System.Collections; using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.Serialization; /// /// Lightweight record button with press-and-hold gesture. /// [RequireComponent(typeof(Image)), AddComponentMenu(@""), DisallowMultipleComponent] public sealed class VideoKitRecordButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler { #region --Inspector-- [Header(@"Settings")] /// /// Maximum duration that button can be pressed. /// [Range(5f, 60f), Tooltip(@"Maximum duration that button can be pressed.")] public float maxDuration = 10f; [Header(@"UI")] /// /// Countdown image. /// [Tooltip(@"Countdown image.")] public Image countdown; [Header(@"Events")] /// /// Event invoked when the button is tapped. /// [Tooltip(@"Event invoked when the button is tapped.")] public UnityEvent OnTap; /// /// Event invoked when the button starts being held. /// [Tooltip(@"Event invoked when the button starts being held."), FormerlySerializedAs(@"OnStartRecording")] public UnityEvent OnBeginHold; /// /// Event invoked when the button stops being held. /// [Tooltip(@"Event invoked when the button stops being held."), FormerlySerializedAs(@"OnStopRecording")] public UnityEvent OnEndHold; #endregion #region --Operations-- private Image button; private bool touch; private const float TapDelay = 0.2f; private void Awake() => button = GetComponent(); private void Start() => Zero(); private void Zero() { button.fillAmount = 1.0f; countdown.fillAmount = 0.0f; } private IEnumerator Countdown() { touch = true; // Wait for false touch yield return new WaitForSeconds(TapDelay); if (!touch) { OnTap?.Invoke(); yield break; } // Start recording OnBeginHold?.Invoke(); // Animate the countdown var startTime = Time.time; while (touch) { var ratio = (Time.time - startTime) / maxDuration; touch = ratio <= 1f; countdown.fillAmount = ratio; button.fillAmount = 1f - ratio; yield return null; } // Reset Zero(); OnEndHold?.Invoke(); } void IPointerDownHandler.OnPointerDown(PointerEventData eventData) => StartCoroutine(Countdown()); void IPointerUpHandler.OnPointerUp(PointerEventData eventData) => touch = false; #endregion } }