Rename Module

This commit is contained in:
raiti-chan 2022-12-08 21:55:40 +09:00
parent 69d18b854a
commit b3fe5c777e
10 changed files with 95 additions and 88 deletions

View File

@ -39,11 +39,15 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
public delegate void AvatarProcessorCallback(GameObject obj); public delegate void AvatarProcessorCallback(GameObject obj);
public static event AvatarProcessorCallback BeforeProcessing;
/// <summary> /// <summary>
/// This API is NOT stable. Do not use it yet. /// This API is NOT stable. Do not use it yet.
/// </summary> /// </summary>
public static event AvatarProcessorCallback AfterProcessing; public static event AvatarProcessorCallback AfterProcessing;
public static event AvatarProcessorCallback CleanedUpProcessing;
static AvatarProcessor() static AvatarProcessor()
{ {
EditorApplication.playModeStateChanged += OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
@ -136,9 +140,10 @@ namespace nadena.dev.modular_avatar.core.editor
Object.DestroyImmediate(component); Object.DestroyImmediate(component);
} }
} }
BeforeProcessing?.Invoke(avatarGameObject);
new RenameParametersHook().OnPreprocessAvatar(avatarGameObject); new RenameParametersHook().OnPreprocessAvatar(avatarGameObject);
new MenuFolderCreateHook().OnPreprocessAvatar(avatarGameObject); new SubMenuCreateHook().OnPreprocessAvatar(avatarGameObject);
new MenuInstallHook().OnPreprocessAvatar(avatarGameObject); new MenuInstallHook().OnPreprocessAvatar(avatarGameObject);
new MergeArmatureHook().OnPreprocessAvatar(avatarGameObject); new MergeArmatureHook().OnPreprocessAvatar(avatarGameObject);
new RetargetMeshes().OnPreprocessAvatar(avatarGameObject); new RetargetMeshes().OnPreprocessAvatar(avatarGameObject);
@ -158,6 +163,7 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
UnityEngine.Object.DestroyImmediate(component); UnityEngine.Object.DestroyImmediate(component);
} }
CleanedUpProcessing?.Invoke(avatarGameObject);
} }
FixupAnimatorDebugData(avatarGameObject); FixupAnimatorDebugData(avatarGameObject);

View File

@ -14,11 +14,11 @@ namespace nadena.dev.modular_avatar.core.editor {
set => this._treeView.Avatar = value; set => this._treeView.Avatar = value;
} }
private ModularAvatarMenuFolderCreator Creator { private ModularAvatarSubMenuCreator Creator {
set => this._treeView.Creator = value; set => this._treeView.Creator = value;
} }
private Action<ModularAvatarMenuFolderCreator> OnMenuSelected = (creator) => { }; private Action<ModularAvatarSubMenuCreator> OnMenuSelected = (creator) => { };
private void Awake() { private void Awake() {
this._treeView = new AvMenuFolderCreatorTreeView(new TreeViewState()) { this._treeView = new AvMenuFolderCreatorTreeView(new TreeViewState()) {
@ -44,7 +44,7 @@ namespace nadena.dev.modular_avatar.core.editor {
this._treeView.OnGUI(new Rect(0, 0, this.position.width, this.position.height)); this._treeView.OnGUI(new Rect(0, 0, this.position.width, this.position.height));
} }
internal static void Show(VRCAvatarDescriptor avatar, ModularAvatarMenuFolderCreator creator, Action<ModularAvatarMenuFolderCreator> OnSelect) { internal static void Show(VRCAvatarDescriptor avatar, ModularAvatarSubMenuCreator creator, Action<ModularAvatarSubMenuCreator> OnSelect) {
AvMenuFolderCreatorTreeViewWindow window = GetWindow<AvMenuFolderCreatorTreeViewWindow>(); AvMenuFolderCreatorTreeViewWindow window = GetWindow<AvMenuFolderCreatorTreeViewWindow>();
window.titleContent = new GUIContent("Select menu folder creator"); window.titleContent = new GUIContent("Select menu folder creator");
@ -66,8 +66,8 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
} }
private ModularAvatarMenuFolderCreator _creator; private ModularAvatarSubMenuCreator _creator;
public ModularAvatarMenuFolderCreator Creator { public ModularAvatarSubMenuCreator Creator {
get => this._creator; get => this._creator;
set { set {
this._creator = value; this._creator = value;
@ -78,14 +78,14 @@ namespace nadena.dev.modular_avatar.core.editor {
private int _currentCreatorIndex; private int _currentCreatorIndex;
private readonly Texture2D _currentBackgroundTexture; private readonly Texture2D _currentBackgroundTexture;
internal Action<ModularAvatarMenuFolderCreator> OnSelect = (creator) => { }; internal Action<ModularAvatarSubMenuCreator> OnSelect = (creator) => { };
internal Action onDoubleClickSelect = () => { }; internal Action onDoubleClickSelect = () => { };
private readonly List<ModularAvatarMenuFolderCreator> _creatorItems = new List<ModularAvatarMenuFolderCreator>(); private readonly List<ModularAvatarSubMenuCreator> _creatorItems = new List<ModularAvatarSubMenuCreator>();
private readonly HashSet<ModularAvatarMenuFolderCreator> _visitedCreators = new HashSet<ModularAvatarMenuFolderCreator>(); private readonly HashSet<ModularAvatarSubMenuCreator> _visitedCreators = new HashSet<ModularAvatarSubMenuCreator>();
private Dictionary<ModularAvatarMenuFolderCreator, List<ModularAvatarMenuFolderCreator>> _childMap; private Dictionary<ModularAvatarSubMenuCreator, List<ModularAvatarSubMenuCreator>> _childMap;
private List<ModularAvatarMenuFolderCreator> _rootCreators; private List<ModularAvatarSubMenuCreator> _rootCreators;
public AvMenuFolderCreatorTreeView(TreeViewState state) : base(state) { public AvMenuFolderCreatorTreeView(TreeViewState state) : base(state) {
this._currentBackgroundTexture = new Texture2D(1, 1); this._currentBackgroundTexture = new Texture2D(1, 1);
@ -120,7 +120,7 @@ namespace nadena.dev.modular_avatar.core.editor {
}); });
this._creatorItems.Add(null); this._creatorItems.Add(null);
foreach (ModularAvatarMenuFolderCreator rootCreator in this._rootCreators) { foreach (ModularAvatarSubMenuCreator rootCreator in this._rootCreators) {
bool isCurrent = rootCreator == this.Creator; bool isCurrent = rootCreator == this.Creator;
if (isCurrent) { if (isCurrent) {
this._currentCreatorIndex = treeItems.Count; this._currentCreatorIndex = treeItems.Count;
@ -140,9 +140,9 @@ namespace nadena.dev.modular_avatar.core.editor {
return root; return root;
} }
private void TraverseCreator(int depth, List<TreeViewItem> items, ModularAvatarMenuFolderCreator creator) { private void TraverseCreator(int depth, List<TreeViewItem> items, ModularAvatarSubMenuCreator creator) {
if (!this._childMap.TryGetValue(creator, out List<ModularAvatarMenuFolderCreator> children)) return; if (!this._childMap.TryGetValue(creator, out List<ModularAvatarSubMenuCreator> children)) return;
foreach (ModularAvatarMenuFolderCreator child in children.Where(child => !this._visitedCreators.Contains(child))) { foreach (ModularAvatarSubMenuCreator child in children.Where(child => !this._visitedCreators.Contains(child))) {
bool isCurrent = child == this.Creator; bool isCurrent = child == this.Creator;
if (isCurrent) { if (isCurrent) {
this._currentCreatorIndex = items.Count; this._currentCreatorIndex = items.Count;
@ -172,20 +172,20 @@ namespace nadena.dev.modular_avatar.core.editor {
private void MappingFolderCreator() { private void MappingFolderCreator() {
this._childMap = new Dictionary<ModularAvatarMenuFolderCreator, List<ModularAvatarMenuFolderCreator>>(); this._childMap = new Dictionary<ModularAvatarSubMenuCreator, List<ModularAvatarSubMenuCreator>>();
this._rootCreators = new List<ModularAvatarMenuFolderCreator>(); this._rootCreators = new List<ModularAvatarSubMenuCreator>();
foreach (ModularAvatarMenuFolderCreator creator in this.Avatar.gameObject.GetComponentsInChildren<ModularAvatarMenuFolderCreator>()) { foreach (ModularAvatarSubMenuCreator creator in this.Avatar.gameObject.GetComponentsInChildren<ModularAvatarSubMenuCreator>()) {
if (!creator.enabled) continue; if (!creator.enabled) continue;
if (creator.installTargetType == ModularAvatarMenuFolderCreator.InstallTargetType.VRCExpressionMenu) { if (creator.installTargetType == ModularAvatarSubMenuCreator.InstallTargetType.VRCExpressionMenu) {
this._rootCreators.Add(creator); this._rootCreators.Add(creator);
} else { } else {
if (creator.installTargetFolderCreator == null) { if (creator.installTargetCreator == null) {
this._rootCreators.Add(creator); this._rootCreators.Add(creator);
} else { } else {
if (!this._childMap.TryGetValue(creator.installTargetFolderCreator, out List<ModularAvatarMenuFolderCreator> children)) { if (!this._childMap.TryGetValue(creator.installTargetCreator, out List<ModularAvatarSubMenuCreator> children)) {
children = new List<ModularAvatarMenuFolderCreator>(); children = new List<ModularAvatarSubMenuCreator>();
this._childMap[creator.installTargetFolderCreator] = children; this._childMap[creator.installTargetCreator] = children;
} }
children.Add(creator); children.Add(creator);

View File

@ -7,7 +7,7 @@ using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
using static nadena.dev.modular_avatar.core.editor.Localization; using static nadena.dev.modular_avatar.core.editor.Localization;
using static nadena.dev.modular_avatar.core.editor.Util; using static nadena.dev.modular_avatar.core.editor.Util;
using static nadena.dev.modular_avatar.core.ModularAvatarMenuFolderCreator; using static nadena.dev.modular_avatar.core.ModularAvatarSubMenuCreator;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
@ -24,7 +24,7 @@ namespace nadena.dev.modular_avatar.core.editor
private bool _devFoldout; private bool _devFoldout;
private HashSet<VRCExpressionsMenu> _avatarMenus; private HashSet<VRCExpressionsMenu> _avatarMenus;
private HashSet<ModularAvatarMenuFolderCreator> _menuFolderCreators; private HashSet<ModularAvatarSubMenuCreator> _menuFolderCreators;
private void OnEnable() private void OnEnable()
{ {
@ -68,12 +68,12 @@ namespace nadena.dev.modular_avatar.core.editor
Type installTargetObjectType; Type installTargetObjectType;
if (installTargetType == InstallTargetType.VRCExpressionMenu) if (installTargetType == InstallTargetType.VRCExpressionMenu)
{ {
installTargetMenuPropertyName = nameof(ModularAvatarMenuFolderCreator.installTargetMenu); installTargetMenuPropertyName = nameof(ModularAvatarSubMenuCreator.installTargetMenu);
installTargetObjectType = typeof(VRCExpressionsMenu); installTargetObjectType = typeof(VRCExpressionsMenu);
} else } else
{ {
installTargetMenuPropertyName = nameof(ModularAvatarMenuFolderCreator.installTargetFolderCreator); installTargetMenuPropertyName = nameof(ModularAvatarSubMenuCreator.installTargetCreator);
installTargetObjectType = typeof(ModularAvatarMenuFolderCreator); installTargetObjectType = typeof(ModularAvatarSubMenuCreator);
commonAvatar = null; commonAvatar = null;
} }
@ -169,7 +169,7 @@ namespace nadena.dev.modular_avatar.core.editor
} }
break; break;
case InstallTargetType.FolderCreator: case InstallTargetType.FolderCreator:
if (!this.IsMenuReachable(avatar, (ModularAvatarMenuFolderCreator)installTargetProperty.objectReferenceValue, new HashSet<ModularAvatarMenuFolderCreator>())) if (!this.IsMenuReachable(avatar, (ModularAvatarSubMenuCreator)installTargetProperty.objectReferenceValue, new HashSet<ModularAvatarSubMenuCreator>()))
{ {
EditorGUILayout.HelpBox("選択されたメニューフォルダからアバターまでのパスが見つかりません。", MessageType.Error); EditorGUILayout.HelpBox("選択されたメニューフォルダからアバターまでのパスが見つかりません。", MessageType.Error);
} }
@ -190,7 +190,7 @@ namespace nadena.dev.modular_avatar.core.editor
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
Object newValue = EditorGUILayout.ObjectField(G("menuinstall.installto"), displayValue, propertyType, Object newValue = EditorGUILayout.ObjectField(G("menuinstall.installto"), displayValue, propertyType,
propertyType == typeof(ModularAvatarMenuFolderCreator)); propertyType == typeof(ModularAvatarSubMenuCreator));
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
installTargetProperty.objectReferenceValue = newValue; installTargetProperty.objectReferenceValue = newValue;
@ -258,10 +258,10 @@ namespace nadena.dev.modular_avatar.core.editor
return; return;
} }
this._menuFolderCreators = new HashSet<ModularAvatarMenuFolderCreator>(); this._menuFolderCreators = new HashSet<ModularAvatarSubMenuCreator>();
VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(this._installer.transform); VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(this._installer.transform);
if (avatar == null) return; if (avatar == null) return;
foreach (ModularAvatarMenuFolderCreator creator in avatar.gameObject.GetComponentsInChildren<ModularAvatarMenuFolderCreator>()) foreach (ModularAvatarSubMenuCreator creator in avatar.gameObject.GetComponentsInChildren<ModularAvatarSubMenuCreator>())
{ {
this._menuFolderCreators.Add(creator); this._menuFolderCreators.Add(creator);
} }
@ -272,7 +272,7 @@ namespace nadena.dev.modular_avatar.core.editor
return _avatarMenus == null || _avatarMenus.Contains(menu); return _avatarMenus == null || _avatarMenus.Contains(menu);
} }
private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarMenuFolderCreator creator, HashSet<ModularAvatarMenuFolderCreator> session) private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarSubMenuCreator creator, HashSet<ModularAvatarSubMenuCreator> session)
{ {
if (avatar == null) return true; if (avatar == null) return true;
if (this._menuFolderCreators == null) return true; if (this._menuFolderCreators == null) return true;
@ -287,7 +287,7 @@ namespace nadena.dev.modular_avatar.core.editor
case InstallTargetType.VRCExpressionMenu: case InstallTargetType.VRCExpressionMenu:
return creator.installTargetMenu == null || this.IsMenuReachable(avatar, creator.installTargetMenu); return creator.installTargetMenu == null || this.IsMenuReachable(avatar, creator.installTargetMenu);
case InstallTargetType.FolderCreator: case InstallTargetType.FolderCreator:
return creator.installTargetFolderCreator == null || this.IsMenuReachable(avatar, creator.installTargetFolderCreator, session); return creator.installTargetCreator == null || this.IsMenuReachable(avatar, creator.installTargetCreator, session);
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }

View File

@ -5,19 +5,19 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
using static nadena.dev.modular_avatar.core.ModularAvatarMenuFolderCreator; using static nadena.dev.modular_avatar.core.ModularAvatarSubMenuCreator;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor { namespace nadena.dev.modular_avatar.core.editor {
[CustomEditor(typeof(ModularAvatarMenuFolderCreator))] [CustomEditor(typeof(ModularAvatarSubMenuCreator))]
[CanEditMultipleObjects] [CanEditMultipleObjects]
internal class MenuFolderCreatorEditor : MAEditorBase { internal class SubMenuCreatorEditor : MAEditorBase {
private ModularAvatarMenuFolderCreator _creator; private ModularAvatarSubMenuCreator _creator;
private HashSet<VRCExpressionsMenu> _avatarMenus; private HashSet<VRCExpressionsMenu> _avatarMenus;
private HashSet<ModularAvatarMenuFolderCreator> _menuFolderCreators; private HashSet<ModularAvatarSubMenuCreator> _menuFolderCreators;
private void OnEnable() { private void OnEnable() {
this._creator = (ModularAvatarMenuFolderCreator)this.target; this._creator = (ModularAvatarSubMenuCreator)this.target;
this.FindMenus(); this.FindMenus();
this.FindMenuFolderCreators(); this.FindMenuFolderCreators();
} }
@ -25,7 +25,7 @@ namespace nadena.dev.modular_avatar.core.editor {
protected override void OnInnerInspectorGUI() { protected override void OnInnerInspectorGUI() {
VRCAvatarDescriptor commonAvatar = this.FindCommonAvatar(); VRCAvatarDescriptor commonAvatar = this.FindCommonAvatar();
SerializedProperty installTargetTypeProperty = this.serializedObject.FindProperty(nameof(ModularAvatarMenuFolderCreator.installTargetType)); SerializedProperty installTargetTypeProperty = this.serializedObject.FindProperty(nameof(ModularAvatarSubMenuCreator.installTargetType));
EditorGUILayout.PropertyField(installTargetTypeProperty, new GUIContent("Install Target Type")); EditorGUILayout.PropertyField(installTargetTypeProperty, new GUIContent("Install Target Type"));
InstallTargetType installTargetType = (InstallTargetType)Enum.ToObject(typeof(InstallTargetType), installTargetTypeProperty.enumValueIndex); InstallTargetType installTargetType = (InstallTargetType)Enum.ToObject(typeof(InstallTargetType), installTargetTypeProperty.enumValueIndex);
@ -33,11 +33,11 @@ namespace nadena.dev.modular_avatar.core.editor {
string installTargetMenuPropertyName; string installTargetMenuPropertyName;
Type installTargetObjectType; Type installTargetObjectType;
if (installTargetType == InstallTargetType.VRCExpressionMenu) { if (installTargetType == InstallTargetType.VRCExpressionMenu) {
installTargetMenuPropertyName = nameof(ModularAvatarMenuFolderCreator.installTargetMenu); installTargetMenuPropertyName = nameof(ModularAvatarSubMenuCreator.installTargetMenu);
installTargetObjectType = typeof(VRCExpressionsMenu); installTargetObjectType = typeof(VRCExpressionsMenu);
} else { } else {
installTargetMenuPropertyName = nameof(ModularAvatarMenuFolderCreator.installTargetFolderCreator); installTargetMenuPropertyName = nameof(ModularAvatarSubMenuCreator.installTargetCreator);
installTargetObjectType = typeof(ModularAvatarMenuFolderCreator); installTargetObjectType = typeof(ModularAvatarSubMenuCreator);
commonAvatar = null; commonAvatar = null;
} }
@ -61,10 +61,10 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
} }
SerializedProperty folderNameProperty = this.serializedObject.FindProperty(nameof(ModularAvatarMenuFolderCreator.folderName)); SerializedProperty folderNameProperty = this.serializedObject.FindProperty(nameof(ModularAvatarSubMenuCreator.folderName));
EditorGUILayout.PropertyField(folderNameProperty, new GUIContent("Folder Name")); EditorGUILayout.PropertyField(folderNameProperty, new GUIContent("Folder Name"));
SerializedProperty iconProperty = this.serializedObject.FindProperty(nameof(ModularAvatarMenuFolderCreator.icon)); SerializedProperty iconProperty = this.serializedObject.FindProperty(nameof(ModularAvatarSubMenuCreator.icon));
EditorGUILayout.PropertyField(iconProperty, new GUIContent("Folder Icon")); EditorGUILayout.PropertyField(iconProperty, new GUIContent("Folder Icon"));
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
@ -88,8 +88,8 @@ namespace nadena.dev.modular_avatar.core.editor {
break; break;
case InstallTargetType.FolderCreator: case InstallTargetType.FolderCreator:
if (!this.IsMenuReachable(avatar, (ModularAvatarMenuFolderCreator)installTargetProperty.objectReferenceValue, if (!this.IsMenuReachable(avatar, (ModularAvatarSubMenuCreator)installTargetProperty.objectReferenceValue,
new HashSet<ModularAvatarMenuFolderCreator>())) { new HashSet<ModularAvatarSubMenuCreator>())) {
EditorGUILayout.HelpBox("選択されたメニューフォルダからアバターまでのパスが見つかりません。", MessageType.Error); EditorGUILayout.HelpBox("選択されたメニューフォルダからアバターまでのパスが見つかりません。", MessageType.Error);
} }
@ -108,7 +108,7 @@ namespace nadena.dev.modular_avatar.core.editor {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
Object newValue = EditorGUILayout.ObjectField(Localization.G("menuinstall.installto"), displayValue, propertyType, Object newValue = EditorGUILayout.ObjectField(Localization.G("menuinstall.installto"), displayValue, propertyType,
propertyType == typeof(ModularAvatarMenuFolderCreator)); propertyType == typeof(ModularAvatarSubMenuCreator));
if (newValue == this._creator) newValue = displayValue; if (newValue == this._creator) newValue = displayValue;
if (EditorGUI.EndChangeCheck()) { if (EditorGUI.EndChangeCheck()) {
installTargetProperty.objectReferenceValue = newValue; installTargetProperty.objectReferenceValue = newValue;
@ -118,7 +118,7 @@ namespace nadena.dev.modular_avatar.core.editor {
private VRCAvatarDescriptor FindCommonAvatar() { private VRCAvatarDescriptor FindCommonAvatar() {
VRCAvatarDescriptor commonAvatar = null; VRCAvatarDescriptor commonAvatar = null;
foreach (Object targetObject in targets) { foreach (Object targetObject in targets) {
ModularAvatarMenuFolderCreator component = (ModularAvatarMenuFolderCreator)targetObject; ModularAvatarSubMenuCreator component = (ModularAvatarSubMenuCreator)targetObject;
VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(component.transform); VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(component.transform);
if (avatar == null) return null; if (avatar == null) return null;
@ -165,11 +165,11 @@ namespace nadena.dev.modular_avatar.core.editor {
return; return;
} }
this._menuFolderCreators = new HashSet<ModularAvatarMenuFolderCreator>(); this._menuFolderCreators = new HashSet<ModularAvatarSubMenuCreator>();
VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(this._creator.transform); VRCAvatarDescriptor avatar = RuntimeUtil.FindAvatarInParents(this._creator.transform);
if (avatar == null) return; if (avatar == null) return;
foreach (ModularAvatarMenuFolderCreator creator in avatar.gameObject foreach (ModularAvatarSubMenuCreator creator in avatar.gameObject
.GetComponentsInChildren<ModularAvatarMenuFolderCreator>() .GetComponentsInChildren<ModularAvatarSubMenuCreator>()
.Where(creator => creator != this._creator)) { .Where(creator => creator != this._creator)) {
this._menuFolderCreators.Add(creator); this._menuFolderCreators.Add(creator);
} }
@ -179,7 +179,7 @@ namespace nadena.dev.modular_avatar.core.editor {
return this._avatarMenus == null || this._avatarMenus.Contains(menu); return this._avatarMenus == null || this._avatarMenus.Contains(menu);
} }
private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarMenuFolderCreator creator, HashSet<ModularAvatarMenuFolderCreator> session) { private bool IsMenuReachable(VRCAvatarDescriptor avatar, ModularAvatarSubMenuCreator creator, HashSet<ModularAvatarSubMenuCreator> session) {
if (avatar == null) return true; if (avatar == null) return true;
if (this._menuFolderCreators == null) return true; if (this._menuFolderCreators == null) return true;
@ -192,7 +192,7 @@ namespace nadena.dev.modular_avatar.core.editor {
case InstallTargetType.VRCExpressionMenu: case InstallTargetType.VRCExpressionMenu:
return creator.installTargetMenu == null || this.IsMenuReachable(avatar, creator.installTargetMenu); return creator.installTargetMenu == null || this.IsMenuReachable(avatar, creator.installTargetMenu);
case InstallTargetType.FolderCreator: case InstallTargetType.FolderCreator:
return creator.installTargetFolderCreator == null || this.IsMenuReachable(avatar, creator.installTargetFolderCreator, session); return creator.installTargetCreator == null || this.IsMenuReachable(avatar, creator.installTargetCreator, session);
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }

View File

@ -5,29 +5,29 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
using static nadena.dev.modular_avatar.core.ModularAvatarMenuFolderCreator; using static nadena.dev.modular_avatar.core.ModularAvatarSubMenuCreator;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor { namespace nadena.dev.modular_avatar.core.editor {
internal class MenuFolderCreateHook { internal class SubMenuCreateHook {
private static Texture2D _MORE_ICON = AssetDatabase.LoadAssetAtPath<Texture2D>( private static readonly Texture2D _MORE_ICON = AssetDatabase.LoadAssetAtPath<Texture2D>(
"Packages/nadena.dev.modular-avatar/Runtime/Icons/Icon_More_A.png" "Packages/nadena.dev.modular-avatar/Runtime/Icons/Icon_More_A.png"
); );
private readonly Dictionary<ModularAvatarMenuFolderCreator, List<ModularAvatarMenuFolderCreator>> _childMap; private readonly Dictionary<ModularAvatarSubMenuCreator, List<ModularAvatarSubMenuCreator>> _childMap;
private readonly List<ModularAvatarMenuFolderCreator> _rootCreators; private readonly List<ModularAvatarSubMenuCreator> _rootCreators;
private readonly Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> _clonedMenus; private readonly Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> _clonedMenus;
private readonly Dictionary<ModularAvatarMenuFolderCreator, VRCExpressionsMenu> _creatFolders; private readonly Dictionary<ModularAvatarSubMenuCreator, VRCExpressionsMenu> _creatFolders;
private Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> _installTargets; private Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> _installTargets;
private VRCExpressionsMenu _rootMenu; private VRCExpressionsMenu _rootMenu;
public MenuFolderCreateHook() { public SubMenuCreateHook() {
this._childMap = new Dictionary<ModularAvatarMenuFolderCreator, List<ModularAvatarMenuFolderCreator>>(); this._childMap = new Dictionary<ModularAvatarSubMenuCreator, List<ModularAvatarSubMenuCreator>>();
this._rootCreators = new List<ModularAvatarMenuFolderCreator>(); this._rootCreators = new List<ModularAvatarSubMenuCreator>();
this._clonedMenus = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>(); this._clonedMenus = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
this._creatFolders = new Dictionary<ModularAvatarMenuFolderCreator, VRCExpressionsMenu>(); this._creatFolders = new Dictionary<ModularAvatarSubMenuCreator, VRCExpressionsMenu>();
} }
public void OnPreprocessAvatar(GameObject avatarRoot) { public void OnPreprocessAvatar(GameObject avatarRoot) {
@ -45,7 +45,7 @@ namespace nadena.dev.modular_avatar.core.editor {
avatar.expressionsMenu = this.CloneMenu(avatar.expressionsMenu); avatar.expressionsMenu = this.CloneMenu(avatar.expressionsMenu);
this._installTargets = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>(this._clonedMenus); this._installTargets = new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>(this._clonedMenus);
foreach (ModularAvatarMenuFolderCreator rootCreator in this._rootCreators.Where(rootCreator => rootCreator.enabled)) { foreach (ModularAvatarSubMenuCreator rootCreator in this._rootCreators.Where(rootCreator => rootCreator.enabled)) {
if (rootCreator.installTargetMenu == null) { if (rootCreator.installTargetMenu == null) {
rootCreator.installTargetMenu = this._rootMenu; rootCreator.installTargetMenu = this._rootMenu;
} }
@ -59,8 +59,8 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
AddSubMenuElement(targetMenu, rootCreator.folderName, folderMenu, rootCreator.icon); AddSubMenuElement(targetMenu, rootCreator.folderName, folderMenu, rootCreator.icon);
if (!this._childMap.TryGetValue(rootCreator, out List<ModularAvatarMenuFolderCreator> children)) continue; if (!this._childMap.TryGetValue(rootCreator, out List<ModularAvatarSubMenuCreator> children)) continue;
foreach (ModularAvatarMenuFolderCreator child in children) { foreach (ModularAvatarSubMenuCreator child in children) {
this.CreateChildFolder(child); this.CreateChildFolder(child);
} }
this.SplitMenu(rootCreator); this.SplitMenu(rootCreator);
@ -72,8 +72,8 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
private void CreateChildFolder(ModularAvatarMenuFolderCreator creator) { private void CreateChildFolder(ModularAvatarSubMenuCreator creator) {
if (!this._creatFolders.TryGetValue(creator.installTargetFolderCreator, out VRCExpressionsMenu targetMenu)) return; if (!this._creatFolders.TryGetValue(creator.installTargetCreator, out VRCExpressionsMenu targetMenu)) return;
if (!this._creatFolders.TryGetValue(creator, out VRCExpressionsMenu folderMenu)) { if (!this._creatFolders.TryGetValue(creator, out VRCExpressionsMenu folderMenu)) {
// 子が1つの親を参照する関係なので、同じ要素が複数現れることはありえない。 // 子が1つの親を参照する関係なので、同じ要素が複数現れることはありえない。
// 同様に循環参照等にもたどり付けないので考慮に入れなくてよい。 // 同様に循環参照等にもたどり付けないので考慮に入れなくてよい。
@ -82,15 +82,15 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
AddSubMenuElement(targetMenu, creator.folderName, folderMenu, creator.icon); AddSubMenuElement(targetMenu, creator.folderName, folderMenu, creator.icon);
if (!this._childMap.TryGetValue(creator, out List<ModularAvatarMenuFolderCreator> children)) return; if (!this._childMap.TryGetValue(creator, out List<ModularAvatarSubMenuCreator> children)) return;
foreach (ModularAvatarMenuFolderCreator child in children) { foreach (ModularAvatarSubMenuCreator child in children) {
this.CreateChildFolder(child); this.CreateChildFolder(child);
} }
this.SplitMenu(creator); this.SplitMenu(creator);
} }
private void SplitMenu(ModularAvatarMenuFolderCreator creator) { private void SplitMenu(ModularAvatarSubMenuCreator creator) {
VRCExpressionsMenu targetMenu = this._creatFolders[creator]; VRCExpressionsMenu targetMenu = this._creatFolders[creator];
while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS) { while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS) {
VRCExpressionsMenu newMenu = CreateMenuAsset(); VRCExpressionsMenu newMenu = CreateMenuAsset();
@ -103,7 +103,7 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
} }
private void SplitParentMenu(VRCExpressionsMenu targetMenu, ModularAvatarMenuFolderCreator rootCreator) { private void SplitParentMenu(VRCExpressionsMenu targetMenu, ModularAvatarSubMenuCreator rootCreator) {
while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS) { while (targetMenu.controls.Count > VRCExpressionsMenu.MAX_CONTROLS) {
VRCExpressionsMenu newMenu = CreateMenuAsset(); VRCExpressionsMenu newMenu = CreateMenuAsset();
const int keepCount = VRCExpressionsMenu.MAX_CONTROLS - 1; const int keepCount = VRCExpressionsMenu.MAX_CONTROLS - 1;
@ -124,10 +124,10 @@ namespace nadena.dev.modular_avatar.core.editor {
installer.installTargetMenu = this._rootMenu; installer.installTargetMenu = this._rootMenu;
} }
if (installer.InstallTargetType == InstallTargetType.VRCExpressionMenu || installer.installTargetFolderCreator == null) { if (installer.InstallTargetType == InstallTargetType.VRCExpressionMenu || installer.installTargetCreator == null) {
installer.installTargetMenu = this._installTargets[installer.installTargetMenu]; installer.installTargetMenu = this._installTargets[installer.installTargetMenu];
} else { } else {
installer.installTargetMenu = this._creatFolders[installer.installTargetFolderCreator]; installer.installTargetMenu = this._creatFolders[installer.installTargetCreator];
} }
} }
} }
@ -147,17 +147,17 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
private void MappingFolderCreator(GameObject avatarRoot) { private void MappingFolderCreator(GameObject avatarRoot) {
foreach (ModularAvatarMenuFolderCreator creator in avatarRoot.GetComponentsInChildren<ModularAvatarMenuFolderCreator>(true)) { foreach (ModularAvatarSubMenuCreator creator in avatarRoot.GetComponentsInChildren<ModularAvatarSubMenuCreator>(true)) {
if (!creator.enabled) continue; if (!creator.enabled) continue;
if (creator.installTargetType == InstallTargetType.VRCExpressionMenu) { if (creator.installTargetType == InstallTargetType.VRCExpressionMenu) {
this._rootCreators.Add(creator); this._rootCreators.Add(creator);
} else { } else {
if (creator.installTargetFolderCreator == null) { if (creator.installTargetCreator == null) {
this._rootCreators.Add(creator); this._rootCreators.Add(creator);
} else { } else {
if (!this._childMap.TryGetValue(creator.installTargetFolderCreator, out List<ModularAvatarMenuFolderCreator> children)) { if (!this._childMap.TryGetValue(creator.installTargetCreator, out List<ModularAvatarSubMenuCreator> children)) {
children = new List<ModularAvatarMenuFolderCreator>(); children = new List<ModularAvatarSubMenuCreator>();
this._childMap[creator.installTargetFolderCreator] = children; this._childMap[creator.installTargetCreator] = children;
} }
children.Add(creator); children.Add(creator);
@ -166,7 +166,7 @@ namespace nadena.dev.modular_avatar.core.editor {
} }
} }
public static void AddSubMenuElement(VRCExpressionsMenu targetMenu, string elementName, VRCExpressionsMenu subMenu, Texture2D icon = null) { private static void AddSubMenuElement(VRCExpressionsMenu targetMenu, string elementName, VRCExpressionsMenu subMenu, Texture2D icon = null) {
targetMenu.controls.Add(new VRCExpressionsMenu.Control() { targetMenu.controls.Add(new VRCExpressionsMenu.Control() {
name = elementName, name = elementName,
type = VRCExpressionsMenu.Control.ControlType.SubMenu, type = VRCExpressionsMenu.Control.ControlType.SubMenu,

View File

@ -1,7 +1,8 @@
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
using static nadena.dev.modular_avatar.core.ModularAvatarMenuFolderCreator; using static nadena.dev.modular_avatar.core.ModularAvatarSubMenuCreator;
namespace nadena.dev.modular_avatar.core namespace nadena.dev.modular_avatar.core
{ {
@ -10,7 +11,7 @@ namespace nadena.dev.modular_avatar.core
public InstallTargetType InstallTargetType; public InstallTargetType InstallTargetType;
public VRCExpressionsMenu menuToAppend; public VRCExpressionsMenu menuToAppend;
public VRCExpressionsMenu installTargetMenu; public VRCExpressionsMenu installTargetMenu;
public ModularAvatarMenuFolderCreator installTargetFolderCreator; [FormerlySerializedAs("installTargetFolderCreator")] public ModularAvatarSubMenuCreator installTargetCreator;
// ReSharper disable once Unity.RedundantEventFunction // ReSharper disable once Unity.RedundantEventFunction

View File

@ -2,11 +2,11 @@
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
namespace nadena.dev.modular_avatar.core { namespace nadena.dev.modular_avatar.core {
[AddComponentMenu("Modular Avatar/MA Menu Folder Creator")] [AddComponentMenu("Modular Avatar/MA SubMenu Creator")]
public class ModularAvatarMenuFolderCreator : AvatarTagComponent { public class ModularAvatarSubMenuCreator : AvatarTagComponent {
public InstallTargetType installTargetType; public InstallTargetType installTargetType;
public VRCExpressionsMenu installTargetMenu; public VRCExpressionsMenu installTargetMenu;
public ModularAvatarMenuFolderCreator installTargetFolderCreator; public ModularAvatarSubMenuCreator installTargetCreator;
public string folderName; public string folderName;
public Texture2D icon; public Texture2D icon;