Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Editor/Tests/Validation.meta → Scripts.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions Scripts/Duck.Forms.asmdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "Duck.Forms"
}
7 changes: 7 additions & 0 deletions Scripts/Duck.Forms.asmdef.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
17 changes: 17 additions & 0 deletions Scripts/Editor/Duck.Forms.Editor.asmdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Duck.Forms.Editor",
"references": [
"GUID:3ccb158d1f7a14482916322a7272767a"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}
7 changes: 7 additions & 0 deletions Scripts/Editor/Duck.Forms.Editor.asmdef.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
File renamed without changes.
53 changes: 53 additions & 0 deletions Scripts/Editor/SelectableFocusSwitcherEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;

namespace DUCK.Forms.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(SelectableFocusSwitcher))]
public class SelectableFocusSwitcherEditor : UnityEditor.Editor
{
private SerializedProperty autoDetectSelectables;
private SerializedProperty selectables;
private ReorderableList list;

void OnEnable()
{
selectables = serializedObject.FindProperty("selectables");
list = new ReorderableList(serializedObject, selectables, true, true, true, true);
autoDetectSelectables = serializedObject.FindProperty("autoDetectSelectables");
list.drawElementCallback = DrawListItems;
list.drawHeaderCallback = DrawHeader;
}

public override void OnInspectorGUI()
{
serializedObject.Update();
autoDetectSelectables.boolValue = EditorGUILayout.Toggle("Auto Detect", autoDetectSelectables.boolValue);
list.DoLayoutList();
serializedObject.ApplyModifiedProperties();

SelectableFocusSwitcher myScript = (SelectableFocusSwitcher) target;
if (!autoDetectSelectables.boolValue)
{
if (GUILayout.Button("Detect Selectables"))
{
myScript.FindSelectablesInScene();
}
}
}

void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty element = list.serializedProperty.GetArrayElementAtIndex(index);
EditorGUI.PropertyField(new Rect(20, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element);
}

void DrawHeader(Rect rect)
{
string name = "Selectables";
EditorGUI.LabelField(rect, name);
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
105 changes: 105 additions & 0 deletions Scripts/SelectableFocusSwitcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace DUCK.Forms
{
public class SelectableFocusSwitcher : MonoBehaviour
{
[Tooltip("Will add all active selectable UI elements to the list on awake, you cannot decide the order.")]
[SerializeField]
public bool autoDetectSelectables = false;

[Tooltip("Customise the order of which selectables will be focused on pressing tab.")] [SerializeField]
private List<Selectable> selectables;
private EventSystem eventSystem;

void Awake()
{
if(selectables == null){
selectables = new List<Selectable>();
}
eventSystem = FindObjectOfType<EventSystem>();

if (autoDetectSelectables)
{
FindActiveSelectionIndex();
}
}

public void FindSelectablesInScene()
{
Selectable[] sceneSelectables = FindObjectsOfType<Selectable>();
for (int i = 0; i < sceneSelectables.Length; i++)
{
AddSelectable(sceneSelectables[i]);
}
}

public void AddSelectable(Selectable selectable)
{
if (!selectables.Contains(selectable))
{
selectables.Add(selectable);
}
}

void Update()
{
if (Input.GetKeyDown(KeyCode.Tab))
{
OnTab();
}
}

private void OnTab()
{
int selectionIndex = FindActiveSelectionIndex();
CleanDestroyedObjects();
if (autoDetectSelectables)
{
FindSelectablesInScene();
}

if (selectionIndex < selectables.Count - 1)
{
selectionIndex++;
}
else
{
selectionIndex = 0;
}

if (selectables.Count > 0)
{
SwitchSelectableFocus(selectionIndex);
}
}

private void SwitchSelectableFocus(int index)
{
eventSystem.SetSelectedGameObject(selectables[index].gameObject);
}

private int FindActiveSelectionIndex()
{
GameObject highlightedObject = eventSystem.currentSelectedGameObject;
for (int i = 0; i < selectables.Count; i++)
{
if (highlightedObject == selectables[i].gameObject) return i;
}

return -1;
}

private void CleanDestroyedObjects()
{
for (int i = selectables.Count - 1; i >= 0; i--)
{
if (selectables[i] == null || selectables[i].gameObject == null)
selectables.Remove(selectables[i]);
}
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions Tests/Duck.Forms.Tests.asmdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "Duck.Forms.Tests",
"references": [
"GUID:3ccb158d1f7a14482916322a7272767a"
],
"optionalUnityReferences": [
"TestAssemblies"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": []
}
7 changes: 7 additions & 0 deletions Tests/Duck.Forms.Tests.asmdef.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.