diff --git a/Editor/Tests/Validation.meta b/Scripts.meta similarity index 62% rename from Editor/Tests/Validation.meta rename to Scripts.meta index f48e163..ef3c5e5 100644 --- a/Editor/Tests/Validation.meta +++ b/Scripts.meta @@ -1,8 +1,6 @@ fileFormatVersion: 2 -guid: 655a7952097a84160b633e4f15d2e778 +guid: fcb5967cba180474b9fb4cf3756a8740 folderAsset: yes -timeCreated: 1512145153 -licenseType: Free DefaultImporter: externalObjects: {} userData: diff --git a/DateOfBirthUtils.cs b/Scripts/DateOfBirthUtils.cs similarity index 100% rename from DateOfBirthUtils.cs rename to Scripts/DateOfBirthUtils.cs diff --git a/DateOfBirthUtils.cs.meta b/Scripts/DateOfBirthUtils.cs.meta similarity index 100% rename from DateOfBirthUtils.cs.meta rename to Scripts/DateOfBirthUtils.cs.meta diff --git a/Scripts/Duck.Forms.asmdef b/Scripts/Duck.Forms.asmdef new file mode 100644 index 0000000..d276020 --- /dev/null +++ b/Scripts/Duck.Forms.asmdef @@ -0,0 +1,3 @@ +{ + "name": "Duck.Forms" +} diff --git a/Scripts/Duck.Forms.asmdef.meta b/Scripts/Duck.Forms.asmdef.meta new file mode 100644 index 0000000..22d01d0 --- /dev/null +++ b/Scripts/Duck.Forms.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3ccb158d1f7a14482916322a7272767a +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor.meta b/Scripts/Editor.meta similarity index 100% rename from Editor.meta rename to Scripts/Editor.meta diff --git a/Scripts/Editor/Duck.Forms.Editor.asmdef b/Scripts/Editor/Duck.Forms.Editor.asmdef new file mode 100644 index 0000000..77a9e4b --- /dev/null +++ b/Scripts/Editor/Duck.Forms.Editor.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Duck.Forms.Editor", + "references": [ + "GUID:3ccb158d1f7a14482916322a7272767a" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [] +} \ No newline at end of file diff --git a/Scripts/Editor/Duck.Forms.Editor.asmdef.meta b/Scripts/Editor/Duck.Forms.Editor.asmdef.meta new file mode 100644 index 0000000..c9f0562 --- /dev/null +++ b/Scripts/Editor/Duck.Forms.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5b7dfc1dd0029414d9720edbf5a47d14 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/FormInspector.cs b/Scripts/Editor/FormInspector.cs similarity index 100% rename from Editor/FormInspector.cs rename to Scripts/Editor/FormInspector.cs diff --git a/Editor/FormInspector.cs.meta b/Scripts/Editor/FormInspector.cs.meta similarity index 100% rename from Editor/FormInspector.cs.meta rename to Scripts/Editor/FormInspector.cs.meta diff --git a/Scripts/Editor/SelectableFocusSwitcherEditor.cs b/Scripts/Editor/SelectableFocusSwitcherEditor.cs new file mode 100644 index 0000000..d59b1ee --- /dev/null +++ b/Scripts/Editor/SelectableFocusSwitcherEditor.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/FieldConfig.cs b/Scripts/FieldConfig.cs similarity index 100% rename from FieldConfig.cs rename to Scripts/FieldConfig.cs diff --git a/FieldConfig.cs.meta b/Scripts/FieldConfig.cs.meta similarity index 100% rename from FieldConfig.cs.meta rename to Scripts/FieldConfig.cs.meta diff --git a/Fields.meta b/Scripts/Fields.meta similarity index 100% rename from Fields.meta rename to Scripts/Fields.meta diff --git a/Fields/AbstractFormField.cs b/Scripts/Fields/AbstractFormField.cs similarity index 100% rename from Fields/AbstractFormField.cs rename to Scripts/Fields/AbstractFormField.cs diff --git a/Fields/AbstractFormField.cs.meta b/Scripts/Fields/AbstractFormField.cs.meta similarity index 100% rename from Fields/AbstractFormField.cs.meta rename to Scripts/Fields/AbstractFormField.cs.meta diff --git a/Fields/CheckboxField.cs b/Scripts/Fields/CheckboxField.cs similarity index 100% rename from Fields/CheckboxField.cs rename to Scripts/Fields/CheckboxField.cs diff --git a/Fields/CheckboxField.cs.meta b/Scripts/Fields/CheckboxField.cs.meta similarity index 100% rename from Fields/CheckboxField.cs.meta rename to Scripts/Fields/CheckboxField.cs.meta diff --git a/Fields/DateOfBirth.cs b/Scripts/Fields/DateOfBirth.cs similarity index 100% rename from Fields/DateOfBirth.cs rename to Scripts/Fields/DateOfBirth.cs diff --git a/Fields/DateOfBirth.cs.meta b/Scripts/Fields/DateOfBirth.cs.meta similarity index 100% rename from Fields/DateOfBirth.cs.meta rename to Scripts/Fields/DateOfBirth.cs.meta diff --git a/Fields/DateOfBirthDropdownField.cs b/Scripts/Fields/DateOfBirthDropdownField.cs similarity index 100% rename from Fields/DateOfBirthDropdownField.cs rename to Scripts/Fields/DateOfBirthDropdownField.cs diff --git a/Fields/DateOfBirthDropdownField.cs.meta b/Scripts/Fields/DateOfBirthDropdownField.cs.meta similarity index 100% rename from Fields/DateOfBirthDropdownField.cs.meta rename to Scripts/Fields/DateOfBirthDropdownField.cs.meta diff --git a/Fields/DropdownField.cs b/Scripts/Fields/DropdownField.cs similarity index 100% rename from Fields/DropdownField.cs rename to Scripts/Fields/DropdownField.cs diff --git a/Fields/DropdownField.cs.meta b/Scripts/Fields/DropdownField.cs.meta similarity index 100% rename from Fields/DropdownField.cs.meta rename to Scripts/Fields/DropdownField.cs.meta diff --git a/Fields/RadioButton.cs b/Scripts/Fields/RadioButton.cs similarity index 100% rename from Fields/RadioButton.cs rename to Scripts/Fields/RadioButton.cs diff --git a/Fields/RadioButton.cs.meta b/Scripts/Fields/RadioButton.cs.meta similarity index 100% rename from Fields/RadioButton.cs.meta rename to Scripts/Fields/RadioButton.cs.meta diff --git a/Fields/RadioField.cs b/Scripts/Fields/RadioField.cs similarity index 100% rename from Fields/RadioField.cs rename to Scripts/Fields/RadioField.cs diff --git a/Fields/RadioField.cs.meta b/Scripts/Fields/RadioField.cs.meta similarity index 100% rename from Fields/RadioField.cs.meta rename to Scripts/Fields/RadioField.cs.meta diff --git a/Fields/TextField.cs b/Scripts/Fields/TextField.cs similarity index 100% rename from Fields/TextField.cs rename to Scripts/Fields/TextField.cs diff --git a/Fields/TextField.cs.meta b/Scripts/Fields/TextField.cs.meta similarity index 100% rename from Fields/TextField.cs.meta rename to Scripts/Fields/TextField.cs.meta diff --git a/Form.cs b/Scripts/Form.cs similarity index 100% rename from Form.cs rename to Scripts/Form.cs diff --git a/Form.cs.meta b/Scripts/Form.cs.meta similarity index 100% rename from Form.cs.meta rename to Scripts/Form.cs.meta diff --git a/Scripts/SelectableFocusSwitcher.cs b/Scripts/SelectableFocusSwitcher.cs new file mode 100644 index 0000000..2f28cb2 --- /dev/null +++ b/Scripts/SelectableFocusSwitcher.cs @@ -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 selectables; + private EventSystem eventSystem; + + void Awake() + { + if(selectables == null){ + selectables = new List(); + } + eventSystem = FindObjectOfType(); + + if (autoDetectSelectables) + { + FindActiveSelectionIndex(); + } + } + + public void FindSelectablesInScene() + { + Selectable[] sceneSelectables = FindObjectsOfType(); + 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]); + } + } + } + } \ No newline at end of file diff --git a/Validation.meta b/Scripts/Validation.meta similarity index 100% rename from Validation.meta rename to Scripts/Validation.meta diff --git a/Validation/AbstractValidator.cs b/Scripts/Validation/AbstractValidator.cs similarity index 100% rename from Validation/AbstractValidator.cs rename to Scripts/Validation/AbstractValidator.cs diff --git a/Validation/AbstractValidator.cs.meta b/Scripts/Validation/AbstractValidator.cs.meta similarity index 100% rename from Validation/AbstractValidator.cs.meta rename to Scripts/Validation/AbstractValidator.cs.meta diff --git a/Validation/BlackListValidator.cs b/Scripts/Validation/BlackListValidator.cs similarity index 100% rename from Validation/BlackListValidator.cs rename to Scripts/Validation/BlackListValidator.cs diff --git a/Validation/BlackListValidator.cs.meta b/Scripts/Validation/BlackListValidator.cs.meta similarity index 100% rename from Validation/BlackListValidator.cs.meta rename to Scripts/Validation/BlackListValidator.cs.meta diff --git a/Validation/CheckboxIsOnValidator.cs b/Scripts/Validation/CheckboxIsOnValidator.cs similarity index 100% rename from Validation/CheckboxIsOnValidator.cs rename to Scripts/Validation/CheckboxIsOnValidator.cs diff --git a/Validation/CheckboxIsOnValidator.cs.meta b/Scripts/Validation/CheckboxIsOnValidator.cs.meta similarity index 100% rename from Validation/CheckboxIsOnValidator.cs.meta rename to Scripts/Validation/CheckboxIsOnValidator.cs.meta diff --git a/Validation/CheckboxValidator.cs b/Scripts/Validation/CheckboxValidator.cs similarity index 100% rename from Validation/CheckboxValidator.cs rename to Scripts/Validation/CheckboxValidator.cs diff --git a/Validation/CheckboxValidator.cs.meta b/Scripts/Validation/CheckboxValidator.cs.meta similarity index 100% rename from Validation/CheckboxValidator.cs.meta rename to Scripts/Validation/CheckboxValidator.cs.meta diff --git a/Validation/DateOfBirthValidator.cs b/Scripts/Validation/DateOfBirthValidator.cs similarity index 100% rename from Validation/DateOfBirthValidator.cs rename to Scripts/Validation/DateOfBirthValidator.cs diff --git a/Validation/DateOfBirthValidator.cs.meta b/Scripts/Validation/DateOfBirthValidator.cs.meta similarity index 100% rename from Validation/DateOfBirthValidator.cs.meta rename to Scripts/Validation/DateOfBirthValidator.cs.meta diff --git a/Validation/NullOrEmptyValidator.cs b/Scripts/Validation/NullOrEmptyValidator.cs similarity index 100% rename from Validation/NullOrEmptyValidator.cs rename to Scripts/Validation/NullOrEmptyValidator.cs diff --git a/Validation/NullOrEmptyValidator.cs.meta b/Scripts/Validation/NullOrEmptyValidator.cs.meta similarity index 100% rename from Validation/NullOrEmptyValidator.cs.meta rename to Scripts/Validation/NullOrEmptyValidator.cs.meta diff --git a/Validation/RegexValidator.cs b/Scripts/Validation/RegexValidator.cs similarity index 100% rename from Validation/RegexValidator.cs rename to Scripts/Validation/RegexValidator.cs diff --git a/Validation/RegexValidator.cs.meta b/Scripts/Validation/RegexValidator.cs.meta similarity index 100% rename from Validation/RegexValidator.cs.meta rename to Scripts/Validation/RegexValidator.cs.meta diff --git a/Validation/TextLengthValidator.cs b/Scripts/Validation/TextLengthValidator.cs similarity index 100% rename from Validation/TextLengthValidator.cs rename to Scripts/Validation/TextLengthValidator.cs diff --git a/Validation/TextLengthValidator.cs.meta b/Scripts/Validation/TextLengthValidator.cs.meta similarity index 100% rename from Validation/TextLengthValidator.cs.meta rename to Scripts/Validation/TextLengthValidator.cs.meta diff --git a/Validation/TextMatchValidator.cs b/Scripts/Validation/TextMatchValidator.cs similarity index 100% rename from Validation/TextMatchValidator.cs rename to Scripts/Validation/TextMatchValidator.cs diff --git a/Validation/TextMatchValidator.cs.meta b/Scripts/Validation/TextMatchValidator.cs.meta similarity index 100% rename from Validation/TextMatchValidator.cs.meta rename to Scripts/Validation/TextMatchValidator.cs.meta diff --git a/Validation/TextValidator.cs b/Scripts/Validation/TextValidator.cs similarity index 100% rename from Validation/TextValidator.cs rename to Scripts/Validation/TextValidator.cs diff --git a/Validation/TextValidator.cs.meta b/Scripts/Validation/TextValidator.cs.meta similarity index 100% rename from Validation/TextValidator.cs.meta rename to Scripts/Validation/TextValidator.cs.meta diff --git a/Editor/Tests.meta b/Tests.meta similarity index 100% rename from Editor/Tests.meta rename to Tests.meta diff --git a/Tests/Duck.Forms.Tests.asmdef b/Tests/Duck.Forms.Tests.asmdef new file mode 100644 index 0000000..b3c4aa4 --- /dev/null +++ b/Tests/Duck.Forms.Tests.asmdef @@ -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": [] +} \ No newline at end of file diff --git a/Tests/Duck.Forms.Tests.asmdef.meta b/Tests/Duck.Forms.Tests.asmdef.meta new file mode 100644 index 0000000..5d6d04a --- /dev/null +++ b/Tests/Duck.Forms.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 653aed1a39022447881d0e7378adb3e4 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Tests/Validation/FieldValidationTests.cs b/Tests/FieldValidationTests.cs similarity index 100% rename from Editor/Tests/Validation/FieldValidationTests.cs rename to Tests/FieldValidationTests.cs diff --git a/Editor/Tests/Validation/FieldValidationTests.cs.meta b/Tests/FieldValidationTests.cs.meta similarity index 100% rename from Editor/Tests/Validation/FieldValidationTests.cs.meta rename to Tests/FieldValidationTests.cs.meta