/// <summary> /// Scroll a ScrollIndicator /// </summary> /// <param name="up"></param> /// <param name="tableView"></param> /// <param name="verticalScrollIndicator"></param> /// <param name="coroutine"></param> public static void ScrollTheScrollIndicator(bool up, TableView tableView, VerticalScrollIndicator verticalScrollIndicator, Coroutine coroutine) { Tuple <int, int> range = tableView.GetVisibleCellsIdRange(); float rangeUpper; float pageSize = range.Item2 - range.Item1; float numOfCells = tableView.numberOfCells; if (up) { rangeUpper = Mathf.Max(0, range.Item2 - pageSize); } else { rangeUpper = Mathf.Min(numOfCells, range.Item2 + pageSize); } float progress = (rangeUpper - pageSize) / (numOfCells - pageSize); if (coroutine != null) { tableView.StopCoroutine(coroutine); } coroutine = tableView.StartCoroutine(ScrollIndicatorAnimator(verticalScrollIndicator.progress, progress, verticalScrollIndicator, 0.3f, () => { tableView.StopCoroutine(coroutine); coroutine = null; })); }
/// <summary> /// Update the Scroll Indicators Graphics /// </summary> /// <param name="tableView"></param> /// <param name="verticalScrollIndicator"></param> /// <param name="doTheWaitThing">if it should wait for 10 ms (for bsml to initialize things)</param> public static async void UpdateScrollIndicator(TableView tableView, VerticalScrollIndicator verticalScrollIndicator, bool doTheWaitThing = false) { if (doTheWaitThing) { await SiraUtil.Utilities.AwaitSleep(10); } Tuple <int, int> range = tableView.GetVisibleCellsIdRange(); float pageSize = range.Item2 - range.Item1; float numOfCells = tableView.numberOfCells; verticalScrollIndicator.normalizedPageHeight = pageSize / numOfCells; verticalScrollIndicator.progress = (range.Item2 - pageSize) / (numOfCells - pageSize); }
public override GameObject CreateObject(Transform parent) { TextPageScrollView textScrollView = MonoBehaviour.Instantiate(Resources.FindObjectsOfTypeAll <ReleaseInfoViewController>().First().GetField <TextPageScrollView, ReleaseInfoViewController>("_textPageScrollView"), parent); textScrollView.name = "BSMLScrollView"; Button pageUpButton = textScrollView.GetField <Button, ScrollView>("_pageUpButton"); Button pageDownButton = textScrollView.GetField <Button, ScrollView>("_pageDownButton"); VerticalScrollIndicator verticalScrollIndicator = textScrollView.GetField <VerticalScrollIndicator, ScrollView>("_verticalScrollIndicator"); RectTransform viewport = textScrollView.GetField <RectTransform, ScrollView>("_viewport"); viewport.gameObject.AddComponent <VRGraphicRaycaster>().SetField("_physicsRaycaster", BeatSaberUI.PhysicsRaycasterWithCache); GameObject.Destroy(textScrollView.GetField <TextMeshProUGUI, TextPageScrollView>("_text").gameObject); GameObject gameObject = textScrollView.gameObject; MonoBehaviour.Destroy(textScrollView); gameObject.SetActive(false); BSMLScrollView scrollView = gameObject.AddComponent <BSMLScrollView>(); scrollView.SetField <ScrollView, Button>("_pageUpButton", pageUpButton); scrollView.SetField <ScrollView, Button>("_pageDownButton", pageDownButton); scrollView.SetField <ScrollView, VerticalScrollIndicator>("_verticalScrollIndicator", verticalScrollIndicator); scrollView.SetField <ScrollView, RectTransform>("_viewport", viewport); viewport.anchorMin = new Vector2(0, 0); viewport.anchorMax = new Vector2(1, 1); GameObject parentObj = new GameObject(); parentObj.name = "BSMLScrollViewContent"; parentObj.transform.SetParent(viewport, false); ContentSizeFitter contentSizeFitter = parentObj.AddComponent <ContentSizeFitter>(); contentSizeFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; contentSizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; VerticalLayoutGroup verticalLayout = parentObj.AddComponent <VerticalLayoutGroup>(); verticalLayout.childForceExpandHeight = false; verticalLayout.childForceExpandWidth = false; verticalLayout.childControlHeight = true; verticalLayout.childControlWidth = true; verticalLayout.childAlignment = TextAnchor.UpperCenter; RectTransform rectTransform = parentObj.transform as RectTransform; rectTransform.anchorMin = new Vector2(0, 1); rectTransform.anchorMax = new Vector2(1, 1); rectTransform.sizeDelta = new Vector2(0, 0); rectTransform.pivot = new Vector2(0.5f, 1); //parentObj.AddComponent<LayoutElement>(); parentObj.AddComponent <ScrollViewContent>().scrollView = scrollView; GameObject child = new GameObject(); child.name = "BSMLScrollViewContentContainer"; child.transform.SetParent(rectTransform, false); VerticalLayoutGroup layoutGroup = child.AddComponent <VerticalLayoutGroup>(); layoutGroup.childControlHeight = false; layoutGroup.childForceExpandHeight = false; layoutGroup.childAlignment = TextAnchor.LowerCenter; layoutGroup.spacing = 0.5f; //parentObj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; //child.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; //child.AddComponent<LayoutElement>(); ExternalComponents externalComponents = child.AddComponent <ExternalComponents>(); externalComponents.components.Add(scrollView); externalComponents.components.Add(scrollView.transform); externalComponents.components.Add(gameObject.AddComponent <LayoutElement>()); (child.transform as RectTransform).sizeDelta = new Vector2(0, -1); scrollView.SetField <ScrollView, RectTransform>("_contentRectTransform", parentObj.transform as RectTransform); gameObject.SetActive(true); return(child); }
public override void HandleType(ComponentTypeWithData componentType, BSMLParserParams parserParams) { CustomListTableData tableData = componentType.component as CustomListTableData; ScrollView scrollView = tableData.tableView.GetField <ScrollView, TableView>("_scrollView"); if (componentType.data.TryGetValue("selectCell", out string selectCell)) { tableData.tableView.didSelectCellWithIdxEvent += delegate(TableView table, int index) { if (!parserParams.actions.TryGetValue(selectCell, out BSMLAction action)) { throw new Exception("select-cell action '" + componentType.data["onClick"] + "' not found"); } action.Invoke(table, index); }; } bool verticalList = true; if (componentType.data.TryGetValue("listDirection", out string listDirection)) { tableData.tableView.SetField <TableView, TableType>("_tableType", (TableType)Enum.Parse(typeof(TableType), listDirection)); scrollViewDirectionField.SetValue(scrollView, Enum.Parse(scrollViewDirectionField.FieldType, listDirection)); verticalList = listDirection.ToLower() != "horizontal"; } if (componentType.data.TryGetValue("listStyle", out string listStyle)) { tableData.Style = (ListStyle)Enum.Parse(typeof(ListStyle), listStyle); } if (componentType.data.TryGetValue("cellSize", out string cellSize)) { tableData.cellSize = Parse.Float(cellSize); } if (componentType.data.TryGetValue("expandCell", out string expandCell)) { tableData.expandCell = Parse.Bool(expandCell); } if (componentType.data.TryGetValue("alignCenter", out string alignCenter)) { tableData.tableView.SetField <TableView, bool>("_alignToCenter", Parse.Bool(alignCenter)); } if (componentType.data.TryGetValue("stickScrolling", out string stickScrolling)) { if (Parse.Bool(stickScrolling)) { scrollView.SetField("_platformHelper", BeatSaberUI.PlatformHelper); } } // We can only show the scroll bar for vertical lists if (verticalList && componentType.data.TryGetValue("showScrollbar", out string showScrollbar)) { if (Parse.Bool(showScrollbar)) { TextPageScrollView textScrollView = UnityEngine.Object.Instantiate(ScrollViewTag.ScrollViewTemplate, componentType.component.transform); Button pageUpButton = textScrollView.GetField <Button, ScrollView>("_pageUpButton"); Button pageDownButton = textScrollView.GetField <Button, ScrollView>("_pageDownButton"); VerticalScrollIndicator verticalScrollIndicator = textScrollView.GetField <VerticalScrollIndicator, ScrollView>("_verticalScrollIndicator"); RectTransform scrollBar = verticalScrollIndicator.transform.parent as RectTransform; scrollView.SetField("_pageUpButton", pageUpButton); scrollView.SetField("_pageDownButton", pageDownButton); scrollView.SetField("_verticalScrollIndicator", verticalScrollIndicator); scrollBar.SetParent(componentType.component.transform); GameObject.Destroy(textScrollView.gameObject); // Need to adjust scroll bar positioning scrollBar.anchorMin = new Vector2(1, 0); scrollBar.anchorMax = Vector2.one; scrollBar.offsetMin = Vector2.zero; scrollBar.offsetMax = new Vector2(8, 0); } } if (componentType.data.TryGetValue("data", out string value)) { if (!parserParams.values.TryGetValue(value, out BSMLValue contents)) { throw new Exception("value '" + value + "' not found"); } var tableDataValue = contents.GetValue(); if (!(tableDataValue is List <CustomCellInfo> tableDataList)) { throw new Exception($"Value '{value}' is not a List<CustomCellInfo>, which is required for custom-list"); } tableData.data = tableDataList; tableData.tableView.ReloadData(); } switch (tableData.tableView.tableType) { case TableType.Vertical: (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(componentType.data.TryGetValue("listWidth", out string vListWidth) ? Parse.Float(vListWidth) : 60, tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string vVisibleCells) ? Parse.Float(vVisibleCells) : 7)); break; case TableType.Horizontal: (componentType.component.gameObject.transform as RectTransform).sizeDelta = new Vector2(tableData.cellSize * (componentType.data.TryGetValue("visibleCells", out string hVisibleCells) ? Parse.Float(hVisibleCells) : 4), componentType.data.TryGetValue("listHeight", out string hListHeight) ? Parse.Float(hListHeight) : 40); break; } componentType.component.gameObject.GetComponent <LayoutElement>().preferredHeight = (componentType.component.gameObject.transform as RectTransform).sizeDelta.y; componentType.component.gameObject.GetComponent <LayoutElement>().preferredWidth = (componentType.component.gameObject.transform as RectTransform).sizeDelta.x; tableData.tableView.gameObject.SetActive(true); tableData.tableView.LazyInit(); if (componentType.data.TryGetValue("id", out string id)) { parserParams.AddEvent(id + "#PageUp", scrollView.PageUpButtonPressed); parserParams.AddEvent(id + "#PageDown", scrollView.PageDownButtonPressed); } }
public override GameObject CreateObject(Transform parent) { TextPageScrollView textScrollView = MonoBehaviour.Instantiate(Resources.FindObjectsOfTypeAll <ReleaseInfoViewController>().First().GetField <TextPageScrollView, ReleaseInfoViewController>("_textPageScrollView"), parent); textScrollView.name = "BSMLScrollableSettingsContainer"; Button pageUpButton = textScrollView.GetField <Button, TextPageScrollView>("_pageUpButton"); Button pageDownButton = textScrollView.GetField <Button, TextPageScrollView>("_pageDownButton"); VerticalScrollIndicator verticalScrollIndicator = textScrollView.GetField <VerticalScrollIndicator, TextPageScrollView>("_verticalScrollIndicator"); RectTransform viewport = textScrollView.GetField <RectTransform, TextPageScrollView>("_viewport"); GameObject.Destroy(textScrollView.GetField <TextMeshProUGUI, TextPageScrollView>("_text").gameObject); GameObject gameObject = textScrollView.gameObject; MonoBehaviour.Destroy(textScrollView); gameObject.SetActive(false); BSMLScrollView scrollView = gameObject.AddComponent <BSMLScrollView>(); scrollView.SetField <ScrollView, Button>("_pageUpButton", pageUpButton); scrollView.SetField <ScrollView, Button>("_pageDownButton", pageDownButton); scrollView.SetField <ScrollView, VerticalScrollIndicator>("_verticalScrollIndicator", verticalScrollIndicator); scrollView.SetField <ScrollView, RectTransform>("_viewport", viewport); RectTransform scrollTransform = scrollView.transform as RectTransform; scrollTransform.anchoredPosition = new Vector2(2, 6); scrollTransform.sizeDelta = new Vector2(0, -20); viewport.anchorMin = new Vector2(0.5f, 0.5f); viewport.anchorMax = new Vector2(0.5f, 0.5f); viewport.sizeDelta = new Vector2(90, 40); GameObject parentObj = new GameObject(); parentObj.name = "BSMLScrollableSettingsContent"; parentObj.transform.SetParent(viewport, false); VerticalLayoutGroup verticalLayout = parentObj.AddComponent <VerticalLayoutGroup>(); verticalLayout.childForceExpandHeight = false; verticalLayout.childForceExpandWidth = false; RectTransform rectTransform = parentObj.transform as RectTransform; rectTransform.anchorMin = new Vector2(0, 0); rectTransform.anchorMax = new Vector2(1, 1); rectTransform.sizeDelta = new Vector2(0, 0); parentObj.AddComponent <LayoutElement>(); GameObject child = new GameObject(); child.name = "BSMLScrollableSettingsContentContainer"; child.transform.SetParent(rectTransform, false); VerticalLayoutGroup layoutGroup = child.AddComponent <VerticalLayoutGroup>(); layoutGroup.childControlHeight = false; layoutGroup.childForceExpandHeight = false; layoutGroup.childAlignment = TextAnchor.MiddleCenter; layoutGroup.spacing = 0.5f; child.AddComponent <ContentSizeFitter>(); child.AddComponent <LayoutElement>(); child.AddComponent <ScrollViewContent>().scrollView = scrollView; (child.transform as RectTransform).sizeDelta = new Vector2(0, -1); scrollView.SetField <ScrollView, RectTransform>("_contentRectTransform", parentObj.transform as RectTransform); gameObject.SetActive(true); return(child); }
/// <summary> /// Animates a Scroll Indicator /// </summary> /// <param name="startValue"></param> /// <param name="endValue"></param> /// <param name="verticalScrollIndicator"></param> /// <param name="lerpDuration"></param> /// <param name="onDone">Method to execute after it's done animating.</param> /// <returns></returns> public static IEnumerator ScrollIndicatorAnimator(float startValue, float endValue, VerticalScrollIndicator verticalScrollIndicator, float lerpDuration = 0.3f, Action onDone = null) { float timeElapsed = 0f; while (timeElapsed < lerpDuration) { verticalScrollIndicator.progress = Mathf.Lerp(startValue, endValue, Easings.EaseOutCubic(timeElapsed / lerpDuration)); timeElapsed += Time.deltaTime; yield return(null); } verticalScrollIndicator.progress = endValue; onDone?.Invoke(); }
// temporary while BSML doesn't support the new scroll buttons & indicator private void CreateTableView() { RectTransform tableViewContainer = new GameObject("AvatarsTableView", typeof(RectTransform)).transform as RectTransform; RectTransform tableView = new GameObject("AvatarsTableView", typeof(RectTransform), typeof(ScrollRect), typeof(Touchable), typeof(EventSystemListener)).transform as RectTransform; RectTransform viewport = new GameObject("Viewport", typeof(RectTransform), typeof(RectMask2D)).transform as RectTransform; RectTransform content = new GameObject("Content", typeof(RectTransform)).transform as RectTransform; tableViewContainer.gameObject.SetActive(false); tableViewContainer.anchorMin = new Vector2(0.1f, 0f); tableViewContainer.anchorMax = new Vector2(0.9f, 0.85f); tableViewContainer.sizeDelta = new Vector2(-10, 0); tableViewContainer.offsetMin = new Vector2(0, 0); tableViewContainer.offsetMax = new Vector2(-10, 0); tableView.anchorMin = Vector2.zero; tableView.anchorMax = Vector2.one; tableView.sizeDelta = Vector2.zero; tableView.anchoredPosition = Vector2.zero; viewport.anchorMin = Vector2.zero; viewport.anchorMax = Vector2.one; viewport.sizeDelta = Vector2.zero; viewport.anchoredPosition = Vector2.zero; tableViewContainer.SetParent(rectTransform, false); tableView.SetParent(tableViewContainer, false); viewport.SetParent(tableView, false); content.SetParent(viewport, false); tableView.GetComponent <ScrollRect>().viewport = viewport; ScrollView scrollView = tableView.gameObject.AddComponent <ScrollView>(); scrollView.SetField("_contentRectTransform", content); scrollView.SetField("_viewport", viewport); RectTransform header = Instantiate((RectTransform)_leaderboardViewController.transform.Find("HeaderPanel"), rectTransform, false); header.name = "HeaderPanel"; Destroy(header.GetComponentInChildren <LocalizedTextMeshProUGUI>()); TextMeshProUGUI textMesh = header.Find("Text").GetComponent <TextMeshProUGUI>(); textMesh.text = "Avatars"; _loadingIndicator = Instantiate(_leaderboardViewController.transform.Find("Container/LeaderboardTableView/LoadingControl/LoadingContainer/LoadingIndicator").gameObject, rectTransform, false); _loadingIndicator.name = "LoadingIndicator"; // buttons and indicator have images so it's easier to just copy from an existing component Transform scrollBar = Instantiate(_levelCollectionViewController.transform.Find("LevelsTableView/ScrollBar"), tableViewContainer, false); scrollBar.name = "ScrollBar"; Button upButton = scrollBar.Find("UpButton").GetComponent <Button>(); Button downButton = scrollBar.Find("DownButton").GetComponent <Button>(); VerticalScrollIndicator verticalScrollIndicator = scrollBar.Find("VerticalScrollIndicator").GetComponent <VerticalScrollIndicator>(); scrollView.SetField("_pageUpButton", upButton); scrollView.SetField("_pageDownButton", downButton); scrollView.SetField("_verticalScrollIndicator", verticalScrollIndicator); _tableView = _container.InstantiateComponent <TableView>(tableView.gameObject); _tableView.SetField("_preallocatedCells", new TableView.CellsGroup[0]); _tableView.SetField("_isInitialized", false); _tableView.SetField("_scrollView", scrollView); _tableView.SetDataSource(this, true); _tableView.didSelectCellWithIdxEvent += OnAvatarClicked; tableViewContainer.gameObject.SetActive(true); }