首次提交
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
[RequireComponent(typeof(Button))]
|
||||
public class ApplySettingsButton : MonoBehaviour
|
||||
{
|
||||
Button Button { get; set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Button = GetComponent<Button>();
|
||||
Button.onClick.AddListener(OnClick);
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
GraphicSettingsManager.Instance.ApplySettings();
|
||||
GraphicSettingsManager.Instance.SaveSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17e9f2e223bd22a4fabb136cd3f16ba9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,118 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="UnityEngine.UI.ScrollRect"/> does not automatically scroll up or down when using the keyboard or gamepad.
|
||||
/// This class automatically handles scrolling, by scrolling towards the selected element of a <see cref="UnityEngine.UI.ScrollRect"/> when selection changes.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(ScrollRect))]
|
||||
[DefaultExecutionOrder(1)]
|
||||
public class AutoScrollHandler : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The currently selected game object
|
||||
/// </summary>
|
||||
GameObject selected = null;
|
||||
|
||||
/// <summary>
|
||||
/// The previously selected game object
|
||||
/// </summary>
|
||||
GameObject previousSelected = null;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("Scroll speed when changing selection")]
|
||||
float scrollSpeed = 5.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the controlled <see cref="UnityEngine.UI.ScrollRect"/> component
|
||||
/// </summary>
|
||||
ScrollRect ScrollRect { get; set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ScrollRect = GetComponent<ScrollRect>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
selected = EventSystem.current.currentSelectedGameObject;
|
||||
previousSelected = selected;
|
||||
|
||||
// Auto focus the first element
|
||||
ScrollRect.verticalScrollbar.value = 1;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
selected = EventSystem.current.currentSelectedGameObject;
|
||||
|
||||
// Check whether the selection has changed
|
||||
if (selected != previousSelected)
|
||||
{
|
||||
previousSelected = selected;
|
||||
|
||||
if (selected != null)
|
||||
{
|
||||
OnSelectionChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scroll towards the selected element when the selection has changed
|
||||
/// </summary>
|
||||
void OnSelectionChanged()
|
||||
{
|
||||
if (TryGetIndex(selected, out var index))
|
||||
{
|
||||
StopAllCoroutines();
|
||||
StartCoroutine(ScrollTowards(index));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the index of the given element in the content
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
bool TryGetIndex(GameObject element, out int index)
|
||||
{
|
||||
index = 0;
|
||||
|
||||
foreach (Transform child in ScrollRect.content)
|
||||
{
|
||||
if (element == child.gameObject)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scrolls towards the content element with the given index
|
||||
/// </summary>
|
||||
/// <param name="targetIndex"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerator ScrollTowards(int targetIndex)
|
||||
{
|
||||
var scrollbar = ScrollRect.verticalScrollbar;
|
||||
|
||||
float target = 1 - targetIndex / (float)(ScrollRect.content.childCount - 1);
|
||||
|
||||
while (Mathf.Abs(scrollbar.value - target) > 0.01f)
|
||||
{
|
||||
scrollbar.value = Mathf.MoveTowards(scrollbar.value, target, scrollSpeed * Time.deltaTime);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 458c41eab5f10bb45926d21f44fa218d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of the <see cref="MultiOptionSelector"/>.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(AudioSource))]
|
||||
public class DefaultMultiOptionSelector : MultiOptionSelector, IMoveHandler
|
||||
{
|
||||
[Header("Text")]
|
||||
[SerializeField]
|
||||
TMPro.TextMeshProUGUI labelText;
|
||||
|
||||
[SerializeField]
|
||||
TMPro.TextMeshProUGUI valueText;
|
||||
|
||||
[Header("Audio")]
|
||||
[SerializeField]
|
||||
AudioClip selectionChangedSFX;
|
||||
|
||||
[SerializeField]
|
||||
AudioClip verticalMovementSFX;
|
||||
|
||||
[Header("Settings")]
|
||||
[Tooltip("When enabled, the selector will loop through the options when reaching the limits.")]
|
||||
[SerializeField]
|
||||
bool loop = true;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current selection
|
||||
/// </summary>
|
||||
int currentIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// A list of all possible values
|
||||
/// </summary>
|
||||
List<string> Values;
|
||||
|
||||
/// <summary>
|
||||
/// Event being invoked when the index has been changed
|
||||
/// </summary>
|
||||
UnityAction<int> OnSelectionChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the Audio Source Component
|
||||
/// </summary>
|
||||
AudioSource AudioSource { get; set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
AudioSource = GetComponent<AudioSource>();
|
||||
}
|
||||
|
||||
public override void Initialize(string label, List<string> values, int index, UnityAction<int> onSelectionChanged)
|
||||
{
|
||||
OnSelectionChanged += onSelectionChanged;
|
||||
|
||||
labelText.text = label;
|
||||
Values = values;
|
||||
currentIndex = index;
|
||||
|
||||
UpdateValueText();
|
||||
}
|
||||
|
||||
public void OnMove(AxisEventData eventData)
|
||||
{
|
||||
Move(eventData.moveVector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the next option
|
||||
/// </summary>
|
||||
public void SelectNextOption() => Move(Vector2.right);
|
||||
|
||||
/// <summary>
|
||||
/// Selects the previous Option
|
||||
/// </summary>
|
||||
public void SelectPreviousOption() => Move(Vector2.left);
|
||||
|
||||
private void Move(Vector2 direction)
|
||||
{
|
||||
int previousIndex = currentIndex;
|
||||
|
||||
// Increase the index when moving to the right
|
||||
if (direction.x > 0)
|
||||
{
|
||||
currentIndex++;
|
||||
|
||||
if (currentIndex >= Values.Count)
|
||||
{
|
||||
currentIndex = loop ? 0 : Values.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrease the index when moving to the left
|
||||
if (direction.x < 0)
|
||||
{
|
||||
currentIndex--;
|
||||
|
||||
if (currentIndex < 0)
|
||||
{
|
||||
currentIndex = loop ? Values.Count - 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (direction.y != 0)
|
||||
{
|
||||
if (AudioSource != null && verticalMovementSFX != null)
|
||||
{
|
||||
PlayAudioFeedback(verticalMovementSFX);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the index has changed
|
||||
if (previousIndex != currentIndex)
|
||||
{
|
||||
OnSelectionChanged?.Invoke(currentIndex);
|
||||
UpdateValueText();
|
||||
PlayAudioFeedback(selectionChangedSFX);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateValueText()
|
||||
{
|
||||
valueText.text = Values[currentIndex];
|
||||
}
|
||||
|
||||
void PlayAudioFeedback(AudioClip audioClip)
|
||||
{
|
||||
if (AudioSource != null && audioClip != null)
|
||||
{
|
||||
AudioSource.PlayOneShot(audioClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 552bbb859029b3642848169db0e28eab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
public class GraphicSettingsPanel : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
[Tooltip("The parent object all UI selectors will be added to. This would be for example the content GameObject of a ScrollView")]
|
||||
Transform container;
|
||||
|
||||
[SerializeField]
|
||||
MultiOptionSelector MultiOptionSelectorPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the Graphic Settings Manager
|
||||
/// </summary>
|
||||
GraphicSettingsManager GraphicSettingsManager { get; set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
GraphicSettingsManager = FindObjectOfType<GraphicSettingsManager>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Get all graphic settings
|
||||
var settings = GraphicSettingsManager.GetGraphicSettings();
|
||||
|
||||
// List holding all selectors
|
||||
List<GameObject> selectors = new();
|
||||
|
||||
// Create the appropriate selector UI elements for each setting
|
||||
foreach (var setting in settings)
|
||||
{
|
||||
if (setting is IMultiOptionGraphicSetting multiOptionSettings)
|
||||
{
|
||||
var multiOptionSelector = Instantiate(MultiOptionSelectorPrefab, container);
|
||||
|
||||
multiOptionSelector.Initialize(setting.GetSettingName(), multiOptionSettings.GetOptionNames(), multiOptionSettings.GetIndex(), multiOptionSettings.SetIndex);
|
||||
|
||||
selectors.Add(multiOptionSelector.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically select the first element
|
||||
if (selectors.Count > 0)
|
||||
{
|
||||
EventSystem.current.SetSelectedGameObject(selectors[0]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3074d3c0feba9fc4f84a74849ac39d65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: cde92c4be2e51894bb915456c3d44460, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Ilumisoft.GraphicsControl.UI",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:7f595fd175e67274183d17fac15b74c9",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f167fb3726278c4481b9f96f60458bd
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
public abstract class MultiOptionSelector : MonoBehaviour
|
||||
{
|
||||
public abstract void Initialize(string label, List<string> values, int index, UnityAction<int> onSelectionChanged);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e948756a0947b2d478b0285f4ab1d359
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Ilumisoft.GraphicsControl.UI
|
||||
{
|
||||
public class PointerDownHandler : MonoBehaviour, IPointerDownHandler
|
||||
{
|
||||
public UnityEvent OnClick = new();
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
OnClick.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f1b5a37363ca0c468220aeff6833044
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user