-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
AssetUtility.cs
111 lines (100 loc) · 4.26 KB
/
AssetUtility.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#nullable enable
using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Object = UnityEngine.Object;
using UnityEditor;
using UniGLTF;
using VRM;
namespace Esperecyan.UniVRMExtensions
{
/// <summary>
/// アセットの保存。
/// </summary>
internal static class AssetUtility
{
/// <summary>
/// アセットの種類ごとの、複製先のフォルダ名の末尾に追加する文字列。
/// </summary>
private static readonly IDictionary<Type, string> TypeSuffixPairs = new Dictionary<Type, string>
{
{ typeof(VRMMetaObject ), ".MetaObject" },
{ typeof(BlendShapeAvatar), ".BlendShapes" },
{ typeof(BlendShapeClip ), ".BlendShapes" },
};
/// <summary>
/// プレハブアセットを生成します。
/// </summary>
/// <param name="gameObject">ヒエラルキー上のオブジェクト、またはプレハブアセット。</param>
/// <returns></returns>
internal static string CreatePrefabVariant(GameObject gameObject)
{
var path = AssetDatabase.GetAssetPath(gameObject);
var activeObjectIsPrefabAsset = !string.IsNullOrEmpty(path);
if (activeObjectIsPrefabAsset)
{
gameObject = (GameObject)PrefabUtility.InstantiatePrefab(gameObject);
if (Path.GetExtension(path) != ".prefab")
{
path = $"{Path.GetDirectoryName(path)}/{Path.GetFileNameWithoutExtension(path)}.prefab";
}
}
else
{
path = PrefabUtility.GetNearestPrefabInstanceRoot(gameObject) == gameObject
? PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject)
: $"Assets/{gameObject.name}.prefab";
}
path = AssetDatabase.GenerateUniqueAssetPath(path);
PrefabUtility.SaveAsPrefabAsset(gameObject, path);
if (activeObjectIsPrefabAsset)
{
Object.DestroyImmediate(gameObject);
}
AssetDatabase.SaveAssets();
return path;
}
/// <summary>
/// インスタンスをプレハブが置かれているディレクトリの直下のフォルダへ保存します。
/// </summary>
/// <remarks>
/// 複製先にすでにアセットが存在していれば上書きし、保存先のアセットのGUIDが変わらないようにします。
/// </remarks>
/// <param name="prefabPath">「Assets/」から始まるパス。</param>
/// <param name="instance">保存するインスタンス。</param>
/// <returns></returns>
internal static T Save<T>(string prefabPath, T instance) where T : Object
{
var destinationPath = AssetUtility.DetermineAssetPath(prefabPath, instance);
var destination = AssetDatabase.LoadMainAssetAtPath(destinationPath);
if (destination)
{
EditorUtility.CopySerialized(instance, destination);
}
else
{
AssetDatabase.CreateAsset(instance, destinationPath);
}
var asset = AssetDatabase.LoadAssetAtPath<T>(destinationPath);
EditorUtility.SetDirty(asset);
return asset;
}
/// <summary>
/// インスタンスの種類に応じて、保存先を決定します。
/// </summary>
/// <param name="prefabPath">「Assets/」から始まるパス。</param>
/// <param name="instance">保存するインスタンス。</param>
/// <returns>「Assets/」から始まるパス。</returns>
private static string DetermineAssetPath(string prefabPath, Object instance)
{
var destinationFolderUnityPath = UnityPath.FromUnityPath(prefabPath).GetAssetFolder(
AssetUtility.TypeSuffixPairs
.First(typeSuffixPair => typeSuffixPair.Key.IsInstanceOfType(instance)).Value
);
destinationFolderUnityPath.EnsureFolder();
return destinationFolderUnityPath.Child(instance.name + ".asset").Value;
}
}
}