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,102 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using Com.ForbiddenByte.OSA.Core;
using Com.ForbiddenByte.OSA.CustomParams;
namespace Com.ForbiddenByte.OSA.CustomAdapters.DateTimePicker
{
/// <summary>Implementing multiple adapters to get a generic picker which returns a <see cref="DateTime"/> object</summary>
public class DateTimePickerAdapter : OSA<MyParams, MyItemViewsHolder>
{
public int SelectedValue { get; private set; }
public event Action<int> OnSelectedValueChanged;
#region OSA implementation
/// <inheritdoc/>
protected override void Start()
{
base.Start();
}
/// <inheritdoc/>
protected override void Update()
{
base.Update();
if (!IsInitialized)
return;
if (VisibleItemsCount == 0)
return;
int middleVHIndex = VisibleItemsCount / 2;
var middleVH = GetItemViewsHolder(middleVHIndex);
var prevValue = SelectedValue;
SelectedValue = _Params.GetItemValueAtIndex(middleVH.ItemIndex);
middleVH.background.CrossFadeColor(_Params.selectedColor, .1f, false, false);
for (int i = 0; i < VisibleItemsCount; ++i)
{
if (i != middleVHIndex)
GetItemViewsHolder(i).background.CrossFadeColor(_Params.nonSelectedColor, .1f, false, false);
}
if (prevValue != SelectedValue && OnSelectedValueChanged != null)
OnSelectedValueChanged(SelectedValue);
}
/// <inheritdoc/>
protected override MyItemViewsHolder CreateViewsHolder(int itemIndex)
{
var instance = new MyItemViewsHolder();
instance.Init(_Params.ItemPrefab, _Params.Content, itemIndex);
return instance;
}
/// <inheritdoc/>
protected override void UpdateViewsHolder(MyItemViewsHolder newOrRecycled) { newOrRecycled.titleText.text = _Params.GetItemValueAtIndex(newOrRecycled.ItemIndex) + ""; }
#endregion
void ChangeItemsCountWithChecks(int newCount)
{
int min = 4;
if (newCount < min)
newCount = min;
ResetItems(newCount);
}
}
[Serializable] // serializable, so it can be shown in inspector
public class MyParams : BaseParamsWithPrefab
{
public int startItemNumber = 0;
public int increment = 1;
public Color selectedColor, nonSelectedColor;
/// <summary>The value of each item is calculated dynamically using its <paramref name="index"/>, <see cref="startItemNumber"/> and the <see cref="increment"/></summary>
/// <returns>The item's value (the displayed number)</returns>
public int GetItemValueAtIndex(int index) { return startItemNumber + increment * index; }
}
public class MyItemViewsHolder : BaseItemViewsHolder
{
public Image background;
public Text titleText;
/// <inheritdoc/>
public override void CollectViews()
{
base.CollectViews();
background = root.GetComponent<Image>();
titleText = root.GetComponentInChildren<Text>();
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f1cc6a6937df8c046943043e53538154
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
@@ -0,0 +1,309 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using frame8.Logic.Misc.Other.Extensions;
using Com.ForbiddenByte.OSA.Core;
namespace Com.ForbiddenByte.OSA.CustomAdapters.DateTimePicker
{
/// <summary>
/// Implementing multiple adapters to get a generic picker which returns a <see cref="DateTime"/> object.
/// There are 2 ways of using this script: either simply call <see cref="Show(Action{DateTime})"/>
/// or drag and drop the prefab from /Resources/Com.ForbiddenByte.OSA/DateTimePickerDialog into your scene and subscribe to <see cref="OnDateSelected"/>
/// </summary>
public class DateTimePickerDialog : MonoBehaviour
{
[SerializeField]
bool _AutoInit = false;
[SerializeField]
bool _DisplaySelectedDateAsShort = false;
[SerializeField]
bool _DisplaySelectedTimeAsShort = false;
[Tooltip("If true, animations won't be affected by Time.timeScale")]
[SerializeField]
bool _UseUnscaledTime = true;
public event Action<DateTime> OnDateSelected;
public DateTimePickerAdapter DayAdapter { get; private set; }
public DateTimePickerAdapter MonthAdapter { get; private set; }
public DateTimePickerAdapter YearAdapter { get; private set; }
public DateTimePickerAdapter HourAdapter { get; private set; }
public DateTimePickerAdapter MinuteAdapter { get; private set; }
public DateTimePickerAdapter SecondAdapter { get; private set; }
public DateTime SelectedValue
{
get
{
return new DateTime(
YearAdapter.SelectedValue, MonthAdapter.SelectedValue, DayAdapter.SelectedValue,
HourAdapter.SelectedValue, MinuteAdapter.SelectedValue, SecondAdapter.SelectedValue
);
}
}
const float SCROLL_DURATION1 = .2f;
const float SCROLL_DURATION2 = .35f;
const float SCROLL_DURATION3 = .5f;
const float ANIM_DURATION = .25f;
const float DEFAULT_WIDTH = 660f, DEFAULT_HEIGHT = DEFAULT_WIDTH / 2;
float AnimElapsedTime01 { get { float t = Mathf.Clamp01((Time - _AnimStartTime) / ANIM_DURATION); return t * t * t * t; } }
//Vector3 AnimCurrentScale { get { return Vector3.Lerp(_AnimStart, _AnimEnd, AnimElapsedTime01); } }
float AnimCurrentFloat { get { return Mathf.Lerp(_AnimStart, _AnimEnd, AnimElapsedTime01); } }
float Time { get { return _UseUnscaledTime ? UnityEngine.Time.unscaledTime : UnityEngine.Time.time; } }
Transform _DatePanel, _TimePanel;
Text _SelectedDateText, _SelectedTimeText;
bool _Initialized;
DateTime? _DateToInitWith;
bool _Animating;
//Vector3 _AnimStart, _AnimEnd;
float _AnimStart, _AnimEnd;
float _AnimStartTime;
Action _ActionOnAnimDone;
CanvasGroup _CanvasGroup;
DateTimePickerAdapter[] _AllAdapters = new DateTimePickerAdapter[6];
public static DateTimePickerDialog Show(Action<DateTime> onSelected)
{
return Show(DateTime.Now, onSelected);
}
public static DateTimePickerDialog Show(Action<DateTime> onSelected, string prefabPathInResources)
{
return Show(DateTime.Now, onSelected, prefabPathInResources);
}
public static DateTimePickerDialog Show(DateTime startingDate, Action<DateTime> onSelected)
{
return Show(startingDate, onSelected, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public static DateTimePickerDialog Show(DateTime startingDate, Action<DateTime> onSelected, string prefabPathInResources)
{
return Show(startingDate, onSelected, DEFAULT_WIDTH, DEFAULT_HEIGHT, prefabPathInResources);
}
public static DateTimePickerDialog Show(DateTime startingDate, Action<DateTime> onSelected, float width, float height)
{
var prefabPathInResources = OSAConst.OSA_PATH_IN_RESOURCES + "/" + typeof(DateTimePickerDialog).Name;
return Show(startingDate, onSelected, width, height, prefabPathInResources);
}
public static DateTimePickerDialog Show(DateTime startingDate, Action<DateTime> onSelected, float width, float height, string prefabPathInResources)
{
var go = Resources.Load<GameObject>(prefabPathInResources);
var picker = (Instantiate(go) as GameObject).GetComponent<DateTimePickerDialog>();
var c = FindObjectOfType<Canvas>();
if (!c)
throw new OSAException(typeof(DateTimePickerDialog).Name + ": no Canvas was found in the scene");
var canvasRT = c.transform as RectTransform;
var rt = (picker.transform as RectTransform);
rt.SetParent(canvasRT, false);
rt.SetAsLastSibling();
picker._DateToInitWith = startingDate;
if (onSelected != null)
picker.OnDateSelected += onSelected;
rt.SetInsetAndSizeFromParentEdgeWithCurrentAnchors(RectTransform.Edge.Left, (canvasRT.rect.width - width) / 2, width);
rt.SetInsetAndSizeFromParentEdgeWithCurrentAnchors(RectTransform.Edge.Top, (canvasRT.rect.height - height) / 2, height);
return picker;
}
void Awake()
{
_CanvasGroup = GetComponent<CanvasGroup>();
_CanvasGroup.alpha = 0f;
_AnimEnd = 1f;
_AnimStartTime = Time;
_Animating = true;
}
void Start()
{
var adaptersTR = transform.Find("Adapters");
_DatePanel = adaptersTR.Find("Date");
_DatePanel.GetComponentAtPath("SelectedIndicatorText", out _SelectedDateText);
int i = 0;
_AllAdapters[i++] = DayAdapter = _DatePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Day");
_AllAdapters[i++] = MonthAdapter = _DatePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Month");
_AllAdapters[i++] = YearAdapter = _DatePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Year");
_TimePanel = adaptersTR.Find("Time");
_TimePanel.GetComponentAtPath("SelectedIndicatorText", out _SelectedTimeText);
_AllAdapters[i++] = HourAdapter = _TimePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Hour");
_AllAdapters[i++] = MinuteAdapter = _TimePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Minute");
_AllAdapters[i++] = SecondAdapter = _TimePanel.GetComponentAtPath<DateTimePickerAdapter>("Panel/Second");
for (i = 0; i < _AllAdapters.Length; ++i)
_AllAdapters[i].Parameters.UseUnscaledTime = _UseUnscaledTime;
if (_AutoInit)
ExecuteAfter(.2f, AutoInit);
}
void Update()
{
if (_Animating)
{
//transform.localScale = AnimCurrentFloat;
_CanvasGroup.alpha = AnimCurrentFloat;
if (AnimElapsedTime01 == 1f)
{
_Animating = false;
if (_ActionOnAnimDone != null)
_ActionOnAnimDone();
}
return;
}
if (!_Initialized)
return;
try
{
var current = SelectedValue;
_SelectedDateText.text = _DisplaySelectedDateAsShort ? current.ToShortDateString() : current.ToLongDateString();
_SelectedTimeText.text = _DisplaySelectedTimeAsShort ? current.ToShortTimeString() : current.ToLongTimeString();
}
catch /*(Exception e)*/{
//Debug.Log(e + "\n"+YearAdapter.SelectedValue + "," + MonthAdapter.SelectedValue + "," + DayAdapter.SelectedValue + "," +
//HourAdapter.SelectedValue + "," + MinuteAdapter.SelectedValue + "," + SecondAdapter.SelectedValue);
}
}
public void InitWithNow() { InitWithDate(DateTime.Now); }
public void InitWithDate(DateTime dateTime)
{
StopAnimations();
_DateToInitWith = null;
UnregisterAutoCorrection();
int doneNum = 0;
int targetDone = 2;
Action onDone = () =>
{
if (++doneNum == targetDone)
{
_Initialized = true;
RegisterAutoCorrection();
}
};
//Func<float, bool> onProgress = p01 =>
//{
// if (p01 == 1f)
// {
// if (++doneNum == targetDone)
// {
// _Initialized = true;
// RegisterAutoCorrection();
// }
// }
// return true;
//};
YearAdapter.ResetItems(3000);
YearAdapter.SmoothScrollTo(dateTime.Year - 1, SCROLL_DURATION1, .5f, .5f);
MonthAdapter.ResetItems(12);
MonthAdapter.SmoothScrollTo(dateTime.Month - 1, SCROLL_DURATION2, .5f, .5f);
DayAdapter.ResetItems(DateTime.DaysInMonth(dateTime.Year, dateTime.Month));
//DayAdapter.SmoothScrollTo(dateTime.Day - 1, SCROLL_DURATION3, .5f, .5f, onProgress, null, true);
DayAdapter.SmoothScrollTo(dateTime.Day - 1, SCROLL_DURATION3, .5f, .5f, null, onDone, true);
SecondAdapter.ResetItems(60);
SecondAdapter.SmoothScrollTo(dateTime.Second, SCROLL_DURATION1, .5f, .5f);
MinuteAdapter.ResetItems(60);
MinuteAdapter.SmoothScrollTo(dateTime.Minute, SCROLL_DURATION2, .5f, .5f);
HourAdapter.ResetItems(24);
//HourAdapter.SmoothScrollTo(dateTime.Hour, SCROLL_DURATION3, .5f, .5f, onProgress, true);
HourAdapter.SmoothScrollTo(dateTime.Hour, SCROLL_DURATION3, .5f, .5f, null, onDone, true);
}
public void ReturnCurrent()
{
//_AnimStart = Vector3.one;
//_AnimEnd = Vector3.zero;
_AnimStart = _CanvasGroup.alpha;
_AnimEnd = 0f;
_AnimStartTime = Time;
_Animating = true;
_ActionOnAnimDone = () =>
{
_ActionOnAnimDone = null;
if (OnDateSelected != null)
OnDateSelected(SelectedValue);
Destroy(gameObject);
};
}
void AutoInit()
{
_DateToInitWith = _DateToInitWith ?? DateTime.Now;
InitWithDate(_DateToInitWith.Value);
}
void UnregisterAutoCorrection()
{
YearAdapter.OnSelectedValueChanged -= OnYearChanged;
MonthAdapter.OnSelectedValueChanged -= OnMonthChanged;
}
void RegisterAutoCorrection()
{
YearAdapter.OnSelectedValueChanged += OnYearChanged;
MonthAdapter.OnSelectedValueChanged += OnMonthChanged;
}
void OnYearChanged(int year) { OnMonthChanged(MonthAdapter.SelectedValue); }
void OnMonthChanged(int month)
{
var selectedDay = DayAdapter.SelectedValue;
int newDaysInMonth = DateTime.DaysInMonth(YearAdapter.SelectedValue, month);
if (newDaysInMonth == DayAdapter.GetItemsCount())
return;
DayAdapter.ResetItems(newDaysInMonth);
DayAdapter.ScrollTo(Math.Min(newDaysInMonth, selectedDay) - 1, .5f, .5f);
}
void StopAnimations()
{
foreach (var adapter in _AllAdapters)
{
if (adapter)
adapter.CancelAllAnimations();
}
}
void ExecuteAfter(float seconds, Action action) { StartCoroutine(ExecuteAfterCoroutine(seconds, action)); }
IEnumerator ExecuteAfterCoroutine(float seconds, Action action)
{
if (seconds > 0f)
{
yield return null;
yield return null;
}
if (_UseUnscaledTime)
yield return new WaitForSecondsRealtime(seconds);
else
yield return new WaitForSeconds(seconds);
action();
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67c05838ffd5f8849ad61288be5e976f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData: