Skip to content

Commit

Permalink
[VRM → VRChat] プレハブインスタンスではないGameObjectの場合でもConverter.Convert()が成功するように
Browse files Browse the repository at this point in the history
パブリックAPIをC#スクリプトから利用する場合の、UniVRMの通常のインポーターを利用しないなどの特殊用途向け。
GUIからの変換においては、UniVRMの通常のインポーターによって生成されたプレハブアセットの変換以外の動作は、引き続き保証しない。
  • Loading branch information
esperecyan committed Aug 23, 2024
1 parent f899150 commit ceeefba
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Editor/Components/ComponentsReplacer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private static void ConvertVRMFirstPerson(GameObject avatar)
private static void RemoveUnusedColliderGroups(GameObject avatar)
{
IEnumerable<GameObject> objectsHavingUsedColliderGroup = avatar.GetComponentsInChildren<VRMSpringBone>()
.SelectMany(springBone => springBone.ColliderGroups)
.SelectMany(springBone => springBone.ColliderGroups ?? new VRMSpringBoneColliderGroup[] { })
.Select(colliderGroup => colliderGroup.gameObject)
.ToArray();

Expand Down
68 changes: 47 additions & 21 deletions Editor/Duplicator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,47 @@ bool combineMeshesAndSubMeshes
return destinationPrefabInstance;
}

/// <summary>
/// アセットの保存先のフォルダを決定します。
/// </summary>
/// <param name="avatarGameObject"></param>
/// <param name="type">アセットの種類。</param>
/// <param name="fileName">ファイル名。</param>
/// <returns>「Assets/」から始まるパス。
/// アバターがプレハブインスタンスならプレハブのパスを、
/// そうでなければ、参照されている、アセットとして存在する、最初に見つかったマテリアルのパスを、
/// いずれも存在しなければ、AssetsフォルダとアバターのGameObjectの名前を結合したパスを返します。</returns>
private static string DetermineDestinationFolderPath(GameObject avatarGameObject)
{
var destinationFolderPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(avatarGameObject);
if (string.IsNullOrEmpty(destinationFolderPath))
{
foreach (var material in avatarGameObject
.GetComponentsInChildren<Renderer>().SelectMany(renderer => renderer.sharedMaterials))
{
if (material == null)
{
continue;
}

var materialPath = AssetDatabase.GetAssetPath(material);
if (string.IsNullOrEmpty(materialPath))
{
continue;
}

destinationFolderPath = materialPath;
break;
}

if (string.IsNullOrEmpty(destinationFolderPath))
{
destinationFolderPath = Path.Combine("Assets", avatarGameObject.name);
}
}
return destinationFolderPath;
}

/// <summary>
/// アセットの種類に応じて、保存先を決定します。
/// </summary>
Expand All @@ -85,22 +126,6 @@ internal static string DetermineAssetPath(string destinationFolderPath, Type typ
return destinationFolderUnityPath.Child(fileName).Value;
}

/// <summary>
/// アセットの種類に応じて、保存先を決定します。
/// </summary>
/// <param name="prefabInstance"></param>
/// <param name="type">アセットの種類。</param>
/// <param name="fileName">ファイル名。</param>
/// <returns>「Assets/」から始まるパス。</returns>
internal static string DetermineAssetPath(GameObject prefabInstance, Type type, string fileName = "")
{
return Duplicator.DetermineAssetPath(
PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabInstance),
type,
fileName
);
}

/// <summary>
/// アセットをプレハブが置かれているディレクトリの直下のフォルダへ複製します。
/// </summary>
Expand Down Expand Up @@ -133,10 +158,11 @@ internal static T DuplicateAssetToFolder<T>(
destinationFileName = fileName;
}

return Duplicator.DuplicateAsset(
source,
destinationPath: Duplicator.DetermineAssetPath(prefabInstance, typeof(T), destinationFileName)
);
return Duplicator.DuplicateAsset(source, destinationPath: Duplicator.DetermineAssetPath(
Duplicator.DetermineDestinationFolderPath(prefabInstance),
typeof(T),
destinationFileName
));
}

/// <summary>
Expand Down Expand Up @@ -209,7 +235,7 @@ string destinationFileName
{
return Duplicator.CreateObjectToFolder<T>(
source,
PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabInstance),
Duplicator.DetermineDestinationFolderPath(prefabInstance),
destinationFileName
);
}
Expand Down

0 comments on commit ceeefba

Please sign in to comment.