Instantly share code, notes, and snippets.
Last active
April 22, 2024 15:10
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save nekomimi-daimao/7b29fbb6f5bda1bf71791412f35fa7ea to your computer and use it in GitHub Desktop.
ButtonExtended
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://gist.github.com/nekomimi-daimao/7b29fbb6f5bda1bf71791412f35fa7ea | |
using System; | |
using UniRx; | |
using UnityEngine; | |
using UnityEngine.EventSystems; | |
namespace Nekomimi.Daimao | |
{ | |
[RequireComponent(typeof(CanvasGroup))] | |
public class ButtonExtended : MonoBehaviour, | |
IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, IDragHandler | |
{ | |
private readonly BoolReactiveProperty _pointerIn = new(false); | |
/// <summary> | |
/// ポインターのイン/アウト. | |
/// </summary> | |
public IReadOnlyReactiveProperty<bool> PointerIn => _pointerIn; | |
/// <summary> | |
/// 有効/無効の切り替え. | |
/// </summary> | |
public readonly BoolReactiveProperty Interactable = new(true); | |
private readonly Subject<float> _onClick = new(); | |
/// <summary> | |
/// クリックイベント. | |
/// 押されていた間の秒数も同時に通知される. | |
/// </summary> | |
public IObservable<float> OnClick => _onClick; | |
private IDisposable _disposablePressed; | |
private readonly FloatReactiveProperty _pressedSecond = new(0f); | |
/// <summary> | |
/// 押され続けている秒数. | |
/// 押されている間は<see cref="Observable.EveryUpdate"/>の間隔で更新される. | |
/// </summary> | |
public IReadOnlyReactiveProperty<float> PressedSecond => _pressedSecond; | |
#region IPointerCallbacks | |
void IPointerDownHandler.OnPointerDown(PointerEventData eventData) | |
{ | |
Release(); | |
if (!Interactable.Value) | |
{ | |
return; | |
} | |
_disposablePressed = Observable.EveryUpdate() | |
.Select(_ => Time.deltaTime) | |
.TakeUntilDisable(this) | |
.Subscribe(f => _pressedSecond.Value += f); | |
} | |
void IPointerUpHandler.OnPointerUp(PointerEventData eventData) | |
{ | |
if (PointerIn.Value && Interactable.Value) | |
{ | |
_onClick.OnNext(PressedSecond.Value); | |
} | |
Release(); | |
} | |
void IPointerEnterHandler.OnPointerEnter(PointerEventData eventData) | |
{ | |
_pointerIn.Value = true; | |
} | |
void IPointerExitHandler.OnPointerExit(PointerEventData eventData) | |
{ | |
_pointerIn.Value = false; | |
Release(); | |
} | |
void IDragHandler.OnDrag(PointerEventData eventData) | |
{ | |
// https://discussions.unity.com/t/mouse-drag-element-inside-scrollrect-throws-pointerup-event/150840/4 | |
} | |
#endregion | |
private void Release() | |
{ | |
_disposablePressed?.Dispose(); | |
_disposablePressed = null; | |
_pressedSecond.Value = 0f; | |
} | |
public virtual void OnStart() | |
{ | |
} | |
[SerializeField] | |
public CanvasGroup canvasGroup; | |
private readonly CompositeDisposable _compositeDisposable = new(); | |
private void Awake() | |
{ | |
_compositeDisposable.Add(_pointerIn); | |
_compositeDisposable.Add(Interactable); | |
_compositeDisposable.Add(_onClick); | |
_compositeDisposable.Add(_pressedSecond); | |
_compositeDisposable.AddTo(this); | |
if (canvasGroup == null) | |
{ | |
canvasGroup = GetComponent<CanvasGroup>(); | |
} | |
} | |
private void Start() | |
{ | |
OnStart(); | |
} | |
#if UNITY_EDITOR | |
private void Reset() | |
{ | |
if (canvasGroup == null) | |
{ | |
canvasGroup = GetComponent<CanvasGroup>(); | |
} | |
} | |
#endif | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment