diff --git a/.github/workflows/development-buildandtestupmrelease.yml b/.github/workflows/development-buildandtestupmrelease.yml index 7bdae5c..42d05b2 100644 --- a/.github/workflows/development-buildandtestupmrelease.yml +++ b/.github/workflows/development-buildandtestupmrelease.yml @@ -24,7 +24,7 @@ env: jobs: test-unity-build: - name: Test Unity UPM Build + name: Test Unity UPM Build (${{ matrix.os }}, Unity ${{ matrix.unity-version }}) runs-on: ${{ matrix.os }} if: always() strategy: @@ -32,11 +32,13 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] unity-version: - - 6000.0.x - - 6000 + - '6000.0.x' + - '6000.1' + - '6000.2' + - '6000.3' include: - # - os: ubuntu-latest - # build-targets: StandaloneLinux64, Android + - os: ubuntu-latest + build-targets: StandaloneLinux64, Android - os: windows-latest build-targets: StandaloneWindows64, Android - os: macos-latest @@ -49,7 +51,9 @@ jobs: unity-version: ${{ matrix.unity-version }} # overrides version in version-file build-targets: ${{ matrix.build-targets }} - - run: | + - name: Inspect Unity setup outputs + shell: pwsh + run: | echo "Step Outputs:" echo "steps.unity-setup.unity-hub-path: '${{ steps.unity-setup.outputs.unity-hub-path }}'" echo "steps.unity-setup.unity-editors: '${{ steps.unity-setup.outputs.unity-editors }}'" @@ -57,10 +61,10 @@ jobs: echo "steps.unity-setup.unity-project-path: '${{ steps.unity-setup.outputs.unity-project-path }}'" echo "Environment Variables:" - echo "UNITY_HUB_PATH: '${{ env.UNITY_HUB_PATH }}'" - echo "UNITY_EDITORS: '${{ env.UNITY_EDITORS }}'" - echo "UNITY_EDITOR_PATH: '${{ env.UNITY_EDITOR_PATH }}'" - echo "UNITY_PROJECT_PATH: '${{ env.UNITY_PROJECT_PATH }}'" + echo "UNITY_HUB_PATH: '$env:UNITY_HUB_PATH'" + echo "UNITY_EDITORS: '$env:UNITY_EDITORS'" + echo "UNITY_EDITOR_PATH: '$env:UNITY_EDITOR_PATH'" + echo "UNITY_PROJECT_PATH: '$env:UNITY_PROJECT_PATH'" - uses: buildalon/activate-unity-license@v2 if: runner.environment == 'github-hosted' diff --git a/Editor/CustomRectTransformEditor.cs b/Editor/CustomRectTransformEditor.cs new file mode 100644 index 0000000..4c08974 --- /dev/null +++ b/Editor/CustomRectTransformEditor.cs @@ -0,0 +1,310 @@ +///Credit Dmitry (mitay-walle) +///Sourced from - https://github.com/mitay-walle/com.mitay-walle.rect-transform-editor + +using System; +using System.Reflection; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Plugins.UI.Editor +{ + [CustomEditor(typeof(RectTransform), true), CanEditMultipleObjects] + public class CustomRectTransformEditor : UnityEditor.Editor + { + private const string NATIVE_EDITOR_TYPE = "UnityEditor.RectTransformEditor"; + private static PropertyInfo _rectDrivenObject = typeof(RectTransform).GetProperty("drivenByObject" + , BindingFlags.Public | BindingFlags.Instance); + private UnityEditor.Editor editorInstance; + private static Type nativeEditorType; + private MethodInfo onSceneGui; + private MethodInfo onDisable; + private Action drawAnchorsOnSceneViewDelegate; + + private Rect _rect = new Rect(45, 65, 45, 18); + private Rect _rect2 = new Rect(70, 25, 20, 18); + private Rect _rect3 = new Rect(70, 45, 20, 18); + private Rect _rect4 = new Rect(0, 65, 45, 18); + + private void OnEnable() + { + if (targets.Length == 0 || targets[0] == null) return; + + Initialize(); + if (nativeEditorType == null) return; + if (editorInstance == null) return; + + InitOnSceneGUIFix(); + ExecuteOnSceneGUIFix(); + try + { + if (editorInstance.targets.Length > 0 && editorInstance.targets[0] != null) + { + nativeEditorType.GetMethod("OnEnable", + BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic) + ?.Invoke(editorInstance, null); + } + } + catch + { + } + } + + private void Initialize() + { + if (nativeEditorType == null) + { + nativeEditorType = Assembly.GetAssembly(typeof(UnityEditor.Editor)).GetType(NATIVE_EDITOR_TYPE); + } + + if (editorInstance) + { + CreateCachedEditor(targets, nativeEditorType, ref editorInstance); + } + else + { + editorInstance = CreateEditor(targets, nativeEditorType); + } + } + + private void InitOnSceneGUIFix() + { + // fix recursive SceneView.duringSceneGui subscription, that affects performance + onSceneGui = nativeEditorType.GetMethod("OnSceneGUI", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + onDisable = nativeEditorType.GetMethod("OnDisable", BindingFlags.NonPublic | BindingFlags.Instance); + var method = nativeEditorType.GetMethod("DrawAnchorsOnSceneView", BindingFlags.NonPublic | BindingFlags.Instance); + drawAnchorsOnSceneViewDelegate = (Action)method.CreateDelegate(typeof(Action), editorInstance); + } + + private void ExecuteOnSceneGUIFix() + { + SceneView.duringSceneGui -= drawAnchorsOnSceneViewDelegate; + } + + public override void OnInspectorGUI() + { + editorInstance.OnInspectorGUI(); + + bool needMoveY = NeedMoveY(); + + Rect rect = _rect; + rect.y += needMoveY ? 20 : 0; + + // Code here + if (GUI.Button(rect, "Snap")) + { + foreach (Object targ in targets) + { + if (targ is RectTransform rectTr) + { + Undo.RecordObject(targ, "Snap to parent"); + SnapToParent(rectTr); + EditorUtility.SetDirty(targ); + } + } + } + + rect = _rect4; + rect.y += needMoveY ? 20 : 0; + + if (GUI.Button(rect, "New")) + { + foreach (Object targ in targets) + { + if (targ is RectTransform rectTr) + { + CreateEmptyParentRect(rectTr); + } + } + } + + if (targets.Length > 1) + { + GUI.enabled = false; + } + + rect = _rect2; + rect.y += needMoveY ? 20 : 0; + + if (GUI.Button(rect, "C")) + { + ComponentUtility.CopyComponent(target as RectTransform); + } + + GUI.enabled = true; + + rect = _rect3; + rect.y += needMoveY ? 20 : 0; + + if (GUI.Button(rect, "P")) + { + foreach (Object targ in targets) + { + Undo.RecordObject(targ, "Paste"); + ComponentUtility.PasteComponentValues(targ as RectTransform); + EditorUtility.SetDirty(targ); + } + } + } + + private void OnSceneGUI() + { + if (!(bool)target) + return; + + onSceneGui.Invoke(editorInstance, null); + } + + private void OnDisable() + { + SceneView.duringSceneGui -= drawAnchorsOnSceneViewDelegate; + if (editorInstance) + { + onDisable?.Invoke(editorInstance, null); + DestroyImmediate(editorInstance); + } + } + + private static void SnapToParent(RectTransform rect) + { + rect.pivot = new Vector2(.5f, .5f); + rect.localScale = Vector3.one; + rect.localPosition = Vector3.zero; + rect.localRotation = Quaternion.identity; + rect.anchoredPosition = Vector2.zero; + rect.anchorMin = Vector2.zero; + rect.anchorMax = Vector2.one; + rect.sizeDelta = Vector2.zero; + } + + public static void CreateEmptyParentRect(RectTransform rect) + { + GameObject go = new GameObject("Create Empty Parent"); + + ComponentUtility.CopyComponent(rect); + ComponentUtility.PasteComponentAsNew(go); + + Undo.RecordObject(rect, "Create Empty, Reparent"); + + Undo.RegisterCreatedObjectUndo(go, "Create Empty Parent"); + + RectTransform rect2 = go.transform as RectTransform; + + PlaceSameAs(go.transform, rect, true, true, true); + ComponentUtility.PasteComponentValues(rect2); + Undo.SetTransformParent(rect, go.transform, "Create Empty, Reparent"); + SnapToParent(rect); + + EditorUtility.SetDirty(rect); + + Selection.activeGameObject = go; + EditorGUIUtility.PingObject(go); + } + + private static void PlaceSameAs(Transform target, Transform source, bool copyName = false, bool undo = false, + bool setDirty = false) + { + if (!source) return; + + if (undo && Application.isPlaying) + { + Undo.RecordObject(target, "PlaceSameAs"); + if (copyName) Undo.RecordObject(target.gameObject, "PlaceSameAs"); + } + + VectorArray matrix = new VectorArray(source, false); + matrix.Apply(target); + if (undo) + { + Undo.SetTransformParent(target, source.parent, "PlaceSameAs"); + } + else + { + target.SetParent(source.parent); + } + + target.SetSiblingIndex(source.GetSiblingIndex()); + + if (copyName) target.name = source.name; + + if (setDirty && Application.isPlaying) + { + EditorUtility.SetDirty(target); + if (copyName) EditorUtility.SetDirty(target.gameObject); + } + } + + // ReSharper disable Unity.PerformanceAnalysis + private bool NeedMoveY() + { + bool value = false; + foreach (RectTransform target in targets) + { + if (NeedMoveY(target)) + { + value = true; + break; + } + } + + return value; + } + + private bool NeedMoveY(RectTransform target) => _rectDrivenObject.GetValue(target) != null; + } + + [Serializable] + public struct VectorArray + { + [SerializeField] public bool local; + [SerializeField] public Vector3 Pos; + [SerializeField] public Quaternion Rot; + [SerializeField] public Vector3 Scale; + + public VectorArray(Transform tr, bool local) + { + this.local = local; + if (!tr) + { + Pos = default; + Rot = default; + Scale = default; + } + else + { + Scale = local ? tr.localScale : tr.lossyScale; + + if (local) + { + Pos = tr.localPosition; + Rot = tr.localRotation; + } + else + { + Pos = tr.position; + Rot = tr.rotation; + } + } + } + + public void Apply(Transform tr) + { + if (local) + { + tr.localPosition = Pos; + tr.localRotation = Rot; + } + else + { + tr.position = Pos; + tr.rotation = Rot; + } + + tr.localScale = Scale; +#if UNITY_EDITOR + if (!Application.isPlaying) EditorUtility.SetDirty(tr); +#endif + } + } +} diff --git a/Editor/CustomRectTransformEditor.cs.meta b/Editor/CustomRectTransformEditor.cs.meta new file mode 100644 index 0000000..43607d6 --- /dev/null +++ b/Editor/CustomRectTransformEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3692129da900a5648a912045e21f7531 \ No newline at end of file diff --git a/Editor/GridRawImage.meta b/Editor/GridRawImage.meta new file mode 100644 index 0000000..14a45e5 --- /dev/null +++ b/Editor/GridRawImage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a28f78e67e4a86346b60c99c3419bddf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/GridRawImage/GridRawImageEditor.cs b/Editor/GridRawImage/GridRawImageEditor.cs new file mode 100644 index 0000000..1e2148d --- /dev/null +++ b/Editor/GridRawImage/GridRawImageEditor.cs @@ -0,0 +1,46 @@ +///Credit Dmitry (mitay-walle) +///Sourced from - https://github.com/mitay-walle/com.mitay-walle.grid-raw-image + +using System.Linq; +using UnityEditor; + +namespace UnityEngine.UI.Extensions +{ + [CustomEditor(typeof(GridRawImage))] + public class GridRawImageEditor : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + serializedObject.UpdateIfRequiredOrScript(); + EditorGUI.BeginChangeCheck(); + DrawPropertiesExcludingCustom(serializedObject, "m_OnCullStateChanged", "m_RaycastPadding"); + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + } + } + + private static void DrawPropertiesExcludingCustom(SerializedObject obj, params string[] propertyToExclude) + { + SerializedProperty iterator = obj.GetIterator(); + bool enterChildren = true; + while (iterator.NextVisible(enterChildren)) + { + enterChildren = false; + if (!propertyToExclude.Contains(iterator.name)) + { + if (iterator.name == "m_Script") + { + GUI.enabled = false; + } + EditorGUILayout.PropertyField(iterator, true); + + if (iterator.name == "m_Script") + { + GUI.enabled = true; + } + } + } + } + } +} \ No newline at end of file diff --git a/Editor/GridRawImage/GridRawImageEditor.cs.meta b/Editor/GridRawImage/GridRawImageEditor.cs.meta new file mode 100644 index 0000000..b224d16 --- /dev/null +++ b/Editor/GridRawImage/GridRawImageEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: eb6c9d572fcbc4344b99dfa12a050bc4 \ No newline at end of file diff --git a/Editor/GridRawImage/GridShapeDrawer.cs b/Editor/GridRawImage/GridShapeDrawer.cs new file mode 100644 index 0000000..e2cc656 --- /dev/null +++ b/Editor/GridRawImage/GridShapeDrawer.cs @@ -0,0 +1,59 @@ +///Credit Dmitry (mitay-walle) +///Sourced from - https://github.com/mitay-walle/com.mitay-walle.grid-raw-image + +using UnityEditor; + +namespace UnityEngine.UI.Extensions +{ + [CustomPropertyDrawer(typeof(GridShape))] + public class GridShapeDrawer : PropertyDrawer + { + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) => 0; + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUILayout.PropertyField(property); + + //property.isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(property.isExpanded, label); + if (property.isExpanded) + { + EditorGUI.indentLevel += 2; + SerializedProperty size = property.FindPropertyRelative("_size"); + SerializedProperty prop = property.FindPropertyRelative("_bitArray"); + // EditorGUILayout.PropertyField(property.FindPropertyRelative("_readable")); + // EditorGUILayout.PropertyField(size); + + EditorGUI.BeginChangeCheck(); + + BitArray256 bitArray = (BitArray256)prop.boxedValue; + float last = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 0; + for (int j = size.vector2IntValue.y - 1; j >= 0; j--) + { + GUILayout.BeginHorizontal(); + + for (int i = 0; i < size.vector2IntValue.x; i++) + { + int index = j * size.vector2IntValue.x + i; + bool value = bitArray[(uint)index]; + bitArray[(uint)index] = EditorGUILayout.Toggle(GUIContent.none, value, GUILayout.Width(20)); + } + GUILayout.EndHorizontal(); + } + + EditorGUIUtility.labelWidth = last; + if (EditorGUI.EndChangeCheck()) + { + foreach (Object targetObject in property.serializedObject.targetObjects) + { + Undo.RecordObject(targetObject, "GridShape flags"); + prop.boxedValue = bitArray; + } + } + EditorGUI.indentLevel -= 2; + } + + EditorGUILayout.EndFoldoutHeaderGroup(); + } + } +} diff --git a/Editor/GridRawImage/GridShapeDrawer.cs.meta b/Editor/GridRawImage/GridShapeDrawer.cs.meta new file mode 100644 index 0000000..a47d5ae --- /dev/null +++ b/Editor/GridRawImage/GridShapeDrawer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f6707ceb1aef81748beddf67fa73c2b6 \ No newline at end of file diff --git a/Editor/UIExtensionsMenuOptions.cs b/Editor/UIExtensionsMenuOptions.cs index def2a80..52c8b6c 100644 --- a/Editor/UIExtensionsMenuOptions.cs +++ b/Editor/UIExtensionsMenuOptions.cs @@ -3,16 +3,14 @@ #endif using TMPro; -using UnityEngine; +using UnityEditor; using UnityEngine.EventSystems; -using UnityEngine.UI; -using UnityEngine.UI.Extensions; #if NEW_INPUT_SYSTEM using UnityEngine.InputSystem.UI; #endif -namespace UnityEditor.UI +namespace UnityEngine.UI.Extensions { /// /// This script adds the Extensions UI menu options to the Unity Editor. @@ -879,10 +877,10 @@ static public void AddAutoCompleteComboBox(MenuCommand menuCommand) GameObject autoCompleteComboBoxRoot = CreateUIElementRoot("AutoCompleteComboBox", menuCommand, s_ThickGUIElementSize); //Create Template - GameObject itemTemplate = AddButtonAsChild(autoCompleteComboBoxRoot); + GameObject itemTemplate = AddComboBoxButtonAsChild(autoCompleteComboBoxRoot); //Create Inputfield - GameObject inputField = AddInputFieldAsChild(autoCompleteComboBoxRoot); + GameObject inputField = AddComboBoxInputFieldAsChild(autoCompleteComboBoxRoot); //Create Overlay GameObject overlay = CreateUIObject("Overlay", autoCompleteComboBoxRoot); @@ -891,7 +889,7 @@ static public void AddAutoCompleteComboBox(MenuCommand menuCommand) GameObject overlayScrollPanelScrollBar = AddScrollbarAsChild(overlayScrollPanel); //Create Arrow Button - GameObject arrowButton = AddButtonAsChild(autoCompleteComboBoxRoot); + GameObject arrowButton = AddComboBoxButtonAsChild(autoCompleteComboBoxRoot); //Setup ComboBox var autoCompleteComboBox = autoCompleteComboBoxRoot.AddComponent(); @@ -913,7 +911,7 @@ static public void AddAutoCompleteComboBox(MenuCommand menuCommand) inputFieldRT.anchorMin = Vector2.zero; inputFieldRT.anchorMax = Vector2.one; inputFieldRT.sizeDelta = Vector2.zero; - Events.UnityEventTools.AddPersistentListener(inputField.GetComponent().onValueChanged, new UnityEngine.Events.UnityAction(autoCompleteComboBox.OnValueChanged)); + WireComboBoxInput(inputField, autoCompleteComboBox.OnValueChanged); //Setup Overlay var overlayRT = overlay.GetComponent(); @@ -922,7 +920,7 @@ static public void AddAutoCompleteComboBox(MenuCommand menuCommand) overlayRT.sizeDelta = new Vector2(0f, 1f); overlayRT.pivot = new Vector2(0f, 1f); overlay.AddComponent().color = new Color(0.243f, 0.871f, 0f, 0f); - Events.UnityEventTools.AddBoolPersistentListener(overlay.AddComponent