Improved tab support
- Ability to specify position of auto & custom tabs (top, left, right) - Highlighting around selected tab
This commit is contained in:
@@ -12,10 +12,11 @@ namespace QuestAppLauncher
|
||||
[Serializable]
|
||||
public class Config
|
||||
{
|
||||
// Supported category types
|
||||
public const string Category_None = "none";
|
||||
public const string Category_Auto = "auto";
|
||||
public const string Category_Custom = "custom";
|
||||
// Supported category mode
|
||||
public const string Category_Off = "off";
|
||||
public const string Category_Top = "top";
|
||||
public const string Category_Left = "left";
|
||||
public const string Category_Right = "right";
|
||||
|
||||
/// <summary>
|
||||
/// Grid size
|
||||
@@ -33,16 +34,11 @@ namespace QuestAppLauncher
|
||||
// Whether to show 2D apps
|
||||
public bool show2D = false;
|
||||
|
||||
// Whether to only show apps that are explicitly specified in appnames.txt file.
|
||||
// If true, this will not show installed apps that are not in appnames.txt. This
|
||||
// is useful for organizing the launcher with a highly curated list of apps.
|
||||
public bool showOnlyCustom = false;
|
||||
// Auto Category: Apps are automatically categorized into 3 tabs - Quest, Go/GearVr, 2D
|
||||
public string autoCategory = Category_Top;
|
||||
|
||||
// Category types: "none", "auto", "custom":
|
||||
// - none: No categories - all apps are listed in a single pane
|
||||
// - auto: Apps are automatically categorized into 3 tabs - Quest, Go/GearVr, 2D
|
||||
// - custom: Apps are categorized according to appnames.txt file
|
||||
public string categoryType = Category_Auto;
|
||||
// Custom Category: Apps are categorized according to appnames.txt file
|
||||
public string customCategory = Category_Right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+150
-104
@@ -42,11 +42,15 @@ namespace QuestAppLauncher
|
||||
// Scroll container game object
|
||||
public GameObject scrollContainer;
|
||||
|
||||
// Tab container
|
||||
public GameObject tabContainer;
|
||||
// Tab containers
|
||||
public GameObject topTabContainer;
|
||||
public GameObject leftTabContainer;
|
||||
public GameObject rightTabContainer;
|
||||
|
||||
// Tab container
|
||||
public GameObject tabContainerContent;
|
||||
public GameObject topTabContainerContent;
|
||||
public GameObject leftTabContainerContent;
|
||||
public GameObject rightTabContainerContent;
|
||||
|
||||
// Tracking space
|
||||
public GameObject trackingSpace;
|
||||
@@ -64,10 +68,12 @@ namespace QuestAppLauncher
|
||||
private Coroutine populateCoroutine;
|
||||
|
||||
// Built-in tab names
|
||||
private const string Tab_None = "None";
|
||||
private const string Tab_Quest = "Quest";
|
||||
private const string Tab_Go = "Go/Gear";
|
||||
private const string Tab_2D = "2D";
|
||||
private const string Tab_All = "All";
|
||||
|
||||
private static readonly string[] Auto_Tabs = { Tab_Quest, Tab_Go, Tab_2D };
|
||||
|
||||
#region MonoBehaviour handler
|
||||
|
||||
@@ -158,7 +164,7 @@ namespace QuestAppLauncher
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetGridSize(GameObject gridContent, int rows, int cols)
|
||||
public Vector2 SetGridSize(GameObject gridContent, int rows, int cols)
|
||||
{
|
||||
// Make sure grid size have sane value
|
||||
cols = Math.Min(cols, 10);
|
||||
@@ -185,8 +191,10 @@ namespace QuestAppLauncher
|
||||
Debug.Log(string.Format("Grid size calculated width x height: {0} x {1}", width, height));
|
||||
|
||||
// Adjust grid container rect transform
|
||||
var size = new Vector2(width, height);
|
||||
|
||||
var gridTransform = this.panelContainer.GetComponent<RectTransform>();
|
||||
gridTransform.sizeDelta = new Vector2(width, height);
|
||||
gridTransform.sizeDelta = size;
|
||||
|
||||
// Adjust grid container Y position to maintain constant height.
|
||||
// TODO: Figure out a way to adjust UI to avoid this calculation in code
|
||||
@@ -194,6 +202,8 @@ namespace QuestAppLauncher
|
||||
(float)((gridTransform.rect.height - 2000) / 2.0),
|
||||
gridTransform.anchoredPosition3D.z);
|
||||
gridTransform.anchoredPosition3D = gridPosition;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public void StartPopulate()
|
||||
@@ -284,8 +294,8 @@ namespace QuestAppLauncher
|
||||
tabName = Tab_Go;
|
||||
}
|
||||
|
||||
apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, AutoTabName = tabName, Tab1Name = tabName, AppName = appName });
|
||||
Debug.LogFormat("[{0}] package: {1}, name: {2}, tab: {3}", i, packageName, appName, tabName);
|
||||
apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, AutoTabName = tabName, AppName = appName });
|
||||
Debug.LogFormat("[{0}] package: {1}, name: {2}, auto tab: {3}", i, packageName, appName, tabName);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
@@ -317,6 +327,15 @@ namespace QuestAppLauncher
|
||||
|
||||
var packageName = entry[0];
|
||||
var appName = entry[1];
|
||||
|
||||
if (!apps.ContainsKey(packageName))
|
||||
{
|
||||
// App is not installed, so skip
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the custom tab names, if any
|
||||
string autoTabName = null;
|
||||
var tab1 = entry.Length > 2 ? entry[2] : null;
|
||||
var tab2 = entry.Length > 3 ? entry[3] : null;
|
||||
|
||||
@@ -330,10 +349,22 @@ namespace QuestAppLauncher
|
||||
tab2 = null;
|
||||
}
|
||||
|
||||
if (!apps.ContainsKey(packageName))
|
||||
if (tab1 != null && tab2 != null && tab1.Equals(tab2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// App is not installed, so skip
|
||||
continue;
|
||||
tab2 = null;
|
||||
}
|
||||
|
||||
// Override auto tabe name if custom name matches built-in tab name
|
||||
if (tab1 != null && Auto_Tabs.Contains(tab1, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
autoTabName = tab1;
|
||||
tab1 = null;
|
||||
}
|
||||
|
||||
if (tab2 != null && Auto_Tabs.Contains(tab2, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
autoTabName = tab2;
|
||||
tab2 = null;
|
||||
}
|
||||
|
||||
// Update entry
|
||||
@@ -342,9 +373,9 @@ namespace QuestAppLauncher
|
||||
PackageName = apps[entry[0]].PackageName,
|
||||
Index = apps[entry[0]].Index,
|
||||
AppName = appName,
|
||||
AutoTabName = apps[entry[0]].AutoTabName,
|
||||
AutoTabName = autoTabName ?? apps[entry[0]].AutoTabName,
|
||||
Tab1Name = tab1 ?? apps[entry[0]].Tab1Name,
|
||||
Tab2Name = tab2,
|
||||
Tab2Name = tab2 ?? apps[entry[0]].Tab2Name,
|
||||
IsOverride = true
|
||||
};
|
||||
}
|
||||
@@ -388,56 +419,120 @@ namespace QuestAppLauncher
|
||||
Dictionary<string, ProcessedApp> apps,
|
||||
Dictionary<string, string> iconOverrides)
|
||||
{
|
||||
// Destroy existing scrollviews and tabs
|
||||
for (int i = 0; i < this.tabContainerContent.transform.childCount; i++)
|
||||
// Set up tabs
|
||||
var topTabs = new List<string>();
|
||||
var leftTabs = new List<string>();
|
||||
var rightTabs = new List<string>();
|
||||
|
||||
// Set auto tabs
|
||||
if (config.autoCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Destroy(this.tabContainerContent.transform.GetChild(i).gameObject);
|
||||
Destroy(this.scrollContainer.transform.GetChild(i).gameObject);
|
||||
topTabs.AddRange(Auto_Tabs);
|
||||
}
|
||||
else if (config.autoCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
leftTabs.AddRange(Auto_Tabs);
|
||||
}
|
||||
else if (config.autoCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
rightTabs.AddRange(Auto_Tabs);
|
||||
}
|
||||
|
||||
List<string> tabs;
|
||||
bool isNoneTab = false;
|
||||
bool isAutoTab = false;
|
||||
// Set custom tabs, sorted alphabetically
|
||||
var customTabs = apps.Where(x => null != x.Value.Tab1Name).Select(x => x.Value.Tab1Name).Union(apps
|
||||
.Where(x => null != x.Value.Tab2Name).Select(x => x.Value.Tab2Name))
|
||||
.Distinct(StringComparer.CurrentCultureIgnoreCase).ToList();
|
||||
customTabs.Sort();
|
||||
|
||||
if (config.categoryType.Equals(Config.Category_None, StringComparison.OrdinalIgnoreCase))
|
||||
if (config.customCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// No tabs - use special "None" tab
|
||||
tabs = new List<string>();
|
||||
tabs.Add(Tab_None);
|
||||
isNoneTab = true;
|
||||
topTabs.AddRange(customTabs);
|
||||
}
|
||||
else if (config.categoryType.Equals(Config.Category_Auto, StringComparison.OrdinalIgnoreCase))
|
||||
else if (config.customCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Add built-in tabs
|
||||
tabs = new List<string>();
|
||||
tabs.Add(Tab_Quest);
|
||||
tabs.Add(Tab_Go);
|
||||
tabs.Add(Tab_2D);
|
||||
isAutoTab = true;
|
||||
leftTabs.AddRange(customTabs);
|
||||
}
|
||||
else if (config.customCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
rightTabs.AddRange(customTabs);
|
||||
}
|
||||
|
||||
// Add the "all" top tab
|
||||
topTabs.Add(Tab_All);
|
||||
|
||||
// Process the tab containers
|
||||
var gridContents = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
ProcessTabContainer(config, topTabs, this.topTabContainer, this.topTabContainerContent, true, gridContents);
|
||||
ProcessTabContainer(config, leftTabs, this.leftTabContainer, this.leftTabContainerContent, false, gridContents);
|
||||
ProcessTabContainer(config, rightTabs, this.rightTabContainer, this.rightTabContainerContent, false, gridContents);
|
||||
|
||||
// Set panel size, use any grid content for reference (since they are all the same size)
|
||||
if (gridContents.Count > 0)
|
||||
{
|
||||
var size = SetGridSize(gridContents.First().Value, config.gridSize.rows, config.gridSize.cols);
|
||||
|
||||
// Adjust tab sizes
|
||||
ResizeTabContent(this.topTabContainer.transform, size, topTabs.Count, true);
|
||||
ResizeTabContent(this.leftTabContainer.transform, size, leftTabs.Count, false);
|
||||
ResizeTabContent(this.rightTabContainer.transform, size, rightTabs.Count, false);
|
||||
}
|
||||
|
||||
// Populate grid with app information (name & icon)
|
||||
// Sort by app name
|
||||
foreach (var app in apps.OrderBy(key => key.Value.AppName))
|
||||
{
|
||||
// Add to all tab
|
||||
yield return AddCellToGrid(app.Value, gridContents[Tab_All].transform, iconOverrides, currentActivity);
|
||||
|
||||
// Add to auto (built-in) tabs
|
||||
if (gridContents.ContainsKey(app.Value.AutoTabName))
|
||||
{
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.AutoTabName].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
|
||||
// Add to tab1
|
||||
if (null != app.Value.Tab1Name && gridContents.ContainsKey(app.Value.Tab1Name))
|
||||
{
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab1Name].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
|
||||
// Add to tab2
|
||||
if (null != app.Value.Tab2Name && gridContents.ContainsKey(app.Value.Tab2Name))
|
||||
{
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab2Name].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResizeTabContent(Transform transform, Vector2 size, int childCount, bool isHorizontal)
|
||||
{
|
||||
var rect = transform.GetComponent<RectTransform>();
|
||||
|
||||
// Resize the transform
|
||||
Vector2 newSize;
|
||||
if (isHorizontal)
|
||||
{
|
||||
newSize = new Vector2(size.x, rect.rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Construct list of custom tabs, sorted alphabetically and add built-in tabs up front
|
||||
tabs = apps.Select(x => x.Value.Tab1Name).Union(
|
||||
apps.Where(x => null != x.Value.Tab2Name).Select(x => x.Value.Tab2Name)).Distinct().ToList();
|
||||
tabs.Sort();
|
||||
if (tabs.Remove(Tab_2D))
|
||||
{
|
||||
tabs.Insert(0, Tab_2D);
|
||||
}
|
||||
if (tabs.Remove(Tab_Go))
|
||||
{
|
||||
tabs.Insert(0, Tab_Go);
|
||||
}
|
||||
if (tabs.Remove(Tab_Quest))
|
||||
{
|
||||
tabs.Insert(0, Tab_Quest);
|
||||
}
|
||||
newSize = new Vector2(rect.rect.width, size.y);
|
||||
}
|
||||
|
||||
var gridContents = new Dictionary<string, GameObject>();
|
||||
bool isFirstTab = true;
|
||||
rect.sizeDelta = newSize;
|
||||
|
||||
// Resize box collider
|
||||
var boxCollider = transform.GetComponent<BoxCollider>();
|
||||
boxCollider.size = new Vector3(newSize.x, newSize.y, (float)0.05);
|
||||
|
||||
// Refresh tab prev / next buttons
|
||||
transform.gameObject.GetComponent<ScrollButtonHandler>().RefreshScrollContent(childCount);
|
||||
}
|
||||
|
||||
private void ProcessTabContainer(Config config, List<string> tabs, GameObject tabContainer,
|
||||
GameObject tabContainerContent, bool setFirstTabActive, Dictionary<string, GameObject> gridContents)
|
||||
{
|
||||
// Create scroll views and tabs
|
||||
foreach (string tabName in tabs)
|
||||
{
|
||||
@@ -447,73 +542,24 @@ namespace QuestAppLauncher
|
||||
var scrollView = (GameObject)Instantiate(this.prefabScrollView, this.scrollContainer.transform);
|
||||
var scrollRectOverride = scrollView.GetComponent<ScrollRectOverride>();
|
||||
scrollRectOverride.trackingSpace = this.trackingSpace.transform;
|
||||
scrollRectOverride.name = tabName;
|
||||
|
||||
var gridContent = scrollRectOverride.content.gameObject;
|
||||
scrollView.SetActive(isFirstTab);
|
||||
|
||||
// Set grid size
|
||||
SetGridSize(gridContent, config.gridSize.rows, config.gridSize.cols);
|
||||
scrollView.SetActive(setFirstTabActive);
|
||||
|
||||
// Create tab
|
||||
var tab = (GameObject)Instantiate(this.prefabTab, this.tabContainerContent.transform);
|
||||
var tab = (GameObject)Instantiate(this.prefabTab, tabContainerContent.transform);
|
||||
tab.GetComponentInChildren<TextMeshProUGUI>().text = tabName;
|
||||
|
||||
var toggle = tab.GetComponent<Toggle>();
|
||||
toggle.isOn = isFirstTab;
|
||||
toggle.group = this.tabContainerContent.GetComponent<ToggleGroup>();
|
||||
toggle.isOn = setFirstTabActive;
|
||||
toggle.group = this.panelContainer.GetComponent<ToggleGroup>();
|
||||
toggle.onValueChanged.AddListener(scrollView.SetActive);
|
||||
|
||||
if (isNoneTab)
|
||||
{
|
||||
// Hide the special "None" tab
|
||||
tab.SetActive(false);
|
||||
}
|
||||
|
||||
isFirstTab = false;
|
||||
setFirstTabActive = false;
|
||||
|
||||
// Record the grid content
|
||||
gridContents[tabName] = scrollView.GetComponent<ScrollRect>().content.gameObject;
|
||||
}
|
||||
|
||||
// Refresh tab prev / next buttons
|
||||
this.tabContainer.GetComponent<ScrollButtonHandler>().RefreshScrollContent(tabs.Count);
|
||||
this.tabContainer.GetComponent<ScrollRectColliderMask>().Refresh();
|
||||
|
||||
// Populate grid with app information (name & icon)
|
||||
// Sort by app name
|
||||
foreach (var app in apps.OrderBy(key => key.Value.AppName))
|
||||
{
|
||||
if (config.showOnlyCustom && !app.Value.IsOverride)
|
||||
{
|
||||
// Since showOnlyCustom is set, skip apps that are not in the appnames.txt file
|
||||
Debug.LogFormat("Skipping non-Show Only Custom [{0}] Package: {1}, name: {2}",
|
||||
app.Value.Index, app.Value.PackageName, app.Value.AppName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isNoneTab)
|
||||
{
|
||||
// No tabs, so use the special "None" tab
|
||||
yield return AddCellToGrid(app.Value, gridContents[Tab_None].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
else if (isAutoTab)
|
||||
{
|
||||
// Add to auto (built-in) tabs
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.AutoTabName].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to tab1
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab1Name].transform, iconOverrides, currentActivity);
|
||||
|
||||
if (null != app.Value.Tab2Name)
|
||||
{
|
||||
// Tab2 exists, so add to tab2
|
||||
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab2Name].transform, iconOverrides, currentActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator AddCellToGrid(ProcessedApp app, Transform transform,
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace QuestAppLauncher
|
||||
{
|
||||
public class ScrollButtonHandler : MonoBehaviour
|
||||
{
|
||||
// Child object, used to determine size
|
||||
public GameObject prefabChild;
|
||||
|
||||
// Scroll content
|
||||
public RectTransform content;
|
||||
|
||||
[Tooltip("Button to go to the previous page")]
|
||||
public Button PrevButton;
|
||||
|
||||
[Tooltip("Button to go to the next page")]
|
||||
public Button NextButton;
|
||||
|
||||
[Tooltip("Whether tabs are horizontal (true) or vertical (false)")]
|
||||
public bool isHorizontal;
|
||||
|
||||
// Size of child object (either width or height)
|
||||
private float childSize;
|
||||
|
||||
// Current rect transform
|
||||
private RectTransform rectTransform;
|
||||
|
||||
private const float CmToInch = 2.54f;
|
||||
private const float DragThresholdCM = 50f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
this.PrevButton.onClick.AddListener(() => { ScrollPrev(); });
|
||||
this.NextButton.onClick.AddListener(() => { ScrollNext(); });
|
||||
|
||||
this.PrevButton.gameObject.SetActive(false);
|
||||
this.NextButton.gameObject.SetActive(false);
|
||||
|
||||
this.rectTransform = GetComponent<RectTransform>();
|
||||
this.childSize = this.isHorizontal ? this.prefabChild.GetComponent<RectTransform>().sizeDelta.x :
|
||||
this.prefabChild.GetComponent<RectTransform>().sizeDelta.y;
|
||||
|
||||
RefreshScrollContent(0);
|
||||
|
||||
SetPhysicalDragThreshold();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void RefreshScrollContent(int numChildren)
|
||||
{
|
||||
Canvas.ForceUpdateCanvases();
|
||||
|
||||
float contentSize = numChildren * this.childSize;
|
||||
var recTransformSize = this.isHorizontal ? this.rectTransform.sizeDelta.x :
|
||||
this.rectTransform.sizeDelta.y;
|
||||
|
||||
if (recTransformSize >= contentSize)
|
||||
{
|
||||
// Viewport can fit the content, so hide the buttons
|
||||
this.PrevButton.gameObject.SetActive(false);
|
||||
this.NextButton.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.PrevButton.gameObject.SetActive(true);
|
||||
this.NextButton.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPhysicalDragThreshold()
|
||||
{
|
||||
Debug.LogFormat("Drag threshold: {0}", EventSystem.current.pixelDragThreshold);
|
||||
|
||||
EventSystem.current.pixelDragThreshold = (int)(DragThresholdCM * Screen.dpi / CmToInch);
|
||||
Debug.LogFormat("Updated drag threshold: {0}", EventSystem.current.pixelDragThreshold);
|
||||
}
|
||||
|
||||
public void ScrollPrev()
|
||||
{
|
||||
Vector2 newPosition;
|
||||
|
||||
if (this.isHorizontal)
|
||||
{
|
||||
newPosition = new Vector2(this.content.transform.localPosition.x + this.childSize,
|
||||
this.content.transform.localPosition.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
newPosition = new Vector2(this.content.transform.localPosition.x,
|
||||
this.content.transform.localPosition.y - this.childSize);
|
||||
}
|
||||
this.content.transform.localPosition = newPosition;
|
||||
}
|
||||
|
||||
public void ScrollNext()
|
||||
{
|
||||
Vector2 newPosition = new Vector2(this.content.transform.localPosition.x - this.childSize, this.content.transform.localPosition.y);
|
||||
|
||||
if (this.isHorizontal)
|
||||
{
|
||||
newPosition = new Vector2(this.content.transform.localPosition.x - this.childSize,
|
||||
this.content.transform.localPosition.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
newPosition = new Vector2(this.content.transform.localPosition.x,
|
||||
this.content.transform.localPosition.y + this.childSize);
|
||||
}
|
||||
|
||||
this.content.transform.localPosition = newPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 390013d26c40ccd4ab21b46bd10bf9dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using ControllerSelection;
|
||||
|
||||
public class ScrollRectColliderMask : MonoBehaviour
|
||||
{
|
||||
// Content
|
||||
public RectTransform content;
|
||||
|
||||
// Tracking space used for ray cast
|
||||
public Transform trackingSpace = null;
|
||||
|
||||
// Box collider used for ray cast
|
||||
private BoxCollider boxCollider = null;
|
||||
|
||||
// Whether the pointer is within bounds of the scroll rect
|
||||
private bool isInBounds = true;
|
||||
private bool isInitialized = false;
|
||||
|
||||
private OVRInput.Controller activeController = OVRInput.Controller.None;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
this.boxCollider = GetComponent<BoxCollider>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
this.activeController = OVRInputHelpers.GetControllerForButton(OVRInput.Button.PrimaryIndexTrigger, this.activeController);
|
||||
Ray pointer = OVRInputHelpers.GetSelectionRay(this.activeController, this.trackingSpace);
|
||||
|
||||
RaycastHit hit;
|
||||
if (this.boxCollider.Raycast(pointer, out hit, 500))
|
||||
{
|
||||
// We got a hit in the scroll view. Check if we're already within the bounds - if so, do nothing.
|
||||
if (!isInBounds)
|
||||
{
|
||||
// We entered the scroll view, so enable box colliders on children.
|
||||
foreach (var boxCollider in this.content.gameObject.GetComponentsInChildren<BoxCollider>())
|
||||
{
|
||||
boxCollider.enabled = true;
|
||||
}
|
||||
|
||||
isInBounds = true;
|
||||
}
|
||||
}
|
||||
else if (isInBounds)
|
||||
{
|
||||
// We are outside the scroll view and were previously inside, so disable box colliders on children.
|
||||
foreach (var boxCollider in this.content.gameObject.GetComponentsInChildren<BoxCollider>())
|
||||
{
|
||||
boxCollider.enabled = false;
|
||||
}
|
||||
|
||||
isInBounds = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f2a3df6684af7245a2512d708d72e62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -20,11 +20,16 @@ namespace QuestAppLauncher
|
||||
public GameObject gridRowsText;
|
||||
public GameObject gridPopulation;
|
||||
public GameObject show2DToggle;
|
||||
public GameObject showOnlyCustomToggle;
|
||||
|
||||
public Toggle tabsNone;
|
||||
public Toggle tabsAuto;
|
||||
public Toggle tabsCustom;
|
||||
public Toggle tabsAutoOff;
|
||||
public Toggle tabsAutoTop;
|
||||
public Toggle tabsAutoLeft;
|
||||
public Toggle tabsAutoRight;
|
||||
|
||||
public Toggle tabsCustomOff;
|
||||
public Toggle tabsCustomTop;
|
||||
public Toggle tabsCustomLeft;
|
||||
public Toggle tabsCustomRight;
|
||||
|
||||
private bool deletedHiddenAppsFile = false;
|
||||
|
||||
@@ -56,21 +61,40 @@ namespace QuestAppLauncher
|
||||
// Set 2D toggle
|
||||
this.show2DToggle.GetComponent<Toggle>().SetIsOnWithoutNotify(this.config.show2D);
|
||||
|
||||
// Set ShowOnlyCustom toggle
|
||||
this.showOnlyCustomToggle.GetComponent<Toggle>().SetIsOnWithoutNotify(this.config.showOnlyCustom);
|
||||
|
||||
// Set tab mode
|
||||
if (this.config.categoryType.Equals(Config.Category_None, StringComparison.OrdinalIgnoreCase))
|
||||
// Set auto tab mode
|
||||
if (this.config.autoCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsNone.isOn = true;
|
||||
this.tabsAutoTop.isOn = true;
|
||||
}
|
||||
else if (this.config.categoryType.Equals(Config.Category_Auto, StringComparison.OrdinalIgnoreCase))
|
||||
else if (this.config.autoCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsAuto.isOn = true;
|
||||
this.tabsAutoLeft.isOn = true;
|
||||
}
|
||||
else if (this.config.autoCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsAutoRight.isOn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tabsCustom.isOn = true;
|
||||
this.tabsAutoOff.isOn = true;
|
||||
}
|
||||
|
||||
// Set custom tab mode
|
||||
if (this.config.customCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsCustomTop.isOn = true;
|
||||
}
|
||||
else if (this.config.customCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsCustomLeft.isOn = true;
|
||||
}
|
||||
else if (this.config.customCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsCustomRight.isOn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tabsCustomOff.isOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,33 +158,53 @@ namespace QuestAppLauncher
|
||||
saveConfig = true;
|
||||
}
|
||||
|
||||
// Update ShowOnlyCustom toggle
|
||||
var showOnlyCustom = this.showOnlyCustomToggle.GetComponent<Toggle>().isOn;
|
||||
if (showOnlyCustom != this.config.showOnlyCustom)
|
||||
// Update auto tab mode
|
||||
string tabAutoMode;
|
||||
if (this.tabsAutoTop.isOn)
|
||||
{
|
||||
this.config.showOnlyCustom = showOnlyCustom;
|
||||
saveConfig = true;
|
||||
tabAutoMode = Config.Category_Top;
|
||||
}
|
||||
|
||||
// Update tabbing
|
||||
string tabMode;
|
||||
if (this.tabsNone.isOn)
|
||||
else if (this.tabsAutoLeft.isOn)
|
||||
{
|
||||
tabMode = Config.Category_None;
|
||||
tabAutoMode = Config.Category_Left;
|
||||
}
|
||||
else if (this.tabsAuto.isOn)
|
||||
else if (this.tabsAutoRight.isOn)
|
||||
{
|
||||
tabMode = Config.Category_Auto;
|
||||
tabAutoMode = Config.Category_Right;
|
||||
}
|
||||
else
|
||||
{
|
||||
tabMode = Config.Category_Custom;
|
||||
tabAutoMode = Config.Category_Off;
|
||||
}
|
||||
|
||||
if (!this.config.categoryType.Equals(tabMode, StringComparison.OrdinalIgnoreCase))
|
||||
if (!this.config.autoCategory.Equals(tabAutoMode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.tabsNone.isOn = true;
|
||||
this.config.categoryType = tabMode;
|
||||
this.config.autoCategory = tabAutoMode;
|
||||
saveConfig = true;
|
||||
}
|
||||
|
||||
// Update auto tab mode
|
||||
string tabCustomMode;
|
||||
if (this.tabsCustomTop.isOn)
|
||||
{
|
||||
tabCustomMode = Config.Category_Top;
|
||||
}
|
||||
else if (this.tabsCustomLeft.isOn)
|
||||
{
|
||||
tabCustomMode = Config.Category_Left;
|
||||
}
|
||||
else if (this.tabsCustomRight.isOn)
|
||||
{
|
||||
tabCustomMode = Config.Category_Right;
|
||||
}
|
||||
else
|
||||
{
|
||||
tabCustomMode = Config.Category_Off;
|
||||
}
|
||||
|
||||
if (!this.config.customCategory.Equals(tabCustomMode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
this.config.customCategory = tabCustomMode;
|
||||
saveConfig = true;
|
||||
}
|
||||
|
||||
@@ -174,7 +218,7 @@ namespace QuestAppLauncher
|
||||
if (saveConfig || deletedHiddenAppsFile)
|
||||
{
|
||||
Debug.Log("Re-populating panel");
|
||||
this.gridPopulation.GetComponent<GridPopulation>().StartPopulate();
|
||||
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user