Skip to content

Commit

Permalink
Merge branch 'develop/unity2022' into develop/remove-internal-access
Browse files Browse the repository at this point in the history
  • Loading branch information
fuqunaga committed Nov 29, 2024
2 parents b63ce8b + 00f5bb8 commit 8a7c762
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.UIElements;

Expand All @@ -16,25 +18,37 @@ public static object Generate(IEnumerable<MenuItem> menuItems, Rect position, Vi
#else
// refs: BasePopupField
// https://github.com/Unity-Technologies/UnityCsReference/blob/c84064be69f20dcf21ebe4a7bbc176d48e2f289c/ModuleOverrides/com.unity.ui/Core/Controls/BasePopupField.cs#L206
var isPlayer = targetElement?.elementPanel.contextType == ContextType.Player;

IGenericMenu menu;
var isPlayer = targetElement?.panel.contextType == ContextType.Player;
GenericDropdownMenuWrapper menu;
if (isPlayer)
{
// Unity2022.3でスクロールバーが表示されてしまう(バグ?)のであらかじめ広めの幅を確保しておく
var genericMenu = new GenericDropdownMenu();
genericMenu.contentContainer.style.width = 200;

menu = genericMenu;
menu = new GenericDropdownMenuWrapper(genericMenu);
}

// GenericDropdownMenu だとエディターでエラーになる場合があるのでDropdownUtility経由でOSのメニューを使用する
// RosettaUIEditorWindowExample > MiscExample > UI.Popup() でエラーになる
// Unity2022.3
// at Unity2022.3
else
{
// DropdownUtility.CreateDropdown() は internal なのでリフレクションで取得
#if false
menu = DropdownUtility.CreateDropdown();
#else
_createDropdownFunc ??= (Func<object>)typeof(VisualElement).Assembly
.GetType("UnityEngine.UIElements.DropdownUtility")?
.GetMethod("CreateDropdown", BindingFlags.NonPublic | BindingFlags.Static)?
.CreateDelegate(typeof(Func<object>));

if (_createDropdownFunc == null)
{
return null;
}

menu = new GenericDropdownMenuWrapper(_createDropdownFunc());
#endif
}

#endif

foreach (var item in menuItems)
Expand All @@ -58,5 +72,70 @@ public static object Generate(IEnumerable<MenuItem> menuItems, Rect position, Vi
menu.DropDown(position, targetElement, anchored);
return menu;
}

#if !UNITY_2023_1_OR_NEWER
private static Func<object> _createDropdownFunc;

/// <summary>
/// UnityEngine.UIElements.IGenericMenu が internal なので代替インターフェース
/// </summary>
private class GenericDropdownMenuWrapper
{
private class MethodInfoSet
{
private static readonly Type[] AddItemTypes = {typeof(string), typeof(bool), typeof(Action)};
private static readonly Type[] AddDisabledItemTypes = {typeof(string), typeof(bool)};
private static readonly Type[] AddSeparatorTypes = {typeof(string)};
private static readonly Type[] DropDownTypes = {typeof(Rect), typeof(VisualElement), typeof(bool)};

public readonly MethodInfo addItem;
public readonly MethodInfo addDisabledItem;
public readonly MethodInfo addSeparator;
public readonly MethodInfo dropDown;

public MethodInfoSet(Type type)
{
addItem = type.GetMethod("AddItem", AddItemTypes);
addDisabledItem = type.GetMethod("AddDisabledItem", AddDisabledItemTypes);
addSeparator = type.GetMethod("AddSeparator", AddSeparatorTypes);
dropDown = type.GetMethod("DropDown", DropDownTypes);
}
}


private static readonly Dictionary<Type, MethodInfoSet> TypeToMethodInfoSet = new();

private static MethodInfoSet GetMethodInfoSet(Type type)
{
if (!TypeToMethodInfoSet.TryGetValue(type, out var methodInfoSet))
{
methodInfoSet = new MethodInfoSet(type);
TypeToMethodInfoSet[type] = methodInfoSet;
}

return methodInfoSet;
}


private readonly Action<string, bool, Action> _addItemAction;
private readonly Action<string, bool> _addDisabledItemAction;
private readonly Action<string> _addSeparatorAction;
private readonly Action<Rect, VisualElement, bool> _dropDownAction;

public GenericDropdownMenuWrapper(object baseObject)
{
var methodInfoSet = GetMethodInfoSet(baseObject.GetType());
_addItemAction = (Action<string, bool, Action>)Delegate.CreateDelegate(typeof(Action<string, bool, Action>), baseObject, methodInfoSet.addItem);
_addDisabledItemAction = (Action<string, bool>)Delegate.CreateDelegate(typeof(Action<string, bool>), baseObject, methodInfoSet.addDisabledItem);
_addSeparatorAction = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), baseObject, methodInfoSet.addSeparator);
_dropDownAction = (Action<Rect, VisualElement, bool>)Delegate.CreateDelegate(typeof(Action<Rect, VisualElement, bool>), baseObject, methodInfoSet.dropDown);
}

public void AddItem(string name, bool isChecked, Action action) => _addItemAction(name, isChecked, action);
public void AddDisabledItem(string name, bool isChecked) => _addDisabledItemAction(name, isChecked);
public void AddSeparator(string path) => _addSeparatorAction(path);
public void DropDown(Rect position, VisualElement targetElement, bool anchored) => _dropDownAction(position, targetElement, anchored);
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public static class UIToolkitUtility
private static MethodInfo _focusControllerGetLeafFocusedElementMethodInfo;
#if UNITY_2023_1_OR_NEWER
private static PropertyInfo _baseBoolFieldAcceptClicksIfDisabledPropertyInfo;
#else
private static FieldInfo _baseBoolFieldClickableFieldInfo;
private static PropertyInfo _clickableAcceptClicksIfDisabledPropertyInfo;
#endif

public static bool WillUseKeyInput(IPanel panel)
Expand All @@ -30,7 +33,11 @@ public static void SetAcceptClicksIfDisabled(BaseBoolField baseBoolField, bool f
_baseBoolFieldAcceptClicksIfDisabledPropertyInfo ??= typeof(BaseBoolField).GetProperty("acceptClicksIfDisabled", BindingFlags.NonPublic | BindingFlags.Instance);
_baseBoolFieldAcceptClicksIfDisabledPropertyInfo?.SetValue(baseBoolField, flag);
#else
baseBoolField.m_Clickable.acceptClicksIfDisabled = flag;
_baseBoolFieldClickableFieldInfo ??= typeof(BaseBoolField).GetField("m_Clickable", BindingFlags.NonPublic | BindingFlags.Instance);
_clickableAcceptClicksIfDisabledPropertyInfo ??= typeof(Clickable).GetProperty("acceptClicksIfDisabled", BindingFlags.NonPublic | BindingFlags.Instance);

var baseBoolFieldClickable = _baseBoolFieldClickableFieldInfo?.GetValue(baseBoolField);
_clickableAcceptClicksIfDisabledPropertyInfo?.SetValue(baseBoolFieldClickable, flag);
#endif
}
}
Expand Down

0 comments on commit 8a7c762

Please sign in to comment.