Added custom grid size support in config.json

- Added support for config.json
- Added custom grid size support in config.json (see readme for instructions)
This commit is contained in:
tverona1
2019-07-21 18:56:25 -07:00
parent 0d5e94c023
commit 7fb1053be7
9 changed files with 1624 additions and 149 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6269b6df21455a244a60057eaa3ff7af
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace QuestAppLauncher
{
/// <summary>
/// Root config object
/// </summary>
[Serializable]
public class Config
{
/// <summary>
/// Grid size
/// </summary>
[Serializable]
public class GridSize
{
public int rows;
public int cols;
}
public GridSize gridSize;
}
/// <summary>
/// Class responsible for loading / saving config into a config.json file.
/// </summary>
public class ConfigPersistence
{
// File name of app name overrides
const string ConfigFileName = "config.json";
/// <summary>
/// Load config from file
/// </summary>
/// <param name="config">Config object that will be overwritten</param>
static public void LoadConfig(Config config)
{
var configFilePath = Path.Combine(UnityEngine.Application.persistentDataPath, ConfigFileName);
if (File.Exists(configFilePath))
{
Debug.Log("Found config file: " + configFilePath);
var jsonConfig = File.ReadAllText(configFilePath);
try
{
JsonUtility.FromJsonOverwrite(jsonConfig, config);
}
catch (Exception e)
{
Debug.Log(string.Format("Failed to read config: {0}", e.Message));
}
}
}
/// <summary>
/// Save config to a file
/// </summary>
/// <param name="config"></param>
static public void SaveConfig(Config config)
{
var configFilePath = Path.Combine(UnityEngine.Application.persistentDataPath, ConfigFileName);
Debug.Log("Saving config file: " + configFilePath);
try
{
File.WriteAllText(configFilePath, JsonUtility.ToJson(config, true));
}
catch (Exception e)
{
Debug.Log(string.Format("Failed to read config: {0}", e.Message));
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6884476ef6b801242904ff090df0fb84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+71
View File
@@ -25,12 +25,21 @@ namespace QuestAppLauncher
// Extension search for icon overrides
const string IconOverrideExtSearch = "*.jpg";
// Canvas game object
public GameObject canvas;
// Scroll view game object
public GameObject scrollView;
// Grid content game object
public GameObject gridContent;
// App info GameObject (a cell in the grid content)
public GameObject prefab;
// Configuration
private Config config = new Config();
#region MonoBehaviour handler
void Start()
@@ -41,6 +50,9 @@ namespace QuestAppLauncher
// Initialize the core platform
Core.AsyncInitialize();
// Load configuration
StartCoroutine(ProcessConfig());
// Populate the grid
StartCoroutine(Populate());
}
@@ -117,6 +129,65 @@ namespace QuestAppLauncher
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
/// <summary>
/// Loads & processes config
/// </summary>
/// <returns></returns>
IEnumerator ProcessConfig()
{
// Load config
ConfigPersistence.LoadConfig(this.config);
ProcessGridSize();
yield return null;
}
private void ProcessGridSize()
{
// Make sure grid size have sane value
if (0 == this.config.gridSize.cols && 0 == this.config.gridSize.rows)
{
// If not initialized, default to 3x3
this.config.gridSize.cols = 3;
this.config.gridSize.rows = 3;
}
this.config.gridSize.cols = Math.Min(this.config.gridSize.cols, 10);
this.config.gridSize.cols = Math.Max(this.config.gridSize.cols, 1);
this.config.gridSize.rows = Math.Min(this.config.gridSize.rows, 50);
this.config.gridSize.rows = Math.Max(this.config.gridSize.rows, 1);
// Get cell size, spacing & padding from the grid layout
var gridLayoutGroup = this.gridContent.GetComponent<GridLayoutGroup>();
var cellHeight = gridLayoutGroup.cellSize.y;
var cellWidth = gridLayoutGroup.cellSize.x;
var paddingX = gridLayoutGroup.padding.horizontal;
var paddingY = gridLayoutGroup.padding.vertical;
var spaceX = gridLayoutGroup.spacing.x;
var spaceY = gridLayoutGroup.spacing.y;
// Width = horizontal padding + # cols * cell width + (# cols - 1) * horizontal spacing
var width = paddingX + this.config.gridSize.cols * cellWidth + (this.config.gridSize.cols - 1) * spaceX;
// Height = vertical padding + # rows * cell height + (# rows - 1) * veritcal spacing + a bit more to show there are more elements
var height = paddingY + this.config.gridSize.rows * cellHeight + (this.config.gridSize.rows - 1) * spaceY + 120;
Debug.Log(string.Format("Setting grid size to {0} x {1} cells", this.config.gridSize.cols, this.config.gridSize.rows));
Debug.Log(string.Format("Grid size calculated width x height: {0} x {1}", width, height));
// Adjust canvas rect transform
var canvasRectTransform = this.canvas.GetComponent<RectTransform>();
canvasRectTransform.sizeDelta = new Vector2(width, height);
// Adjust scroll view rect transform
var scrollViewRectTransform = this.scrollView.GetComponent<RectTransform>();
scrollViewRectTransform.sizeDelta = new Vector2(width, height);
// Adjust scroll view box collider
var scrollViewBoxCollider = this.scrollView.GetComponent<BoxCollider>();
scrollViewBoxCollider.size = new Vector3(width, height, 0);
}
/// <summary>
/// Populate the grid from installed apps
/// </summary>
+57 -54
View File
@@ -2,62 +2,65 @@
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class OnInteraction : MonoBehaviour
namespace QuestAppLauncher
{
protected Material oldHoverMat;
public Material yellowMat;
public Material backIdle;
public Material backACtive;
public UnityEngine.UI.Text outText;
public void OnHoverEnter(Transform t)
public class OnInteraction : MonoBehaviour
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
protected Material oldHoverMat;
public Material yellowMat;
public Material backIdle;
public Material backACtive;
public UnityEngine.UI.Text outText;
public void OnHoverEnter(Transform t)
{
// Enable border
EnableBorder(t, true);
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Enable border
EnableBorder(t, true);
}
}
public void OnHoverExit(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Disable border
EnableBorder(t, false);
}
}
public void OnSelected(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Launch app
Debug.Log("Launching: " + appEntry.appName + " (package id: " + appEntry.packageId + ")");
QuestAppLauncher.GridPopulation.LaunchApp(appEntry.packageId);
}
}
public void OnSelectedPressedBorY(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Add package name to excluded file
Debug.Log("Hiding: " + appEntry.appName + " (package id: " + appEntry.packageId + ")");
QuestAppLauncher.GridPopulation.AddAppToExcludedFile(appEntry.packageId);
// Remove ourselves from the gridview
Destroy(t.gameObject);
}
}
void EnableBorder(Transform t, bool enable)
{
var border = t.Find("Border");
border?.gameObject.SetActive(enable);
}
}
public void OnHoverExit(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Disable border
EnableBorder(t, false);
}
}
public void OnSelected(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Launch app
Debug.Log("Launching: " + appEntry.appName + " (package id: " + appEntry.packageId + ")");
QuestAppLauncher.GridPopulation.LaunchApp(appEntry.packageId);
}
}
public void OnSelectedPressedBorY(Transform t)
{
var appEntry = t.gameObject.GetComponent("AppEntry") as AppEntry;
if (null != appEntry)
{
// Add package name to excluded file
Debug.Log("Hiding: " + appEntry.appName + " (package id: " + appEntry.packageId + ")");
QuestAppLauncher.GridPopulation.AddAppToExcludedFile(appEntry.packageId);
// Remove ourselves from the gridview
Destroy(t.gameObject);
}
}
void EnableBorder(Transform t, bool enable)
{
var border = t.Find("Border");
border?.gameObject.SetActive(enable);
}
}
}
+48 -45
View File
@@ -3,62 +3,65 @@ using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ScrollRectOverride : ScrollRect, IMoveHandler, IPointerClickHandler, IScrollHandler
namespace QuestAppLauncher
{
private const float speedMultiplier = 15f;
private float cellHeight = 0f;
void Start()
public class ScrollRectOverride : ScrollRect, IMoveHandler, IPointerClickHandler, IScrollHandler
{
this.cellHeight = this.transform.GetComponentInChildren<GridLayoutGroup>().cellSize.y;
}
private const float speedMultiplier = 15f;
private float cellHeight = 0f;
void Update()
{
// Get vector from either left or right thumbstick
var moveVector = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick);
if (moveVector.x == 0 && moveVector.y == 0)
void Start()
{
moveVector = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick);
this.cellHeight = this.transform.GetComponentInChildren<GridLayoutGroup>().cellSize.y;
}
// Scroll by a fixed amount proportional to thumbstick position on each frame
// and map this to a fraction of the total viewport size:
// moveVector.y: The thumbstick vertical position normalized to [-1,1].
// Time.deltaTime: The time delta since last frame
// speedMultiplier: Just a multiplier to get a good scrolling speed.
// So, moveVector.y * Time.deltaTime * speedMultiplier = the amount to scroll in "units"
// proportional to thumbstick position since last frame.
// this.cellHeight / this.content.sizeDelta.y = cell height / total content height.
float verticalIncrement = moveVector.y * Time.deltaTime * speedMultiplier * this.cellHeight / this.content.sizeDelta.y;
this.verticalNormalizedPosition = Mathf.Clamp01(this.verticalNormalizedPosition + verticalIncrement);
}
void Update()
{
// Get vector from either left or right thumbstick
var moveVector = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick);
if (moveVector.x == 0 && moveVector.y == 0)
{
moveVector = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick);
}
public void OnPointerClick(PointerEventData e)
{
}
// Scroll by a fixed amount proportional to thumbstick position on each frame
// and map this to a fraction of the total viewport size:
// moveVector.y: The thumbstick vertical position normalized to [-1,1].
// Time.deltaTime: The time delta since last frame
// speedMultiplier: Just a multiplier to get a good scrolling speed.
// So, moveVector.y * Time.deltaTime * speedMultiplier = the amount to scroll in "units"
// proportional to thumbstick position since last frame.
// this.cellHeight / this.content.sizeDelta.y = cell height / total content height.
float verticalIncrement = moveVector.y * Time.deltaTime * speedMultiplier * this.cellHeight / this.content.sizeDelta.y;
this.verticalNormalizedPosition = Mathf.Clamp01(this.verticalNormalizedPosition + verticalIncrement);
}
public override void OnBeginDrag(PointerEventData eventData)
{
}
public void OnPointerClick(PointerEventData e)
{
}
void IMoveHandler.OnMove(AxisEventData e)
{
}
public override void OnBeginDrag(PointerEventData eventData)
{
}
void IScrollHandler.OnScroll(PointerEventData eventData)
{
}
void IMoveHandler.OnMove(AxisEventData e)
{
}
void OnMouseDrag()
{
}
void IScrollHandler.OnScroll(PointerEventData eventData)
{
}
void OnMouseUp()
{
}
void OnMouseDrag()
{
}
void OnMouseDown()
{
void OnMouseUp()
{
}
void OnMouseDown()
{
}
}
}
}
+33 -31
View File
@@ -3,40 +3,42 @@ using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SettingsHandler : MonoBehaviour
namespace QuestAppLauncher
{
public GameObject scrollView;
public GameObject openSettingsButton;
public GameObject closeSettingsButton;
public GameObject settingsView;
public void OpenSettings()
public class SettingsHandler : MonoBehaviour
{
Debug.Log("Open Settings");
scrollView.SetActive(false);
openSettingsButton.SetActive(false);
closeSettingsButton.SetActive(true);
settingsView.SetActive(true);
}
public GameObject scrollView;
public GameObject openSettingsButton;
public GameObject closeSettingsButton;
public GameObject settingsView;
public void CloseSettings()
{
Debug.Log("Close Settings");
scrollView.SetActive(true);
openSettingsButton.SetActive(true);
closeSettingsButton.SetActive(false);
settingsView.SetActive(false);
}
public void OpenSettings()
{
Debug.Log("Open Settings");
scrollView.SetActive(false);
openSettingsButton.SetActive(false);
closeSettingsButton.SetActive(true);
settingsView.SetActive(true);
}
public void RefreshScene()
{
Debug.Log("Scene refreshed");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void CloseSettings()
{
Debug.Log("Close Settings");
scrollView.SetActive(true);
openSettingsButton.SetActive(true);
closeSettingsButton.SetActive(false);
settingsView.SetActive(false);
}
public void DeleteExcludedApksFile()
{
Debug.Log("Delete Excluded Apk List");
QuestAppLauncher.GridPopulation.DeleteExcludedApksFile();
public void ResizeGrid(int selection)
{
Debug.Log("Resize grid: " + selection);
}
public void DeleteExcludedApksFile()
{
Debug.Log("Delete Excluded Apk List");
QuestAppLauncher.GridPopulation.DeleteExcludedApksFile();
}
}
}
}
+22 -3
View File
@@ -5,17 +5,36 @@ An app launcher for Quest implemented in Unity.
## Overriding app icons and names
For each installed app, we extract the default app name (PackageManager.getApplicationLabel()) and default app icon (PackageManager.getApplicationIcon()). Sometimes, however, these do not map to the actual app name and icon in the Oculus Store. In order to override this, do the following:
1) Override app names: Create a file called appnames.txt. Add a line per app with comma-separated package-id and desired name. Example:
# Override app names
Create a file called **appnames.txt**. Add a line per app with comma-separated package-id and desired name. Example:
appnames.txt:
com.mycompany.myapp,My Application
com.othercompany.otherapp,Other application
2) Override app icons: Create a jpg file per app with the package-id as the filename. Example:
Copy this file (appnames.txt) to the following location on your Quest: Android/data/aaa.QuestAppLauncher.App/files
# Override app icons
Create a jpg file per app with the package-id as the filename. Example:
com.mycompany.myapp.jpg
com.thirdcompany.yetanotherapp.jpg
Copy these files to the following location on your Quest: Android/data/aaa.QuestAppLauncher.App/files
3) Copy the above contents (appnames.txt + jpg files) to the following location on your Quest: Android/data/aaa.QuestAppLauncher.App/files
## Configuration
The app can be customized by creating a **config.json** file and copying it to the following location on your Quest: Android/data/aaa.QuestAppLauncher.App/files.
The following options are supported:
# Setting Grid Size
The default grid size is 3x3 cells. The grid size can be customer by specifying grid rows and columns as in the following example:
```
{
"gridSize": {
"rows": 2,
"cols": 4
}
}
```
## Source structure:
- Assets/Scenes/QuestAppLauncher.unity: The main scene