diff --git a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ScriptedImporterImpl.cs b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ScriptedImporterImpl.cs
index ac9897aaf..ec13afd46 100644
--- a/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ScriptedImporterImpl.cs
+++ b/Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/ScriptedImporterImpl.cs
@@ -51,6 +51,8 @@ namespace UniGLTF
// Root GameObject is main object
context.SetMainObject(loaded.Root);
}
+
+ return true;
});
}
}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs
index 653bbfa3a..991ce537c 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs
@@ -206,6 +206,14 @@ namespace UniGLTF
}
}
}
+ void RemoveMesh(Mesh mesh)
+ {
+ var index = Meshes.FindIndex(x => x.Mesh == mesh);
+ if (index >= 0)
+ {
+ Meshes.RemoveAt(index);
+ }
+ }
public void EnableUpdateWhenOffscreen()
{
@@ -266,27 +274,44 @@ namespace UniGLTF
/// Root ヒエラルキーで使っているリソース
///
///
- public virtual void TransferOwnership(Action add)
+ public virtual void TransferOwnership(TakeOwnershipFunc take)
{
+ var list = new List();
foreach (var mesh in Meshes)
{
- add(mesh.Mesh);
+ if (take(mesh.Mesh))
+ {
+ list.Add(mesh.Mesh);
+ }
+ }
+ foreach (var x in list)
+ {
+ RemoveMesh(x as Mesh);
}
- Meshes.Clear();
- TextureFactory.TransferOwnership(add);
- MaterialFactory.TransferOwnership(add);
+ TextureFactory.TransferOwnership(take);
+ MaterialFactory.TransferOwnership(take);
+ list.Clear();
foreach (var animation in AnimationClips)
{
- add(animation);
+ if (take(animation))
+ {
+ list.Add(animation);
+ }
+ }
+ foreach (var x in list)
+ {
+ AnimationClips.Remove(x as AnimationClip);
}
- AnimationClips.Clear();
if (m_ownRoot && Root != null)
{
- add(Root);
- m_ownRoot = false;
+ if (take(Root))
+ {
+ // 所有権(Dispose権)
+ m_ownRoot = false;
+ }
}
}
@@ -302,7 +327,11 @@ namespace UniGLTF
public UnityResourceDestroyer DisposeOnGameObjectDestroyed()
{
var destroyer = Root.AddComponent();
- TransferOwnership(destroyer.Resources.Add);
+ TransferOwnership(o =>
+ {
+ destroyer.Resources.Add(o);
+ return true;
+ });
return destroyer;
}
}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs
index 57cd2e7d7..b36126eba 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs
@@ -75,6 +75,15 @@ namespace UniGLTF
List m_materials = new List();
public IReadOnlyList Materials => m_materials;
+ void Remove(Material material)
+ {
+ var index = m_materials.FindIndex(x => x.Asset == material);
+ if (index >= 0)
+ {
+ m_materials.RemoveAt(index);
+
+ }
+ }
public void Dispose()
{
@@ -82,6 +91,7 @@ namespace UniGLTF
{
if (!x.UseExternal)
{
+ // 外部の '.asset' からロードしていない
#if VRM_DEVELOP
Debug.Log($"Destroy {x.Asset}");
#endif
@@ -90,16 +100,28 @@ namespace UniGLTF
}
}
- public void TransferOwnership(Action add)
+ ///
+ /// 所有権(Dispose権)を移譲する
+ ///
+ ///
+ public void TransferOwnership(TakeOwnershipFunc take)
{
+ var list = new List();
foreach (var x in m_materials)
{
if (!x.UseExternal)
{
- add(x.Asset);
+ // 外部の '.asset' からロードしていない
+ if (take(x.Asset))
+ {
+ list.Add(x.Asset);
+ }
}
}
- m_materials.Clear();
+ foreach (var x in list)
+ {
+ Remove(x);
+ }
}
public Material GetMaterial(int index)
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs
new file mode 100644
index 000000000..4cb91856c
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs
@@ -0,0 +1,13 @@
+namespace UniGLTF
+{
+ ///
+ /// 所有権を移動する関数。
+ ///
+ /// * 所有権が移動する。return true => ImporterContext.Dispose の対象から外れる
+ /// * 所有権が移動しない。return false => Importer.Context.Dispose でDestroyされる
+ ///
+ ///
+ /// 対象のオブジェクト
+ /// 所有権が移動したらtrue
+ public delegate bool TakeOwnershipFunc(UnityEngine.Object o);
+}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs.meta
new file mode 100644
index 000000000..0b34ae7e0
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ab2b998b9235dc94a90ccaf2e40a50a6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs
index 155f4a670..c89cde2ae 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs
@@ -98,15 +98,23 @@ namespace UniGLTF
m_textureCache.Clear();
}
- public void TransferOwnership(Action add)
+ ///
+ /// 所有権(Dispose権)を移譲する
+ ///
+ ///
+ public void TransferOwnership(TakeOwnershipFunc take)
{
var keys = new List();
foreach (var x in m_textureCache)
{
if (x.Value.IsUsed && !x.Value.IsExternal)
{
- keys.Add(x.Key);
- add(x.Value.Texture);
+ // マテリアルから参照されていて
+ // 外部のAssetからロードしていない。
+ if (take(x.Value.Texture))
+ {
+ keys.Add(x.Key);
+ }
}
}
foreach (var x in keys)
diff --git a/Assets/VRM/Editor/Format/VRMEditorImporterContext.cs b/Assets/VRM/Editor/Format/VRMEditorImporterContext.cs
index e258c33fd..54b40740a 100644
--- a/Assets/VRM/Editor/Format/VRMEditorImporterContext.cs
+++ b/Assets/VRM/Editor/Format/VRMEditorImporterContext.cs
@@ -10,10 +10,14 @@ namespace VRM
public class VRMEditorImporterContext
{
VRMImporterContext m_context;
+ UnityPath m_prefabPath;
+ List m_paths = new List();
- public VRMEditorImporterContext(VRMImporterContext context)
+
+ public VRMEditorImporterContext(VRMImporterContext context, UnityPath prefabPath)
{
m_context = context;
+ m_prefabPath = prefabPath;
}
public bool AvoidOverwriteAndLoad(UnityPath assetPath, UnityEngine.Object o)
@@ -57,7 +61,7 @@ namespace VRM
return false;
}
- public UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o, bool meshAsSubAsset)
+ public UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o)
{
if (o is BlendShapeAvatar
|| o is BlendShapeClip)
@@ -96,7 +100,7 @@ namespace VRM
var texturePath = textureDir.Child(o.name.EscapeFilePath() + ".asset");
return texturePath;
}
- else if (o is Mesh && !meshAsSubAsset)
+ else if (o is Mesh)
{
var meshDir = prefabPath.GetAssetFolder(".Meshes");
var meshPath = meshDir.Child(o.name.EscapeFilePath() + ".asset");
@@ -146,85 +150,64 @@ namespace VRM
TextureExtractor.ExtractTextures(assetPath.Value, subAssets, _ => { }, onTextureReloaded);
}
- public void SaveAsAsset(UnityPath prefabPath, bool meshAsSubAsset = false)
+ bool SaveAsAsset(UnityEngine.Object o)
{
- m_context.ShowMeshes();
-
- //var prefabPath = PrefabPath;
- if (prefabPath.IsFileExists)
+ if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o)))
{
- // clear SubAssets
- foreach (var x in prefabPath.GetSubAssets().Where(x => !(x is GameObject) && !(x is Component)))
+ // already exists. not dispose
+ return true;
+ }
+
+ var assetPath = GetAssetPath(m_prefabPath, o);
+ if (assetPath.IsNull)
+ {
+ return false;
+ }
+
+ if (assetPath.IsFileExists)
+ {
+ if (AvoidOverwriteAndLoad(assetPath, o))
{
- GameObject.DestroyImmediate(x, true);
+ // 上書きせずに既存のアセットからロードして置き換えた
+ return true;
}
}
+ // アセットとして書き込む
+ assetPath.Parent.EnsureFolder();
+ assetPath.CreateAsset(o);
+ m_paths.Add(assetPath);
+
+ // 所有権が移動
+ return true;
+ }
+
+ public void SaveAsAsset()
+ {
+ m_context.ShowMeshes();
+
//
// save sub assets
//
- var paths = new List(){
- prefabPath
- };
-
- // backup
- var root = m_context.Root;
-
- m_context.TransferOwnership(o =>
- {
-
- if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o)))
- {
- // already exists
- return;
- }
-
- var assetPath = GetAssetPath(prefabPath, o, meshAsSubAsset);
- if (!assetPath.IsNull)
- {
- if (assetPath.IsFileExists)
- {
- if (AvoidOverwriteAndLoad(assetPath, o))
- {
- // 上書きせずに既存のアセットからロードして置き換えた
- return;
- }
- }
-
- // アセットとして書き込む
- assetPath.Parent.EnsureFolder();
- assetPath.CreateAsset(o);
- paths.Add(assetPath);
- }
- else
- {
- // save as subasset
- if (o is GameObject)
- {
-
- }
- else
- {
- prefabPath.AddObjectToAsset(o);
- }
- }
-
- });
+ m_paths.Clear();
+ m_paths.Add(m_prefabPath);
+ m_context.TransferOwnership(SaveAsAsset);
// Create or update Main Asset
- if (prefabPath.IsFileExists)
+ if (m_prefabPath.IsFileExists)
{
- Debug.LogFormat("replace prefab: {0}", prefabPath);
- var prefab = prefabPath.LoadAsset();
- PrefabUtility.SaveAsPrefabAssetAndConnect(root, prefabPath.Value, InteractionMode.AutomatedAction);
+ Debug.LogFormat("replace prefab: {0}", m_prefabPath);
+ var prefab = m_prefabPath.LoadAsset();
+ PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, m_prefabPath.Value, InteractionMode.AutomatedAction);
}
else
{
- Debug.LogFormat("create prefab: {0}", prefabPath);
- PrefabUtility.SaveAsPrefabAssetAndConnect(root, prefabPath.Value, InteractionMode.AutomatedAction);
+ Debug.LogFormat("create prefab: {0}", m_prefabPath);
+ PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, m_prefabPath.Value, InteractionMode.AutomatedAction);
}
- foreach (var x in paths)
+
+ foreach (var x in m_paths)
{
x.ImportAsset();
}
diff --git a/Assets/VRM/Editor/Format/VRMImporterMenu.cs b/Assets/VRM/Editor/Format/VRMImporterMenu.cs
index f99e8dda3..88879c266 100644
--- a/Assets/VRM/Editor/Format/VRMImporterMenu.cs
+++ b/Assets/VRM/Editor/Format/VRMImporterMenu.cs
@@ -64,15 +64,15 @@ namespace VRM
//
using (var context = new VRMImporterContext(parser))
{
- var editor = new VRMEditorImporterContext(context);
+ var editor = new VRMEditorImporterContext(context, prefabPath);
context.Load();
- editor.SaveAsAsset(prefabPath);
+ editor.SaveAsAsset();
}
};
using (var context = new VRMImporterContext(parser))
{
- var editor = new VRMEditorImporterContext(context);
+ var editor = new VRMEditorImporterContext(context, prefabPath);
editor.ConvertAndExtractImages(UnityPath.FromFullpath(path), onCompleted);
}
}
diff --git a/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs b/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs
index daab9d98f..be8655a4b 100644
--- a/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs
+++ b/Assets/VRM/Editor/Format/vrmAssetPostprocessor.cs
@@ -1,7 +1,5 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
using UniGLTF;
using UnityEditor;
using UnityEngine;
@@ -38,16 +36,7 @@ namespace VRM
}
var parser = new GltfParser();
- try
- {
- parser.ParseGlb(File.ReadAllBytes(path.FullPath));
- }
- catch (KeyNotFoundException)
- {
- // invalid VRM-0.X.
- // maybe VRM-1.0.do nothing
- return;
- }
+ parser.ParseGlb(File.ReadAllBytes(path.FullPath));
var prefabPath = path.Parent.Child(path.FileNameWithoutExtension + ".prefab");
@@ -55,15 +44,15 @@ namespace VRM
{
using (var context = new VRMImporterContext(parser))
{
- var editor = new VRMEditorImporterContext(context);
+ var editor = new VRMEditorImporterContext(context, prefabPath);
context.Load();
- editor.SaveAsAsset(prefabPath);
+ editor.SaveAsAsset();
}
};
using (var context = new VRMImporterContext(parser))
{
- var editor = new VRMEditorImporterContext(context);
+ var editor = new VRMEditorImporterContext(context, prefabPath);
editor.ConvertAndExtractImages(path, onCompleted);
}
}
diff --git a/Assets/VRM/Runtime/IO/VRMImporterContext.cs b/Assets/VRM/Runtime/IO/VRMImporterContext.cs
index 795cfdf13..5bbba0780 100644
--- a/Assets/VRM/Runtime/IO/VRMImporterContext.cs
+++ b/Assets/VRM/Runtime/IO/VRMImporterContext.cs
@@ -304,28 +304,44 @@ namespace VRM
return meta;
}
- public override void TransferOwnership(Action add)
+ public override void TransferOwnership(TakeOwnershipFunc take)
{
// VRM 固有のリソース(ScriptableObject)
- add(HumanoidAvatar);
- HumanoidAvatar = null;
+ if (take(HumanoidAvatar))
+ {
+ HumanoidAvatar = null;
+ }
- add(Meta);
- Meta = null;
+ if (take(Meta))
+ {
+ Meta = null;
+ }
- add(AvatarDescription);
- AvatarDescription = null;
+ if (take(AvatarDescription))
+ {
+ AvatarDescription = null;
+ }
+ var list = new List();
foreach (var x in BlendShapeAvatar.Clips)
{
- add(x);
+ if (take(x))
+ {
+ list.Add(x);
+ }
+ }
+ foreach (var x in list)
+ {
+ BlendShapeAvatar.Clips.Remove(x);
}
- BlendShapeAvatar.Clips.Clear();
- add(BlendShapeAvatar);
- BlendShapeAvatar = null;
+ if (take(BlendShapeAvatar))
+ {
+ BlendShapeAvatar = null;
+ }
- base.TransferOwnership(add);
+ // GLTF のリソース
+ base.TransferOwnership(take);
}
}
}