This commit is contained in:
2025-08-18 09:22:24 +08:00
commit cef5623ab0
1333 changed files with 305844 additions and 0 deletions
@@ -0,0 +1,32 @@
using System;
using System.Reflection;
namespace Com.ForbiddenByte.OSA.AdditionalComponents
{
public class InputFieldInScrollRectFixer : InputFieldInScrollRectFixerBase
{
MethodInfo _ActivateInputFieldMI;
PropertyInfo _isFocusedPI;
/// <summary>Using reflection so you won't get compile-time errors</summary>
protected override void CacheMethods()
{
var type = _InputField.GetType();
string reqComp = "UnityEngine.UI.InputField";
if (type.FullName != reqComp)
throw new InvalidOperationException("This script can only be attached to a GameObject containing a " + reqComp);
_ActivateInputFieldMI = type.GetMethod("ActivateInputField");
_isFocusedPI = type.GetProperty("isFocused");
}
protected override void ActivateInputField()
{
if (_ActivateInputFieldMI != null)
_ActivateInputFieldMI.Invoke(_InputField, null);
}
protected override bool IsInputFieldFocused() { return (bool)_isFocusedPI.GetValue(_InputField, null); }
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55f8d870c6da97e45ab5020ef4ae817e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
@@ -0,0 +1,196 @@
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.EventSystems;
namespace Com.ForbiddenByte.OSA.AdditionalComponents
{
/// <summary>
/// Utility that allows dragging a ScrollRect even if the PointerDown event has started inside a child InputField (which cancels the dragging by default)
/// </summary>
public abstract class InputFieldInScrollRectFixerBase : MonoBehaviour, IInitializePotentialDragHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IScrollHandler
{
protected Selectable _InputField;
Image _ImageOnMeIfChild;
const string CHILD_NAME = "InputFieldFixer-Child";
bool _IAmChild;
bool _DragInProgress;
protected virtual void Awake()
{
_InputField = GetComponent<Selectable>();
_IAmChild = _InputField == null;
if (_IAmChild)
{
InitAsChild();
}
else
{
CacheMethods();
InitAsParent();
}
}
protected abstract void CacheMethods();
void OnDisable()
{
_DragInProgress = false;
}
void InitAsParent()
{
var inputFieldImg = _InputField.image;
if (inputFieldImg)
inputFieldImg.raycastTarget = false;
var tr = transform.Find(CHILD_NAME);
GameObject go;
RectTransform goRT;
// The child may already exist if you'll instantiate an existing InputField with InputFieldInScrollRectFixer attached
if (tr == null)
{
go = new GameObject(CHILD_NAME, typeof(RectTransform));
goRT = go.transform as RectTransform;
goRT.SetParent(_InputField.transform, false);
go.AddComponent(GetType() /*add the same component as <this>'s type, i.e. the one for InputField or TMPro.TMP_InputField*/);
}
// Parent not needed anymore
Destroy(this);
}
void InitAsChild()
{
name = CHILD_NAME;
_InputField = transform.parent.GetComponent<Selectable>();
if (!_InputField)
throw new InvalidOperationException("Child InputFieldInScrollRectFixer: InputField not found in parent");
CacheMethods();
var inputFieldImg = _InputField.image;
if (!inputFieldImg)
throw new InvalidOperationException("Child InputFieldInScrollRectFixer: InputField must have an image attached (can be invisible)");
// May have already been created if this is an instance of a another runtime instance
_ImageOnMeIfChild = GetComponent<Image>();
if (!_ImageOnMeIfChild)
{
_ImageOnMeIfChild = gameObject.AddComponent<Image>();
_ImageOnMeIfChild.sprite = inputFieldImg.sprite;
}
var goRT = transform as RectTransform;
goRT.SetAsLastSibling();
goRT.anchorMin = Vector2.zero;
goRT.anchorMax = Vector2.one;
goRT.sizeDelta = Vector2.zero;
_ImageOnMeIfChild.color = Color.clear;
}
protected abstract void ActivateInputField();
protected abstract bool IsInputFieldFocused();
void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
{
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IPointerDownHandler>();
if (par != null)
par.OnPointerDown(eventData);
}
void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
{
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IPointerUpHandler>();
if (par != null)
par.OnPointerUp(eventData);
}
void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
{
if (InputFieldActiveAndFocused())
{
(_InputField as IPointerClickHandler).OnPointerClick(eventData);
return;
}
if (_DragInProgress)
return;
if (eventData.useDragThreshold)
{
var dragDist = Vector2.Distance(eventData.pressPosition, eventData.position);
if (dragDist > EventSystem.current.pixelDragThreshold)
return;
}
if (CanInputFieldBeFocused())
{
ActivateInputField();
return;
}
var par = GetComponentInInputFieldParents<IPointerClickHandler>();
if (par != null)
par.OnPointerClick(eventData);
}
void IInitializePotentialDragHandler.OnInitializePotentialDrag(PointerEventData eventData)
{
if (!InputFieldActiveAndFocused())
{
var par = GetComponentInInputFieldParents<IInitializePotentialDragHandler>();
if (par != null)
par.OnInitializePotentialDrag(eventData);
}
}
void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
{
_DragInProgress = true;
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IBeginDragHandler>();
if (par != null)
par.OnBeginDrag(eventData);
}
void IDragHandler.OnDrag(PointerEventData eventData)
{
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IDragHandler>();
if (par != null)
par.OnDrag(eventData);
}
void IScrollHandler.OnScroll(PointerEventData eventData)
{
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IScrollHandler>();
if (par != null)
par.OnScroll(eventData);
}
void IEndDragHandler.OnEndDrag(PointerEventData eventData)
{
_DragInProgress = false;
var par = GetInputFieldIfActiveOrNextComponentInItsParents<IEndDragHandler>();
if (par != null)
par.OnEndDrag(eventData);
}
bool InputFieldActiveAndFocused() { return CanInputFieldBeFocused() && IsInputFieldFocused(); }
bool CanInputFieldBeFocused() { return _InputField.isActiveAndEnabled && _InputField.interactable; }
T GetInputFieldIfActiveOrNextComponentInItsParents<T>()
{
if (InputFieldActiveAndFocused())
return (T)(object)_InputField;
return GetComponentInInputFieldParents<T>();
}
T GetComponentInInputFieldParents<T>() { return (T)(object)_InputField.transform.parent.GetComponentInParent(typeof(T)); }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 800d0ae0d22df834fad82405cbc91e8a
timeCreated: 1563646918
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
// Uncomment this if you have TMPro installed and want to use this script
//#define TMPRO_AVAILABLE
using System;
using System.Reflection;
namespace Com.ForbiddenByte.OSA.AdditionalComponents
{
public class InputFieldInScrollRectFixerTMPro : InputFieldInScrollRectFixerBase
{
MethodInfo _ActivateInputFieldMI;
PropertyInfo _isFocusedPI;
/// <summary>Using reflection so you won't get compile-time errors</summary>
protected override void CacheMethods()
{
var type = _InputField.GetType();
string reqComp = "TMPro.TMP_InputField";
if (type.FullName != reqComp)
throw new InvalidOperationException("This script can only be attached to a GameObject containing a " + reqComp);
_ActivateInputFieldMI = type.GetMethod("ActivateInputField");
_isFocusedPI = type.GetProperty("isFocused");
}
protected override void ActivateInputField()
{
if (_ActivateInputFieldMI != null)
_ActivateInputFieldMI.Invoke(_InputField, null);
}
protected override bool IsInputFieldFocused() { return (bool)_isFocusedPI.GetValue(_InputField, null); }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6ba1a9fc18218a848a11e8cddd64bdb3
timeCreated: 1563646918
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using frame8.Logic.Misc.Other.Extensions;
using frame8.Logic.Misc.Visual.UI;
using frame8.Logic.Misc.Visual.UI.MonoBehaviours;
using UnityEngine.EventSystems;
namespace Com.ForbiddenByte.OSA.Util.ScrollViews
{
public class NonInteractableScrollRect : ScrollRect
{
public override void OnInitializePotentialDrag(PointerEventData eventData) { }
public override void OnBeginDrag(PointerEventData eventData) { }
public override void OnDrag(PointerEventData eventData) { }
public override void OnEndDrag(PointerEventData eventData) { }
public override void OnScroll(PointerEventData data) { }
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 45de622d467858c4d9599c5c2ac8ec4d
timeCreated: 1532623175
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,53 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using frame8.Logic.Misc.Other.Extensions;
using frame8.Logic.Misc.Visual.UI;
using frame8.Logic.Misc.Visual.UI.MonoBehaviours;
using UnityEngine.EventSystems;
namespace Com.ForbiddenByte.OSA.Util.ScrollViews
{
/// <summary>
/// Provides access to a Unity's ScrollRect through <see cref="IScrollRectProxy"/>.
/// For example, it can be added to a regular ScrollRect so <see cref="ScrollbarFixer8"/> can communicate with it, in case you want to use the <see cref="ScrollbarFixer8"/> without OSA.
/// </summary>
[RequireComponent(typeof(ScrollRect))]
public class UnityScrollRectProxy : MonoBehaviour, IScrollRectProxy
{
#region IScrollRectProxy properties implementation
public bool IsInitialized { get { return ScrollRect != null; } }
public Vector2 Velocity { get { return ScrollRect.velocity; } set { ScrollRect.velocity = value; } }
public bool IsHorizontal { get { return ScrollRect.horizontal; } }
public bool IsVertical { get { return ScrollRect.vertical; } }
public RectTransform Content { get { return ScrollRect.content; } }
public RectTransform Viewport { get { return ScrollRect.viewport; } }
public double ContentInsetFromViewportStart { get { return Content.GetInsetFromParentEdge(Viewport, (this as IScrollRectProxy).GetStartEdge()); } }
public double ContentInsetFromViewportEnd { get { return Content.GetInsetFromParentEdge(Viewport, (this as IScrollRectProxy).GetEndEdge()); } }
#endregion
ScrollRect ScrollRect { get { if (!_ScrollRect) _ScrollRect = GetComponent<ScrollRect>(); return _ScrollRect; } }
ScrollRect _ScrollRect;
void Awake()
{
if (ScrollRect == null)
throw new UnityException(GetType().Name + ": No ScrollRect component found");
}
#region IScrollRectProxy methods implementation
#pragma warning disable 0067
public event System.Action<double> ScrollPositionChanged;
#pragma warning restore 0067
public void SetNormalizedPosition(double normalizedPosition) { if (IsHorizontal) ScrollRect.horizontalNormalizedPosition = (float)normalizedPosition; else ScrollRect.verticalNormalizedPosition = (float)normalizedPosition; }
public double GetNormalizedPosition() { return IsHorizontal ? ScrollRect.horizontalNormalizedPosition : ScrollRect.verticalNormalizedPosition; }
public double GetContentSize() { return IsHorizontal ? Content.rect.width : Content.rect.height; }
public double GetViewportSize() { return IsHorizontal ? Viewport.rect.width : Viewport.rect.height; }
public void StopMovement() { ScrollRect.StopMovement(); }
#endregion
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7b56953da65ca4d40aa44696aca06058
timeCreated: 1532607872
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: