feat: unified clothing menu

This commit is contained in:
bd_ 2023-05-05 15:04:19 +09:00
parent 5a45c2b04f
commit d8cab10a3d
22 changed files with 539 additions and 21 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f64854e011ac2dd49b84527e3cfcfd62
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -54,7 +54,7 @@ namespace nadena.dev.modular_avatar.core.editor
/// </summary>
private static bool nowProcessing = false;
public delegate void AvatarProcessorCallback(GameObject obj);
internal delegate void AvatarProcessorCallback(GameObject obj, BuildContext context);
/// <summary>
/// This API is NOT stable. Do not use it yet.
@ -114,7 +114,7 @@ namespace nadena.dev.modular_avatar.core.editor
BuildReport.Clear();
ProcessAvatar(avatar);
Selection.objects = new Object[] { avatar };
Selection.objects = new Object[] {avatar};
}
finally
{
@ -204,11 +204,11 @@ namespace nadena.dev.modular_avatar.core.editor
new BlendshapeSyncAnimationProcessor().OnPreprocessAvatar(avatarGameObject, context);
PhysboneBlockerPass.Process(avatarGameObject);
AfterProcessing?.Invoke(avatarGameObject, context);
context.AnimationDatabase.Commit();
new GCGameObjectsPass(context, avatarGameObject).OnPreprocessAvatar();
AfterProcessing?.Invoke(avatarGameObject);
}
finally
{
@ -333,13 +333,13 @@ namespace nadena.dev.modular_avatar.core.editor
var animator = avatarGameObject.GetComponent<Animator>();
var builder = ty_VRCSdkControlPanelAvatarBuilder3A.GetConstructor(Type.EmptyTypes)
.Invoke(Array.Empty<object>());
var perfStats = ty_AvatarPerformanceStats.GetConstructor(new[] { typeof(bool) })
.Invoke(new object[] { false });
var perfStats = ty_AvatarPerformanceStats.GetConstructor(new[] {typeof(bool)})
.Invoke(new object[] {false});
ty_VRCSdkControlPanelAvatarBuilder3A
.GetMethod("RegisterBuilder", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] { tempControlPanel });
.Invoke(builder, new object[] {tempControlPanel});
ty_VRCSdkControlPanelAvatarBuilder3A.GetMethod("ValidateFeatures").Invoke(
builder, new object[] { avatar, animator, perfStats }
builder, new object[] {avatar, animator, perfStats}
);
}
catch (Exception e)
@ -354,4 +354,4 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
}
}
}

View File

@ -1,11 +1,19 @@
using System.Text;
using UnityEditor;
using UnityEngine;
using VRC.Core;
using VRC.SDK3.Avatars.ScriptableObjects;
namespace nadena.dev.modular_avatar.core.editor
{
public class EasySetupOutfit
{
private static readonly ControlGroup CLOTHING_GROUP
= Util.LoadAssetByGuid<GameObject>("e451e988456f35b49a3d011d780bda07")?.GetComponent<ControlGroup>();
private static readonly VRCExpressionsMenu CLOTHING_MENU
= Util.LoadAssetByGuid<VRCExpressionsMenu>("2fe0aa7ecd6bc4443bade672c978f59d");
private const int PRIORITY = 49;
[MenuItem("GameObject/[ModularAvatar] Setup Outfit", false, PRIORITY)]
@ -18,13 +26,38 @@ namespace nadena.dev.modular_avatar.core.editor
var avatarArmature = avatarHips.transform.parent;
var outfitArmature = outfitHips.transform.parent;
if (outfitArmature.GetComponent<ModularAvatarMergeArmature>() != null) return;
if (outfitArmature.GetComponent<ModularAvatarMergeArmature>() == null)
{
var merge = Undo.AddComponent<ModularAvatarMergeArmature>(outfitArmature.gameObject);
merge.mergeTarget = new AvatarObjectReference();
merge.mergeTarget.referencePath = RuntimeUtil.RelativePath(avatarRoot, avatarArmature.gameObject);
merge.InferPrefixSuffix();
HeuristicBoneMapper.RenameBonesByHeuristic(merge);
}
var merge = Undo.AddComponent<ModularAvatarMergeArmature>(outfitArmature.gameObject);
merge.mergeTarget = new AvatarObjectReference();
merge.mergeTarget.referencePath = RuntimeUtil.RelativePath(avatarRoot, avatarArmature.gameObject);
merge.InferPrefixSuffix();
HeuristicBoneMapper.RenameBonesByHeuristic(merge);
if (CLOTHING_MENU == null || CLOTHING_GROUP == null) return;
var outfitObject = (GameObject) cmd.context;
if (outfitObject.GetComponent<ModularAvatarMenuInstaller>() == null)
{
var installer = Undo.AddComponent<ModularAvatarMenuInstaller>(outfitObject);
installer.installTargetMenu = CLOTHING_MENU;
var menuItem = Undo.AddComponent<ModularAvatarMenuItem>(outfitObject);
menuItem.Control.type = VRCExpressionsMenu.Control.ControlType.Toggle;
menuItem.controlGroup = CLOTHING_GROUP;
var action = Undo.AddComponent<ActionToggleObject>(outfitObject);
action.Objects.Add(new ActionToggleObject.ObjectEntry()
{
target = new AvatarObjectReference()
{
referencePath = RuntimeUtil.AvatarRootPath(outfitObject)
},
Active = true
});
}
}
[MenuItem("GameObject/[ModularAvatar] Setup Outfit", true, PRIORITY)]

View File

@ -24,6 +24,60 @@ namespace nadena.dev.modular_avatar.core.editor
}
public void OnPreprocessAvatar(VRCAvatarDescriptor avatar)
{
List<Action> revertChangesActions = new List<Action>();
try
{
ApplyControlGroupOverrides(revertChangesActions, avatar);
Generate(avatar);
}
finally
{
foreach (var action in revertChangesActions)
{
try
{
action();
}
catch (Exception e)
{
/* ignore */
}
}
}
}
private void ApplyControlGroupOverrides(List<Action> revertChangesActions, VRCAvatarDescriptor avatar)
{
foreach (var groupOverride in avatar.GetComponentsInChildren<SetGroupDefaults>(true))
{
var target = groupOverride.targetControlGroup;
if (target == null)
{
continue;
}
bool oldSynced = target.isSynced;
bool oldSaved = target.isSaved;
var oldDefault = target.defaultValue;
revertChangesActions.Add(() =>
{
if (target == null) return;
target.isSynced = oldSynced;
target.isSaved = oldSaved;
target.defaultValue = oldDefault;
});
target.isSynced = groupOverride.isSynced;
target.isSaved = groupOverride.isSaved;
target.defaultValue = groupOverride.defaultValue;
}
}
private void Generate(VRCAvatarDescriptor avatar)
{
// Locate MenuActions
var actionMenus = avatar.GetComponentsInChildren<MenuAction>(true)

View File

@ -262,5 +262,13 @@ namespace nadena.dev.modular_avatar.core.editor
return path.Contains("/AV3 Demo Assets/Animation/ProxyAnim/proxy")
|| path.Contains("/VRCSDK/Examples3/Animation/ProxyAnim/proxy");
}
public static T LoadAssetByGuid<T>(string guid) where T : UnityEngine.Object
{
var path = AssetDatabase.GUIDToAssetPath(guid);
if (string.IsNullOrWhiteSpace(path)) return null;
return AssetDatabase.LoadAssetAtPath<T>(path);
}
}
}

View File

@ -0,0 +1,4 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("net.fushizen.xdress")]
[assembly: InternalsVisibleTo("net.fushizen.xdress.editor")]

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 13191adee0f6404897a89756755f1857
timeCreated: 1683259670

View File

@ -11,7 +11,5 @@ namespace nadena.dev.modular_avatar.core
[DisallowMultipleComponent]
public abstract class ActionController : AvatarTagComponent
{
internal abstract bool isSyncedProp { get; }
internal abstract bool isSavedProp { get; }
}
}

View File

@ -3,7 +3,7 @@
namespace nadena.dev.modular_avatar.core
{
[AddComponentMenu("Modular Avatar/MA Control Group")]
public class ControlGroup : AvatarTagComponent
public class ControlGroup : ActionController
{
public bool isSynced = true;
public bool isSaved = true;

View File

@ -0,0 +1,14 @@
namespace nadena.dev.modular_avatar.core
{
/// <summary>
/// Tag class which overrides the default configuration of a control group. This is primarily used for asset-based
/// shared control groups which can't be configured in place.
/// </summary>
public class SetGroupDefaults : AvatarTagComponent
{
public bool isSynced;
public bool isSaved;
public ModularAvatarMenuItem defaultValue;
public ControlGroup targetControlGroup;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a6629f9f600742c5856a09779ca0bf12
timeCreated: 1683264633

View File

@ -30,9 +30,6 @@ namespace nadena.dev.modular_avatar.core
public bool isSaved = true;
internal override bool isSyncedProp => isSynced;
internal override bool isSavedProp => isSaved;
protected override void OnValidate()
{
base.OnValidate();

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a588d47980ee09a4ebc7e3b2411b2222
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,112 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1080921226743144895
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 570747844396393361}
- component: {fileID: 8592491745236883318}
- component: {fileID: 8665741192270437505}
- component: {fileID: 778752409363411128}
- component: {fileID: 1787808300107497781}
m_Layer: 0
m_Name: BaseOutfit
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &570747844396393361
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080921226743144895}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -3.1377757, y: -1.206413, z: -5.7641807}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8592491745236883318
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080921226743144895}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
m_Name:
m_EditorClassIdentifier:
menuToAppend: {fileID: 0}
installTargetMenu: {fileID: 11400000, guid: 2fe0aa7ecd6bc4443bade672c978f59d, type: 2}
--- !u!114 &8665741192270437505
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080921226743144895}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name:
icon: {fileID: 0}
type: 102
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 0}
subParameters: []
labels: []
MenuSource: 0
menuSource_otherObjectChildren: {fileID: 0}
controlGroup: {fileID: 2600055823091535516, guid: e451e988456f35b49a3d011d780bda07,
type: 3}
isSynced: 1
isSaved: 1
--- !u!114 &778752409363411128
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080921226743144895}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fcac4d9412424173bd294ffd5fc5f9db, type: 3}
m_Name:
m_EditorClassIdentifier:
Objects:
- target:
referencePath:
Active: 1
--- !u!114 &1787808300107497781
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080921226743144895}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a6629f9f600742c5856a09779ca0bf12, type: 3}
m_Name:
m_EditorClassIdentifier:
isSynced: 1
isSaved: 1
defaultValue: {fileID: 8665741192270437505}
targetControlGroup: {fileID: 2600055823091535516, guid: e451e988456f35b49a3d011d780bda07,
type: 3}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b784af569c82a4845807cfe1775b4d2f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,182 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4243820046722602069
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4243820046722602068}
- component: {fileID: 4243820046722602075}
m_Layer: 0
m_Name: Outfits
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4243820046722602068
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4243820046722602069}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4243820047656436306}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4243820046722602075
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4243820046722602069}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name:
icon: {fileID: 0}
type: 103
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 11400000, guid: 2fe0aa7ecd6bc4443bade672c978f59d, type: 2}
subParameters: []
labels: []
MenuSource: 0
menuSource_otherObjectChildren: {fileID: 0}
controlGroup: {fileID: 0}
isSynced: 1
isSaved: 1
--- !u!1 &4243820047656436300
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4243820047656436306}
- component: {fileID: 4243820047656436307}
m_Layer: 0
m_Name: ClothingMenu
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4243820047656436306
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4243820047656436300}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3.1377757, y: -1.206413, z: -5.7641807}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1425964763638874286}
- {fileID: 4243820046722602068}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4243820047656436307
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4243820047656436300}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 97e46a47dd8a425eb4ce9411defe313d, type: 3}
m_Name:
m_EditorClassIdentifier:
targetObject: {fileID: 4243820047656436300}
--- !u!1001 &1450650863557829439
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 4243820047656436306}
m_Modifications:
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalPosition.x
value: -3.1377757
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalPosition.y
value: -1.206413
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalPosition.z
value: -5.7641807
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1080921226743144895, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
propertyPath: m_Name
value: BaseOutfit
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: b784af569c82a4845807cfe1775b4d2f, type: 3}
--- !u!4 &1425964763638874286 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 570747844396393361, guid: b784af569c82a4845807cfe1775b4d2f,
type: 3}
m_PrefabInstance: {fileID: 1450650863557829439}
m_PrefabAsset: {fileID: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2097228906bdff44fb40a3d9f39cf599
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3376212393282143958
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8419335417409494192}
- component: {fileID: 2600055823091535516}
m_Layer: 0
m_Name: Modular Avatar Clothing Group
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8419335417409494192
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3376212393282143958}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3.1377757, y: -1.206413, z: -5.7641807}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2600055823091535516
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3376212393282143958}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 99c60d83ad614e81a0488d98b83b5c1c, type: 3}
m_Name:
m_EditorClassIdentifier:
isSynced: 1
isSaved: 1
defaultValue: {fileID: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e451e988456f35b49a3d011d780bda07
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,15 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -340790334, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3}
m_Name: Modular Avatar Clothing Menu Contents
m_EditorClassIdentifier:
controls: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2fe0aa7ecd6bc4443bade672c978f59d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,6 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("nadena.dev.modular-avatar.core.editor")]
[assembly: InternalsVisibleTo("net.fushizen.xdress")]
[assembly: InternalsVisibleTo("net.fushizen.xdress.editor")]
[assembly: InternalsVisibleTo("Tests")]