-
Notifications
You must be signed in to change notification settings - Fork 1
Assembly definitions added #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
4497f85
5edf6d7
b7cc053
8ed980e
e63b73a
825ce26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "name": "Duck.Forms" | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| 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": [] | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| 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); | ||
| } | ||
| } | ||
| } |
| 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]); | ||
| } | ||
| } | ||
| } | ||
| } |
| 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": [] | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Tests folders in a package are usually then split into
EditorandRuntimefolders / assemblies (see here).I know we only have editor tests right now, but it would be good to stick to the expected layout just in case we add any runtime tests later on.