mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-12 05:48:47 -05:00
TakeOwnershipFunc
This commit is contained in:
@@ -51,6 +51,8 @@ namespace UniGLTF
|
||||
// Root GameObject is main object
|
||||
context.SetMainObject(loaded.Root);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ヒエラルキーで使っているリソース
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual void TransferOwnership(Action<UnityEngine.Object> add)
|
||||
public virtual void TransferOwnership(TakeOwnershipFunc take)
|
||||
{
|
||||
var list = new List<UnityEngine.Object>();
|
||||
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<UnityResourceDestroyer>();
|
||||
TransferOwnership(destroyer.Resources.Add);
|
||||
TransferOwnership(o =>
|
||||
{
|
||||
destroyer.Resources.Add(o);
|
||||
return true;
|
||||
});
|
||||
return destroyer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,15 @@ namespace UniGLTF
|
||||
|
||||
List<MaterialLoadInfo> m_materials = new List<MaterialLoadInfo>();
|
||||
public IReadOnlyList<MaterialLoadInfo> 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<UnityEngine.Object> add)
|
||||
/// <summary>
|
||||
/// 所有権(Dispose権)を移譲する
|
||||
/// </summary>
|
||||
/// <param name="take"></param>
|
||||
public void TransferOwnership(TakeOwnershipFunc take)
|
||||
{
|
||||
var list = new List<Material>();
|
||||
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)
|
||||
|
||||
13
Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs
Normal file
13
Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// 所有権を移動する関数。
|
||||
///
|
||||
/// * 所有権が移動する。return true => ImporterContext.Dispose の対象から外れる
|
||||
/// * 所有権が移動しない。return false => Importer.Context.Dispose でDestroyされる
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o">対象のオブジェクト</param>
|
||||
/// <returns>所有権が移動したらtrue</returns>
|
||||
public delegate bool TakeOwnershipFunc(UnityEngine.Object o);
|
||||
}
|
||||
11
Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs.meta
Normal file
11
Assets/UniGLTF/Runtime/UniGLTF/IO/TakeOwnershipFunc.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab2b998b9235dc94a90ccaf2e40a50a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -98,15 +98,23 @@ namespace UniGLTF
|
||||
m_textureCache.Clear();
|
||||
}
|
||||
|
||||
public void TransferOwnership(Action<UnityEngine.Object> add)
|
||||
/// <summary>
|
||||
/// 所有権(Dispose権)を移譲する
|
||||
/// </summary>
|
||||
/// <param name="take"></param>
|
||||
public void TransferOwnership(TakeOwnershipFunc take)
|
||||
{
|
||||
var keys = new List<string>();
|
||||
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)
|
||||
|
||||
@@ -10,10 +10,14 @@ namespace VRM
|
||||
public class VRMEditorImporterContext
|
||||
{
|
||||
VRMImporterContext m_context;
|
||||
UnityPath m_prefabPath;
|
||||
List<UnityPath> m_paths = new List<UnityPath>();
|
||||
|
||||
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<UnityPath>(){
|
||||
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<GameObject>();
|
||||
PrefabUtility.SaveAsPrefabAssetAndConnect(root, prefabPath.Value, InteractionMode.AutomatedAction);
|
||||
Debug.LogFormat("replace prefab: {0}", m_prefabPath);
|
||||
var prefab = m_prefabPath.LoadAsset<GameObject>();
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,28 +304,44 @@ namespace VRM
|
||||
return meta;
|
||||
}
|
||||
|
||||
public override void TransferOwnership(Action<UnityEngine.Object> 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<BlendShapeClip>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user