/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
///
/// This component smoothly moves the contentContainer horizontally
/// until the selected page is completely visible, the anchor of the page is at the (0, any)
/// position relative to the parent of the contentContainer when the page anchor is set to "top-left"
///
public class PageScroll : UIBehaviour
{
[SerializeField] private UnityEngine.UI.ToggleGroup _toggleGroup;
[SerializeField] private RectTransform _contentContainer;
[Serializable]
public struct Page
{
public UnityEngine.UI.Toggle toggle;
public RectTransform container;
public CanvasGroup canvasGroup;
}
[SerializeField] private List _pages;
[SerializeField] private int _pageIndex;
public float animationSpeed;
public AnimationCurve alphaTransitionCurve;
private float _pageAnim;
public void SetPageIndex(int pageIndex)
{
var index = pageIndex < 0 ? 0 : pageIndex > _pages.Count - 1 ? _pages.Count - 1 : pageIndex;
if (this._pageIndex != index)
{
this._pageIndex = index;
_pages[this._pageIndex].toggle.isOn = true;
}
}
public void ScrollPage(int direction)
{
var newPage = _pageIndex + direction;
SetPageIndex(newPage);
}
/*#if UNITY_EDITOR
protected override void OnValidate()
{
if (_pageIndex < 0)
{
_pageIndex = 0;
}
else if (_pageIndex > _pages.Count - 1)
{
_pageIndex = _pages.Count - 1;
}
_pages[_pageIndex].toggle.isOn = true;
}
#endif*/
protected override void OnEnable()
{
foreach (var page in _pages)
{
page.toggle.onValueChanged.AddListener(delegate { ActiveToggleChanged(page.toggle); });
}
}
protected override void OnDisable()
{
foreach (var page in _pages)
{
page.toggle.onValueChanged.RemoveAllListeners();
}
}
private void ActiveToggleChanged(UnityEngine.UI.Toggle toggle)
{
if (toggle == null) return;
if (!toggle.isOn) return;
var toggleIndex = _pages.FindIndex(page => page.toggle == toggle);
var containsToggle = toggleIndex >= 0;
if (!containsToggle) return;
_pageIndex = toggleIndex;
}
protected override void Start()
{
StartCoroutine(LateStart());
}
private IEnumerator LateStart()
{
yield return null;
if (_pages == null) yield break;
_pages[0].toggle.isOn = true;
}
protected virtual void Update()
{
_pageAnim = Mathf.Lerp(_pageAnim, (float)_pageIndex, animationSpeed * Time.deltaTime);
_pageAnim = Mathf.Clamp(_pageAnim, 0.0f, _pages.Count - 1);
UpdateVisial();
}
private void UpdateVisial()
{
if (Mathf.Abs(_pageAnim - (float)_pageIndex) < 0.005f)
{
var position = _pages[_pageIndex].container.anchoredPosition;
_pages[_pageIndex].canvasGroup.alpha = 1.0f;
SetOtherPagesTransparent(_pageIndex, -1);
_contentContainer.anchoredPosition = position * new Vector2(-1.0f, 1.0f);
}
else
{
var anim = Mathf.Clamp(_pageAnim, 0.0f, _pages.Count - 1);
var currentPage = Mathf.Floor(anim);
var nextPage = Mathf.Ceil(anim);
var currentPageIndex = (int)currentPage;
var nextPageIndex = (int)nextPage;
var animParam = anim - currentPage;
var startPosition = _pages[currentPageIndex].container.anchoredPosition;
var endPosition = _pages[nextPageIndex].container.anchoredPosition;
SetOtherPagesTransparent(currentPageIndex, nextPageIndex);
_pages[currentPageIndex].canvasGroup.alpha = alphaTransitionCurve.Evaluate(1.0f - animParam);
_pages[nextPageIndex].canvasGroup.alpha = alphaTransitionCurve.Evaluate(animParam);
_contentContainer.anchoredPosition = Vector2.Lerp(startPosition, endPosition, animParam) * new Vector2(-1.0f, 1.0f);
}
}
private void SetOtherPagesTransparent(int index0, int index1)
{
for (int i = 0; i < _pages.Count; i++)
{
if (i == index0 || i == index1) continue;
if (_pages[i].canvasGroup == null) continue;
_pages[i].canvasGroup.alpha = 0;
}
}
#region Inject
public void InjectAllPageScroll(UnityEngine.UI.ToggleGroup toggleGroup, RectTransform contentContainer, List pages, int pageIndex)
{
InjectToggleGroup(toggleGroup);
InjectContentContainer(contentContainer);
InjectPages(pages);
InjectPageIndex(pageIndex);
}
public void InjectToggleGroup(UnityEngine.UI.ToggleGroup toggleGroup)
{
this._toggleGroup = toggleGroup;
}
public void InjectContentContainer(RectTransform contentContainer)
{
this._contentContainer = contentContainer;
}
public void InjectPages(List pages)
{
this._pages = pages;
}
public void InjectPageIndex(int pageIndex)
{
this._pageIndex = pageIndex;
}
#endregion
}