Merge pull request #1021 from ousttrue/feature10/UnityObjectManager

UnityObjectDestoyer 改め UnityObjectManager
This commit is contained in:
ousttrue
2021-06-11 17:22:42 +09:00
committed by GitHub
39 changed files with 630 additions and 685 deletions

View File

@@ -21,7 +21,7 @@ namespace UniGLTF
}
}
importer.DrawRemapGUI<AnimationClip>(parser.GLTF.animations.Select(x => new SubAssetKey(typeof(AnimationClip), x.name)));
importer.DrawRemapGUI<AnimationClip>(AnimationImporterUtil.EnumerateSubAssetKeys(parser.GLTF));
if (GUILayout.Button("Clear"))
{

View File

@@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using VRMShaders;
#if UNITY_2020_2_OR_NEWER
@@ -50,20 +48,18 @@ namespace UniGLTF
}
loader.InvertAxis = reverseAxis;
loader.Load();
loader.ShowMeshes();
var loaded = loader.Load();
loaded.ShowMeshes();
loader.TransferOwnership(o =>
loaded.TransferOwnership((k, o) =>
{
context.AddObjectToAsset(o.name, o);
if (o is GameObject)
{
// Root GameObject is main object
context.SetMainObject(loader.Root);
}
return true;
context.AddObjectToAsset(k.Name, o);
});
var root = loaded.Root;
GameObject.DestroyImmediate(loaded);
context.AddObjectToAsset(root.name, root);
context.SetMainObject(root);
}
}
}

View File

@@ -107,13 +107,4 @@ namespace UniGLTF
};
}
}
public static class KeyValuePariExtensions
{
public static void Deconstruct<T, U>(this KeyValuePair<T, U> pair, out T key, out U value)
{
key = pair.Key;
value = pair.Value;
}
}
}

View File

@@ -312,5 +312,13 @@ namespace UniGLTF
}
return clip;
}
public static IEnumerable<VRMShaders.SubAssetKey> EnumerateSubAssetKeys(glTF gltf)
{
foreach (var gltfAnimation in gltf.animations)
{
yield return new VRMShaders.SubAssetKey(typeof(AnimationClip), gltfAnimation.name);
}
}
}
}

View File

@@ -10,7 +10,7 @@ namespace UniGLTF
/// <summary>
/// GLTF importer
/// </summary>
public class ImporterContext : IDisposable
public class ImporterContext : IResponsibilityForDestroyObjects
{
public ITextureDescriptorGenerator TextureDescriptorGenerator { get; protected set; }
public IMaterialDescriptorGenerator MaterialDescriptorGenerator { get; protected set; }
@@ -61,7 +61,7 @@ namespace UniGLTF
};
#region Load. Build unity objects
public virtual async Task LoadAsync(IAwaitCaller awaitCaller = null, Func<string, IDisposable> MeasureTime = null)
public virtual async Task<RuntimeGltfInstance> LoadAsync(IAwaitCaller awaitCaller = null, Func<string, IDisposable> MeasureTime = null)
{
if (awaitCaller == null)
{
@@ -108,6 +108,8 @@ namespace UniGLTF
}
await OnLoadHierarchy(awaitCaller, MeasureTime);
return RuntimeGltfInstance.AttachTo(Root, this);
}
/// <summary>
@@ -119,18 +121,17 @@ namespace UniGLTF
{
if (GLTF.animations != null && GLTF.animations.Any())
{
for (int i = 0; i < GLTF.animations.Count; ++i)
foreach (var (key, gltfAnimation) in Enumerable.Zip(AnimationImporterUtil.EnumerateSubAssetKeys(GLTF), GLTF.animations, (x, y) => (x, y)))
{
var gltfAnimation = GLTF.animations[i];
AnimationClip clip = default;
if (_externalObjectMap.TryGetValue(new SubAssetKey(typeof(AnimationClip), gltfAnimation.name), out UnityEngine.Object value))
if (_externalObjectMap.TryGetValue(key, out UnityEngine.Object value))
{
clip = value as AnimationClip;
}
else
{
clip = AnimationImporterUtil.ConvertAnimationClip(GLTF, GLTF.animations[i], InvertAxis.Create());
AnimationClips.Add(clip);
clip = AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create());
AnimationClips.Add((key, clip));
}
}
@@ -150,7 +151,7 @@ namespace UniGLTF
var animation = Root.AddComponent<Animation>();
for (int i = 0; i < AnimationClips.Count; ++i)
{
var clip = AnimationClips[i];
var (_, clip) = AnimationClips[i];
animation.AddClip(clip, clip.name);
if (i == 0)
{
@@ -275,46 +276,12 @@ namespace UniGLTF
#endregion
#region Imported
public GameObject Root;
bool m_ownRoot = true;
protected GameObject Root;
public List<Transform> Nodes = new List<Transform>();
public List<MeshWithMaterials> Meshes = new List<MeshWithMaterials>();
public void ShowMeshes()
{
foreach (var x in Meshes)
{
foreach (var y in x.Renderers)
{
y.enabled = true;
}
}
}
void RemoveMesh(Mesh mesh)
{
var index = Meshes.FindIndex(x => x.Mesh == mesh);
if (index >= 0)
{
Meshes.RemoveAt(index);
}
}
public void EnableUpdateWhenOffscreen()
{
foreach (var x in Meshes)
{
foreach (var r in x.Renderers)
{
var skinnedMeshRenderer = r as SkinnedMeshRenderer;
if (skinnedMeshRenderer != null)
{
skinnedMeshRenderer.updateWhenOffscreen = true;
}
}
}
}
public List<AnimationClip> AnimationClips = new List<AnimationClip>();
public List<(SubAssetKey, AnimationClip)> AnimationClips = new List<(SubAssetKey, AnimationClip)>();
#endregion
/// <summary>
@@ -322,101 +289,42 @@ namespace UniGLTF
/// </summary>
public virtual void Dispose()
{
Action<UnityEngine.Object> destroy = UnityResourceDestroyer.DestroyResource();
foreach (var x in AnimationClips)
foreach (var (k, x) in AnimationClips)
{
#if VRM_DEVELOP
// Debug.Log($"Destroy {x}");
#endif
destroy(x);
UnityObjectDestoyer.DestroyRuntimeOrEditor(x);
}
AnimationClips.Clear();
foreach (var x in Meshes)
{
#if VRM_DEVELOP
// Debug.Log($"Destroy {x.Mesh}");
#endif
destroy(x.Mesh);
UnityObjectDestoyer.DestroyRuntimeOrEditor(x.Mesh);
}
Meshes.Clear();
MaterialFactory?.Dispose();
TextureFactory?.Dispose();
if (m_ownRoot && Root != null)
{
#if VRM_DEVELOP
// Debug.Log($"Destroy {Root}");
#endif
destroy(Root);
}
}
/// <summary>
/// Root ヒエラルキーで使っているリソース
/// </summary>
/// <returns></returns>
public virtual void TransferOwnership(Func<UnityEngine.Object, bool> take)
public virtual void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
var list = new List<UnityEngine.Object>();
foreach (var mesh in Meshes)
foreach (var mesh in Meshes.ToArray())
{
if (take(mesh.Mesh))
{
list.Add(mesh.Mesh);
}
}
foreach (var x in list)
{
RemoveMesh(x as Mesh);
take(SubAssetKey.Create(mesh.Mesh), mesh.Mesh);
Meshes.Remove(mesh);
}
TextureFactory.TransferOwnership(take);
MaterialFactory.TransferOwnership(take);
list.Clear();
foreach (var animation in AnimationClips)
foreach (var (key, animation) in AnimationClips.ToArray())
{
if (take(animation))
{
list.Add(animation);
}
take(key, animation);
AnimationClips.Remove((key, animation));
}
foreach (var x in list)
{
AnimationClips.Remove(x as AnimationClip);
}
if (m_ownRoot && Root != null)
{
if (take(Root))
{
// 所有権(Dispose権)
m_ownRoot = false;
}
}
}
/// <summary>
/// RootにUnityResourceDestroyerをアタッチして、
/// RootをUnityEngine.Object.Destroyしたときに、
/// 関連するUnityEngine.Objectを破棄するようにする。
/// Mesh, Material, Texture, AnimationClip, GameObject の所有者が
/// ImporterContext から UnityResourceDestroyer に移動する。
/// ImporterContext.Dispose の対象から外れる。
/// </summary>
/// <returns></returns>
public UnityResourceDestroyer DisposeOnGameObjectDestroyed()
{
var destroyer = Root.AddComponent<UnityResourceDestroyer>();
TransferOwnership(o =>
{
destroyer.Resources.Add(o);
return true;
});
return destroyer;
}
}
}

View File

@@ -8,7 +8,7 @@ namespace UniGLTF
/// <summary>
/// Build unity objects from parsed gltf
/// </summary>
public static void Load(this ImporterContext self)
public static RuntimeGltfInstance Load(this ImporterContext self)
{
var meassureTime = new ImporterContextSpeedLog();
var task = self.LoadAsync(default(ImmediateCaller), meassureTime.MeasureTime);
@@ -24,6 +24,8 @@ namespace UniGLTF
#if VRM_DEVELOP
Debug.Log($"{self.Parser.TargetPath}: {meassureTime.GetSpeedLog()}");
#endif
return task.Result;
}
}
}

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
using UnityEngine;
using VRMShaders;
namespace UniGLTF
{
/// <summary>
/// ImporterContext の Load 結果の GltfModel
///
/// Runtime でモデルを Destory したときに関連リソース(Texture, Material...などの UnityEngine.Object)を自動的に Destroy する。
/// </summary>
public class RuntimeGltfInstance : MonoBehaviour, IResponsibilityForDestroyObjects
{
/// <summary>
/// this is UniGLTF root gameObject
/// </summary>
public GameObject Root => this.gameObject;
List<(SubAssetKey, UnityEngine.Object)> m_resources = new List<(SubAssetKey, UnityEngine.Object)>();
public static RuntimeGltfInstance AttachTo(GameObject go, ImporterContext context)
{
var loaded = go.AddComponent<RuntimeGltfInstance>();
context.TransferOwnership((k, o) =>
{
loaded.m_resources.Add((k, o));
});
return loaded;
}
public void ShowMeshes()
{
foreach (var r in GetComponentsInChildren<Renderer>())
{
r.enabled = true;
}
}
public void EnableUpdateWhenOffscreen()
{
foreach (var smr in GetComponentsInChildren<SkinnedMeshRenderer>())
{
smr.updateWhenOffscreen = true;
}
}
void OnDestroy()
{
Debug.Log("UnityResourceDestroyer.OnDestroy");
foreach (var (key, x) in m_resources)
{
UnityObjectDestoyer.DestroyRuntimeOrEditor(x);
}
}
public void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
foreach (var (key, x) in m_resources.ToArray())
{
take(key, x);
m_resources.Remove((key, x));
}
}
public void Dispose()
{
UnityObjectDestoyer.DestroyRuntimeOrEditor(this.gameObject);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 93b3af59a4d8b704a883260f2fd40c44
guid: 423fb0cccbe420047ac28163cce68db4
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// Mesh, Material, Texture などを抱えておいて確実に破棄できるようにする
/// </summary>
public class UnityResourceDestroyer : MonoBehaviour
{
List<UnityEngine.Object> m_resources = new List<UnityEngine.Object>();
public IList<UnityEngine.Object> Resources => m_resources;
void OnDestroy()
{
Debug.Log("UnityResourceDestroyer.OnDestroy");
foreach (var x in Resources)
{
#if VRM_DEVELOP
Debug.Log($"Destroy: {x}");
#endif
Destroy(x);
}
}
public static Action<UnityEngine.Object> DestroyResource()
{
Action<UnityEngine.Object> des = (UnityEngine.Object o) => UnityEngine.Object.Destroy(o);
Action<UnityEngine.Object> desi = (UnityEngine.Object o) => UnityEngine.Object.DestroyImmediate(o);
Action<UnityEngine.Object> func = Application.isPlaying
? des
: desi
;
return func;
}
}
}

View File

@@ -93,27 +93,27 @@ namespace UniGLTF
{
try
{
loader.Load();
var loaded = loader.Load();
if (loaded == null)
{
Debug.LogWarning($"root is null: ${gltf}");
return;
}
if (Skip.Contains(gltf.Directory.Parent.Name))
{
// Export issue:
// skip
return;
}
Export(loaded.gameObject);
}
catch (Exception ex)
{
Message(gltf.FullName.Substring(subStrStart), ex);
}
if (Skip.Contains(gltf.Directory.Parent.Name))
{
// Export issue:
// skip
return;
}
if (loader.Root == null)
{
Debug.LogWarning($"root is null: ${gltf}");
return;
}
Export(loader.Root);
}
}

View File

@@ -120,9 +120,9 @@ namespace UniGLTF
// import
using (var context = new ImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
AssertAreEqual(go.transform, context.Root.transform);
AssertAreEqual(go.transform, loaded.transform);
}
}
@@ -557,16 +557,14 @@ namespace UniGLTF
parser.ParseJson(json, new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024])));
using (var context = new ImporterContext(parser))
using (var loaded = context.Load())
{
//Debug.LogFormat("{0}", context.Json);
context.Load();
var importedRed = context.Root.transform.GetChild(0);
var importedRed = loaded.transform.GetChild(0);
var importedRedMaterial = importedRed.GetComponent<Renderer>().sharedMaterial;
Assert.AreEqual("red", importedRedMaterial.name);
Assert.AreEqual(Color.red, importedRedMaterial.color);
var importedBlue = context.Root.transform.GetChild(1);
var importedBlue = loaded.transform.GetChild(1);
var importedBlueMaterial = importedBlue.GetComponent<Renderer>().sharedMaterial;
Assert.AreEqual("blue", importedBlueMaterial.name);
Assert.AreEqual(Color.blue, importedBlueMaterial.color);
@@ -579,15 +577,14 @@ namespace UniGLTF
parser.ParseJson(json, new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024])));
//Debug.LogFormat("{0}", context.Json);
using (var context = new ImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
var importedRed = context.Root.transform.GetChild(0);
var importedRed = loaded.transform.GetChild(0);
var importedRedMaterial = importedRed.GetComponent<Renderer>().sharedMaterial;
Assert.AreEqual("red", importedRedMaterial.name);
Assert.AreEqual(Color.red, importedRedMaterial.color);
var importedBlue = context.Root.transform.GetChild(1);
var importedBlue = loaded.transform.GetChild(1);
var importedBlueMaterial = importedBlue.GetComponent<Renderer>().sharedMaterial;
Assert.AreEqual("blue", importedBlueMaterial.name);
Assert.AreEqual(Color.blue, importedBlueMaterial.color);
@@ -633,13 +630,11 @@ namespace UniGLTF
parser.ParseJson(json, new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024])));
using (var context = new ImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
Assert.AreEqual(1, context.Root.transform.GetChildren().Count());
Assert.AreEqual(1, loaded.transform.GetChildren().Count());
{
var child = context.Root.transform.GetChild(0);
var child = loaded.transform.GetChild(0);
Assert.IsNull(child.GetSharedMesh());
}
}
@@ -700,18 +695,17 @@ namespace UniGLTF
parser.ParseJson(json, new SimpleStorage(new ArraySegment<byte>(new byte[1024 * 1024])));
using (var context = new ImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
Assert.AreEqual(2, context.Root.transform.GetChildren().Count());
Assert.AreEqual(2, loaded.transform.GetChildren().Count());
{
var child = context.Root.transform.GetChild(0);
var child = loaded.transform.GetChild(0);
Assert.IsNull(child.GetSharedMesh());
}
{
var child = context.Root.transform.GetChild(1);
var child = loaded.transform.GetChild(1);
Assert.IsNull(child.GetSharedMesh());
}
}

View File

@@ -47,152 +47,144 @@ namespace VRM.Samples
parser.ParseGlb(File.ReadAllBytes(path));
using (var context = new VRMImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
var destroyer = context.DisposeOnGameObjectDestroyed();
try
// mesh
{
// mesh
foreach (var renderer in loaded.GetComponentsInChildren<Renderer>())
{
foreach (var renderer in destroyer.GetComponentsInChildren<Renderer>())
Mesh mesh = default;
if (renderer is MeshRenderer)
{
Mesh mesh = default;
if (renderer is MeshRenderer)
var f = renderer.GetComponent<MeshFilter>();
mesh = f.sharedMesh;
}
else if (renderer is SkinnedMeshRenderer smr)
{
mesh = smr.sharedMesh;
}
var gltfMesh = parser.GLTF.meshes.Find(x => x.name == mesh.name);
Assert.AreEqual(gltfMesh.name, mesh.name);
// materials
foreach (var material in renderer.sharedMaterials)
{
var gltfMaterial = parser.GLTF.materials.Find(x => x.name == material.name);
Assert.AreEqual(gltfMaterial.name, material.name);
var materialIndex = parser.GLTF.materials.IndexOf(gltfMaterial);
var vrmMaterial = context.VRM.materialProperties[materialIndex];
// Debug.Log($"shaderName: '{vrmMaterial.shader}'");
if (vrmMaterial.shader == "VRM/MToon")
{
var f = renderer.GetComponent<MeshFilter>();
mesh = f.sharedMesh;
// MToon
// Debug.Log($"{material.name} is MToon");
foreach (var kv in vrmMaterial.textureProperties)
{
var texture = material.GetTexture(kv.Key);
// Debug.Log($"{kv.Key}: {texture}");
Assert.NotNull(texture);
}
}
else if (renderer is SkinnedMeshRenderer smr)
else if (glTF_KHR_materials_unlit.IsEnable(gltfMaterial))
{
mesh = smr.sharedMesh;
// Unlit
// Debug.Log($"{material.name} is unlit");
throw new NotImplementedException();
}
var gltfMesh = parser.GLTF.meshes.Find(x => x.name == mesh.name);
Assert.AreEqual(gltfMesh.name, mesh.name);
// materials
foreach (var material in renderer.sharedMaterials)
else
{
var gltfMaterial = parser.GLTF.materials.Find(x => x.name == material.name);
Assert.AreEqual(gltfMaterial.name, material.name);
var materialIndex = parser.GLTF.materials.IndexOf(gltfMaterial);
var vrmMaterial = context.VRM.materialProperties[materialIndex];
// Debug.Log($"shaderName: '{vrmMaterial.shader}'");
if (vrmMaterial.shader == "VRM/MToon")
{
// MToon
// Debug.Log($"{material.name} is MToon");
foreach (var kv in vrmMaterial.textureProperties)
{
var texture = material.GetTexture(kv.Key);
// Debug.Log($"{kv.Key}: {texture}");
Assert.NotNull(texture);
}
}
else if (glTF_KHR_materials_unlit.IsEnable(gltfMaterial))
{
// Unlit
// Debug.Log($"{material.name} is unlit");
throw new NotImplementedException();
}
else
{
// PBR
// Debug.Log($"{material.name} is PBR");
throw new NotImplementedException();
}
// PBR
// Debug.Log($"{material.name} is PBR");
throw new NotImplementedException();
}
}
}
// meta
{
var meta = destroyer.GetComponent<VRMMeta>();
}
// humanoid
{
var animator = destroyer.GetComponent<Animator>();
}
// blendshape
{
var blendshapeProxy = destroyer.GetComponent<VRMBlendShapeProxy>();
for (int i = 0; i < context.VRM.blendShapeMaster.blendShapeGroups.Count; ++i)
{
var gltfBlendShapeClip = context.VRM.blendShapeMaster.blendShapeGroups[i];
var unityBlendShapeClip = blendshapeProxy.BlendShapeAvatar.Clips[i];
Assert.AreEqual(Enum.Parse(typeof(BlendShapePreset), gltfBlendShapeClip.presetName, true), unityBlendShapeClip.Preset);
}
}
var importedJson = JsonParser.Parse(context.Json);
importedJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION, (f, x) => f.Value(x));
importedJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION, (f, x) => f.Value(x));
importedJson.SetValue("/scene", 0, (f, x) => f.Value(x));
importedJson.SetValue("/materials/*/doubleSided", false, (f, x) => f.Value(x));
//importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0);
//importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 });
importedJson.SetValue("/accessors/*/normalized", false, (f, x) => f.Value(x));
importedJson.RemoveValue(Utf8String.From("/nodes/*/extras"));
/*
importJson.SetValue("/bufferViews/12/byteStride", 4);
importJson.SetValue("/bufferViews/13/byteStride", 4);
importJson.SetValue("/bufferViews/14/byteStride", 4);
importJson.SetValue("/bufferViews/15/byteStride", 4);
importJson.SetValue("/bufferViews/22/byteStride", 4);
importJson.SetValue("/bufferViews/29/byteStride", 4);
importJson.SetValue("/bufferViews/45/byteStride", 4);
importJson.SetValue("/bufferViews/46/byteStride", 4);
importJson.SetValue("/bufferViews/47/byteStride", 4);
importJson.SetValue("/bufferViews/201/byteStride", 4);
importJson.SetValue("/bufferViews/202/byteStride", 4);
importJson.SetValue("/bufferViews/203/byteStride", 4);
importJson.SetValue("/bufferViews/204/byteStride", 4);
importJson.SetValue("/bufferViews/211/byteStride", 4);
importJson.SetValue("/bufferViews/212/byteStride", 4);
importJson.SetValue("/bufferViews/213/byteStride", 4);
importJson.SetValue("/bufferViews/214/byteStride", 4);
importJson.SetValue("/bufferViews/215/byteStride", 4);
importJson.SetValue("/bufferViews/243/byteStride", 4);
importJson.SetValue("/bufferViews/247/byteStride", 64);
importJson.SetValue("/bufferViews/248/byteStride", 64);
importJson.SetValue("/bufferViews/249/byteStride", 64);
importJson.SetValue("/bufferViews/250/byteStride", 64);
importJson.SetValue("/bufferViews/251/byteStride", 64);
importJson.SetValue("/bufferViews/252/byteStride", 64);
importJson.SetValue("/bufferViews/253/byteStride", 64);
*/
importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, context.Root, new EditorTextureSerializer());
// TODO: Check contents in JSON
/*var exportJson = */
JsonParser.Parse(vrm.ToJson());
// TODO: Check contents in JSON
/*var newExportedJson = */
// JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
/*
foreach (var kv in importJson.Diff(exportJson))
{
Debug.Log(kv);
}
Assert.AreEqual(importJson, exportJson);
*/
}
finally
// meta
{
UnityEngine.Object.DestroyImmediate(destroyer.gameObject);
var meta = loaded.GetComponent<VRMMeta>();
}
// humanoid
{
var animator = loaded.GetComponent<Animator>();
}
// blendshape
{
var blendshapeProxy = loaded.GetComponent<VRMBlendShapeProxy>();
for (int i = 0; i < context.VRM.blendShapeMaster.blendShapeGroups.Count; ++i)
{
var gltfBlendShapeClip = context.VRM.blendShapeMaster.blendShapeGroups[i];
var unityBlendShapeClip = blendshapeProxy.BlendShapeAvatar.Clips[i];
Assert.AreEqual(Enum.Parse(typeof(BlendShapePreset), gltfBlendShapeClip.presetName, true), unityBlendShapeClip.Preset);
}
}
var importedJson = JsonParser.Parse(context.Json);
importedJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION, (f, x) => f.Value(x));
importedJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION, (f, x) => f.Value(x));
importedJson.SetValue("/scene", 0, (f, x) => f.Value(x));
importedJson.SetValue("/materials/*/doubleSided", false, (f, x) => f.Value(x));
//importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0);
//importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 });
importedJson.SetValue("/accessors/*/normalized", false, (f, x) => f.Value(x));
importedJson.RemoveValue(Utf8String.From("/nodes/*/extras"));
/*
importJson.SetValue("/bufferViews/12/byteStride", 4);
importJson.SetValue("/bufferViews/13/byteStride", 4);
importJson.SetValue("/bufferViews/14/byteStride", 4);
importJson.SetValue("/bufferViews/15/byteStride", 4);
importJson.SetValue("/bufferViews/22/byteStride", 4);
importJson.SetValue("/bufferViews/29/byteStride", 4);
importJson.SetValue("/bufferViews/45/byteStride", 4);
importJson.SetValue("/bufferViews/46/byteStride", 4);
importJson.SetValue("/bufferViews/47/byteStride", 4);
importJson.SetValue("/bufferViews/201/byteStride", 4);
importJson.SetValue("/bufferViews/202/byteStride", 4);
importJson.SetValue("/bufferViews/203/byteStride", 4);
importJson.SetValue("/bufferViews/204/byteStride", 4);
importJson.SetValue("/bufferViews/211/byteStride", 4);
importJson.SetValue("/bufferViews/212/byteStride", 4);
importJson.SetValue("/bufferViews/213/byteStride", 4);
importJson.SetValue("/bufferViews/214/byteStride", 4);
importJson.SetValue("/bufferViews/215/byteStride", 4);
importJson.SetValue("/bufferViews/243/byteStride", 4);
importJson.SetValue("/bufferViews/247/byteStride", 64);
importJson.SetValue("/bufferViews/248/byteStride", 64);
importJson.SetValue("/bufferViews/249/byteStride", 64);
importJson.SetValue("/bufferViews/250/byteStride", 64);
importJson.SetValue("/bufferViews/251/byteStride", 64);
importJson.SetValue("/bufferViews/252/byteStride", 64);
importJson.SetValue("/bufferViews/253/byteStride", 64);
*/
importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
var vrm = VRMExporter.Export(UniGLTF.MeshExportSettings.Default, loaded.gameObject, new EditorTextureSerializer());
// TODO: Check contents in JSON
/*var exportJson = */
JsonParser.Parse(vrm.ToJson());
// TODO: Check contents in JSON
/*var newExportedJson = */
// JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
/*
foreach (var kv in importJson.Diff(exportJson))
{
Debug.Log(kv);
}
Assert.AreEqual(importJson, exportJson);
*/
}
}
@@ -204,10 +196,10 @@ namespace VRM.Samples
parser.ParseGlb(File.ReadAllBytes(path));
using (var context = new VRMImporterContext(parser))
using (var loaded = context.Load())
{
context.Load();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
foreach (var mesh in context.Meshes)
{
var src = mesh.Mesh;

View File

@@ -59,13 +59,12 @@ namespace VRM.Samples
Debug.LogFormat("meta: title:{0}", meta.Title);
// ParseしたJSONをシーンオブジェクトに変換していく
await context.LoadAsync();
var loaded = await context.LoadAsync();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
var destroyer = context.DisposeOnGameObjectDestroyed();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
OnLoaded(destroyer.gameObject);
OnLoaded(loaded.gameObject);
}
}

View File

@@ -97,16 +97,17 @@ namespace VRM.Samples
Debug.LogFormat("meta: title:{0}", meta.Title);
// ParseしたJSONをシーンオブジェクトに変換していく
var loaded = default(RuntimeGltfInstance);
if (m_loadAsync)
{
await context.LoadAsync();
loaded = await context.LoadAsync();
}
else
{
context.Load();
loaded = context.Load();
}
OnLoaded(context);
OnLoaded(loaded);
}
}
@@ -135,15 +136,16 @@ namespace VRM.Samples
parser.ParseGlb(bytes);
var context = new VRMImporterContext(parser);
var loaded = default(RuntimeGltfInstance);
if (m_loadAsync)
{
await context.LoadAsync();
loaded = await context.LoadAsync();
}
else
{
context.Load();
loaded = context.Load();
}
OnLoaded(context);
OnLoaded(loaded);
}
void LoadBVHClicked()
@@ -165,15 +167,14 @@ namespace VRM.Samples
#endif
}
void OnLoaded(VRMImporterContext context)
void OnLoaded(RuntimeGltfInstance loaded)
{
var root = context.Root;
var root = loaded.gameObject;
root.transform.SetParent(transform, false);
//メッシュを表示します
context.ShowMeshes();
context.DisposeOnGameObjectDestroyed();
loaded.ShowMeshes();
// add motion
var humanPoseTransfer = root.AddComponent<UniHumanoid.HumanPoseTransfer>();

View File

@@ -317,11 +317,10 @@ namespace VRM.Samples
using (var context = new VRMImporterContext(parser))
{
await m_texts.UpdateMetaAsync(context);
await context.LoadAsync();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
context.DisposeOnGameObjectDestroyed();
SetModel(context.Root);
var loaded = await context.LoadAsync();
loaded.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
SetModel(loaded.gameObject);
}
break;
}
@@ -333,11 +332,10 @@ namespace VRM.Samples
parser.ParseGlb(file);
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
context.DisposeOnGameObjectDestroyed();
SetModel(context.Root);
var loaded = context.Load();
loaded.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
SetModel(loaded.gameObject);
break;
}
@@ -348,11 +346,10 @@ namespace VRM.Samples
parser.ParsePath(path);
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
context.DisposeOnGameObjectDestroyed();
SetModel(context.Root);
var loaded = context.Load();
loaded.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
SetModel(loaded.gameObject);
break;
}

View File

@@ -108,61 +108,51 @@ namespace VRM
TextureExtractor.ExtractTextures(m_context.Parser, m_prefabPath.Parent.Child(dirName), m_context.TextureDescriptorGenerator, subAssets, (_x, _y) => { }, onTextureReloaded);
}
bool SaveAsAsset(UnityEngine.Object o)
void SaveAsAsset(SubAssetKey _, UnityEngine.Object o)
{
if (o is GameObject)
{
return false;
}
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o)))
{
// already exists. not dispose
#if VRM_DEVELOP
Debug.Log($"Loaded. skip: {o}");
// 来ない?
Debug.LogWarning($"{o} already exists. skip write");
#endif
return true;
return;
}
var assetPath = GetAssetPath(m_prefabPath, o);
if (assetPath.IsNull)
if (!assetPath.IsNull)
{
// not dispose
return true;
// アセットとして書き込む
assetPath.Parent.EnsureFolder();
assetPath.CreateAsset(o);
m_paths.Add(assetPath);
}
// アセットとして書き込む
assetPath.Parent.EnsureFolder();
assetPath.CreateAsset(o);
m_paths.Add(assetPath);
// 所有権が移動
return true;
}
public void SaveAsAsset()
public void SaveAsAsset(UniGLTF.RuntimeGltfInstance loaded)
{
m_context.ShowMeshes();
loaded.ShowMeshes();
//
// save sub assets
//
m_paths.Clear();
m_paths.Add(m_prefabPath);
m_context.TransferOwnership(SaveAsAsset);
loaded.TransferOwnership(SaveAsAsset);
var root = loaded.Root;
GameObject.DestroyImmediate(loaded);
// Create or update Main Asset
if (m_prefabPath.IsFileExists)
{
Debug.LogFormat("replace prefab: {0}", m_prefabPath);
var prefab = m_prefabPath.LoadAsset<GameObject>();
PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, m_prefabPath.Value, InteractionMode.AutomatedAction);
PrefabUtility.SaveAsPrefabAssetAndConnect(root, m_prefabPath.Value, InteractionMode.AutomatedAction);
}
else
{
Debug.LogFormat("create prefab: {0}", m_prefabPath);
PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, m_prefabPath.Value, InteractionMode.AutomatedAction);
PrefabUtility.SaveAsPrefabAssetAndConnect(root, m_prefabPath.Value, InteractionMode.AutomatedAction);
}
foreach (var x in m_paths)

View File

@@ -50,11 +50,10 @@ namespace VRM
using (var context = new VRMImporterContext(parser))
{
context.Load();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
context.DisposeOnGameObjectDestroyed();
Selection.activeGameObject = context.Root;
var loaded = context.Load();
loaded.EnableUpdateWhenOffscreen();
loaded.ShowMeshes();
Selection.activeGameObject = loaded.gameObject;
}
}
@@ -88,8 +87,8 @@ namespace VRM
{
VRMShaders.TextureImporterConfigurator.Configure(textureInfo, context.TextureFactory.ExternalTextures);
}
context.Load();
editor.SaveAsAsset();
var loaded = context.Load();
editor.SaveAsAsset(loaded);
}
};

View File

@@ -63,8 +63,8 @@ namespace VRM
{
VRMShaders.TextureImporterConfigurator.Configure(textureInfo, context.TextureFactory.ExternalTextures);
}
context.Load();
editor.SaveAsAsset();
var loaded = context.Load();
editor.SaveAsAsset(loaded);
}
};

View File

@@ -317,36 +317,30 @@ namespace VRM
return meta;
}
public override void TransferOwnership(Func<UnityEngine.Object, bool> take)
public override void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
// VRM-0 は SubAssetKey を使っていないので default で済ます
// VRM 固有のリソース(ScriptableObject)
if (take(HumanoidAvatar))
{
HumanoidAvatar = null;
}
take(default, HumanoidAvatar);
HumanoidAvatar = null;
if (take(Meta))
{
Meta = null;
}
take(default, Meta);
Meta = null;
if (take(AvatarDescription))
{
AvatarDescription = null;
}
take(default, AvatarDescription);
AvatarDescription = null;
foreach (var x in BlendShapeAvatar.Clips)
{
if (take(x))
take(default, x);
{
// do nothing
}
}
if (take(BlendShapeAvatar))
{
BlendShapeAvatar = null;
}
take(default, BlendShapeAvatar);
BlendShapeAvatar = null;
// GLTF のリソース
base.TransferOwnership(take);
@@ -354,28 +348,26 @@ namespace VRM
public override void Dispose()
{
Action<UnityEngine.Object> destroy = UnityResourceDestroyer.DestroyResource();
// VRM specific
if (HumanoidAvatar != null)
{
destroy(HumanoidAvatar);
UnityObjectDestoyer.DestroyRuntimeOrEditor(HumanoidAvatar);
}
if (Meta != null)
{
destroy(Meta);
UnityObjectDestoyer.DestroyRuntimeOrEditor(Meta);
}
if (AvatarDescription != null)
{
destroy(AvatarDescription);
UnityObjectDestoyer.DestroyRuntimeOrEditor(AvatarDescription);
}
if (BlendShapeAvatar != null)
{
foreach (var clip in BlendShapeAvatar.Clips)
{
destroy(clip);
UnityObjectDestoyer.DestroyRuntimeOrEditor(clip);
}
destroy(BlendShapeAvatar);
UnityObjectDestoyer.DestroyRuntimeOrEditor(BlendShapeAvatar);
}
base.Dispose();

View File

@@ -74,8 +74,7 @@ namespace VRM
{
using (var importer = new VRMImporterContext(parser))
{
importer.Load();
return importer.DisposeOnGameObjectDestroyed().gameObject;
return importer.Load().gameObject;
}
}
catch (Exception ex)

View File

@@ -24,11 +24,11 @@ namespace VRM
parser.ParsePath(AliciaPath);
byte[] bytes = default;
using (var loader = new VRMImporterContext(parser))
using (var loaded = loader.Load())
{
loader.Load();
loader.ShowMeshes();
loaded.ShowMeshes();
var go = loader.Root;
var go = loaded.gameObject;
var fp = go.GetComponent<VRMFirstPerson>();
GameObject.DestroyImmediate(go.GetComponent<VRMLookAtBoneApplyer>());
var lookAt = go.AddComponent<VRMLookAtBlendShapeApplyer>();
@@ -54,11 +54,11 @@ namespace VRM
byte[] bytes = default;
CurveMapper horizontalInner = default;
using (var loader = new VRMImporterContext(parser))
using (var loaded = loader.Load())
{
loader.Load();
loader.ShowMeshes();
loaded.ShowMeshes();
var go = loader.Root;
var go = loaded.gameObject;
var fp = go.GetComponent<VRMFirstPerson>();
var lookAt = go.GetComponent<VRMLookAtBoneApplyer>();
horizontalInner = lookAt.HorizontalInner;
@@ -71,11 +71,11 @@ namespace VRM
var parser2 = new GltfParser();
parser2.Parse(AliciaPath, bytes);
using (var loader = new VRMImporterContext(parser2))
using (var loaded = loader.Load())
{
loader.Load();
loader.ShowMeshes();
loaded.ShowMeshes();
var lookAt = loader.Root.GetComponent<VRMLookAtBoneApplyer>();
var lookAt = loaded.GetComponent<VRMLookAtBoneApplyer>();
Assert.AreEqual(horizontalInner.CurveXRangeDegree, lookAt.HorizontalInner.CurveXRangeDegree);
Assert.AreEqual(horizontalInner.CurveYRangeDegree, lookAt.HorizontalInner.CurveYRangeDegree);
}
@@ -89,11 +89,11 @@ namespace VRM
byte[] bytes = default;
CurveMapper horizontalInner = default;
using (var loader = new VRMImporterContext(parser))
using (var loaded = loader.Load())
{
loader.Load();
loader.ShowMeshes();
loaded.ShowMeshes();
var go = loader.Root;
var go = loaded.gameObject;
var fp = go.GetComponent<VRMFirstPerson>();
var lookAt = go.GetComponent<VRMLookAtBoneApplyer>();
horizontalInner = lookAt.HorizontalInner;
@@ -106,11 +106,11 @@ namespace VRM
var parser2 = new GltfParser();
parser2.Parse(AliciaPath, bytes);
using (var loader = new VRMImporterContext(parser2))
using (var loaded = loader.Load())
{
loader.Load();
loader.ShowMeshes();
loaded.ShowMeshes();
var lookAt = loader.Root.GetComponent<VRMLookAtBoneApplyer>();
var lookAt = loaded.GetComponent<VRMLookAtBoneApplyer>();
Assert.AreEqual(horizontalInner.CurveXRangeDegree, lookAt.HorizontalInner.CurveXRangeDegree);
Assert.AreEqual(horizontalInner.CurveYRangeDegree, lookAt.HorizontalInner.CurveYRangeDegree);
}

View File

@@ -26,9 +26,9 @@ namespace VRM
using (var loader = new VRMImporterContext(parser))
{
loader.Load();
loader.ShowMeshes();
return loader.DisposeOnGameObjectDestroyed().gameObject;
var loaded = loader.Load();
loaded.ShowMeshes();
return loaded.gameObject;
}
}

View File

@@ -308,18 +308,17 @@ namespace UniVRM10.Samples
{
case ".vrm":
{
if(!Vrm10Parser.TryParseOrMigrate(path, doMigrate: true, out Vrm10Parser.Result result, out string error))
if (!Vrm10Parser.TryParseOrMigrate(path, doMigrate: true, out Vrm10Parser.Result result, out string error))
{
Debug.LogError(error);
return;
}
using (var loader = new Vrm10Importer(result.Parser, result.Vrm))
{
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
var loaded = loader.Load();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
SetModel(loaded.gameObject);
}
break;
}
@@ -332,12 +331,10 @@ namespace UniVRM10.Samples
using (var loader = new UniGLTF.ImporterContext(parser))
{
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
loader.ShowMeshes();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
var loaded = loader.Load();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
SetModel(loaded.gameObject);
}
break;
}
@@ -350,12 +347,10 @@ namespace UniVRM10.Samples
using (var loader = new UniGLTF.ImporterContext(parser))
{
loader.Load();
loader.ShowMeshes();
loader.EnableUpdateWhenOffscreen();
loader.ShowMeshes();
var destroyer = loader.DisposeOnGameObjectDestroyed();
SetModel(destroyer.gameObject);
var loaded = loader.Load();
loaded.ShowMeshes();
loaded.EnableUpdateWhenOffscreen();
SetModel(loaded.gameObject);
}
break;
}

View File

@@ -15,18 +15,6 @@ namespace UniVRM10
{
public static class EditorVrm
{
static ExpressionKey CreateKey(UniGLTF.Extensions.VRMC_vrm.Expression expression)
{
if (expression.Preset == UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom)
{
return ExpressionKey.CreateCustom(expression.Name);
}
else
{
return ExpressionKey.CreateFromPreset(expression.Preset);
}
}
public static void OnGUI(ScriptedImporter importer, GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)
{
var hasExternal = importer.GetExternalObjectMap().Any(x => x.Value is VRM10MetaObject || x.Value is VRM10ExpressionAvatar || x.Value is VRM10Expression);
@@ -42,7 +30,7 @@ namespace UniVRM10
importer.DrawRemapGUI<VRM10MetaObject>(new SubAssetKey[] { VRM10MetaObject.SubAssetKey });
// expressions
importer.DrawRemapGUI<VRM10Expression>(vrm.Expressions.Select(x => CreateKey(x).SubAssetKey));
importer.DrawRemapGUI<VRM10Expression>(vrm.Expressions.Select(x => ExpressionKey.CreateFromVrm10(x).SubAssetKey));
if (GUILayout.Button("Clear"))
{

View File

@@ -42,20 +42,18 @@ namespace UniVRM10
VRMShaders.TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalTextures);
}
loader.Load();
loader.ShowMeshes();
var loaded = loader.Load();
loaded.ShowMeshes();
loader.TransferOwnership(o =>
loaded.TransferOwnership((key, o) =>
{
context.AddObjectToAsset(o.name, o);
if (o is GameObject)
{
// Root GameObject is main object
context.SetMainObject(loader.Root);
}
return true;
context.AddObjectToAsset(key.Name, o);
});
var root = loaded.Root;
GameObject.DestroyImmediate(loaded);
context.AddObjectToAsset(root.name, root);
context.SetMainObject(root);
}
}
}

View File

@@ -133,6 +133,18 @@ namespace UniVRM10
return new ExpressionKey(clip.Preset, clip.ExpressionName);
}
public static ExpressionKey CreateFromVrm10(UniGLTF.Extensions.VRMC_vrm.Expression expression)
{
if (expression.Preset == UniGLTF.Extensions.VRMC_vrm.ExpressionPreset.custom)
{
return ExpressionKey.CreateCustom(expression.Name);
}
else
{
return ExpressionKey.CreateFromPreset(expression.Preset);
}
}
public override string ToString()
{
return _id.Replace(UnknownPresetPrefix, "");

View File

@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UniGLTF;
using UnityEngine;
using VrmLib;
using VRMShaders;
@@ -16,7 +14,7 @@ namespace UniVRM10
/// </summary>
public class Vrm10Importer : UniGLTF.ImporterContext
{
readonly Model m_model;
readonly VrmLib.Model m_model;
UniGLTF.Extensions.VRMC_vrm.VRMC_vrm m_vrm;
@@ -54,61 +52,61 @@ namespace UniVRM10
// assign humanoid bones
if (m_vrm.Humanoid != null)
{
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Hips, HumanoidBones.hips);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftUpperLeg, HumanoidBones.leftUpperLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightUpperLeg, HumanoidBones.rightUpperLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLowerLeg, HumanoidBones.leftLowerLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLowerLeg, HumanoidBones.rightLowerLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftFoot, HumanoidBones.leftFoot);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightFoot, HumanoidBones.rightFoot);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Spine, HumanoidBones.spine);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Chest, HumanoidBones.chest);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Neck, HumanoidBones.neck);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Head, HumanoidBones.head);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftShoulder, HumanoidBones.leftShoulder);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightShoulder, HumanoidBones.rightShoulder);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftUpperArm, HumanoidBones.leftUpperArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightUpperArm, HumanoidBones.rightUpperArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLowerArm, HumanoidBones.leftLowerArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLowerArm, HumanoidBones.rightLowerArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftHand, HumanoidBones.leftHand);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightHand, HumanoidBones.rightHand);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftToes, HumanoidBones.leftToes);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightToes, HumanoidBones.rightToes);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftEye, HumanoidBones.leftEye);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightEye, HumanoidBones.rightEye);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Jaw, HumanoidBones.jaw);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbProximal, HumanoidBones.leftThumbProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbIntermediate, HumanoidBones.leftThumbIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbDistal, HumanoidBones.leftThumbDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexProximal, HumanoidBones.leftIndexProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexIntermediate, HumanoidBones.leftIndexIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexDistal, HumanoidBones.leftIndexDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleProximal, HumanoidBones.leftMiddleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleIntermediate, HumanoidBones.leftMiddleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleDistal, HumanoidBones.leftMiddleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingProximal, HumanoidBones.leftRingProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingIntermediate, HumanoidBones.leftRingIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingDistal, HumanoidBones.leftRingDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleProximal, HumanoidBones.leftLittleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleIntermediate, HumanoidBones.leftLittleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleDistal, HumanoidBones.leftLittleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbProximal, HumanoidBones.rightThumbProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbIntermediate, HumanoidBones.rightThumbIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbDistal, HumanoidBones.rightThumbDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexProximal, HumanoidBones.rightIndexProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexIntermediate, HumanoidBones.rightIndexIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexDistal, HumanoidBones.rightIndexDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleProximal, HumanoidBones.rightMiddleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleIntermediate, HumanoidBones.rightMiddleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleDistal, HumanoidBones.rightMiddleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingProximal, HumanoidBones.rightRingProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingIntermediate, HumanoidBones.rightRingIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingDistal, HumanoidBones.rightRingDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleProximal, HumanoidBones.rightLittleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleIntermediate, HumanoidBones.rightLittleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleDistal, HumanoidBones.rightLittleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.UpperChest, HumanoidBones.upperChest);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Hips, VrmLib.HumanoidBones.hips);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftUpperLeg, VrmLib.HumanoidBones.leftUpperLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightUpperLeg, VrmLib.HumanoidBones.rightUpperLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLowerLeg, VrmLib.HumanoidBones.leftLowerLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLowerLeg, VrmLib.HumanoidBones.rightLowerLeg);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftFoot, VrmLib.HumanoidBones.leftFoot);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightFoot, VrmLib.HumanoidBones.rightFoot);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Spine, VrmLib.HumanoidBones.spine);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Chest, VrmLib.HumanoidBones.chest);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Neck, VrmLib.HumanoidBones.neck);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Head, VrmLib.HumanoidBones.head);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftShoulder, VrmLib.HumanoidBones.leftShoulder);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightShoulder, VrmLib.HumanoidBones.rightShoulder);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftUpperArm, VrmLib.HumanoidBones.leftUpperArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightUpperArm, VrmLib.HumanoidBones.rightUpperArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLowerArm, VrmLib.HumanoidBones.leftLowerArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLowerArm, VrmLib.HumanoidBones.rightLowerArm);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftHand, VrmLib.HumanoidBones.leftHand);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightHand, VrmLib.HumanoidBones.rightHand);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftToes, VrmLib.HumanoidBones.leftToes);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightToes, VrmLib.HumanoidBones.rightToes);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftEye, VrmLib.HumanoidBones.leftEye);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightEye, VrmLib.HumanoidBones.rightEye);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.Jaw, VrmLib.HumanoidBones.jaw);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbProximal, VrmLib.HumanoidBones.leftThumbProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbIntermediate, VrmLib.HumanoidBones.leftThumbIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftThumbDistal, VrmLib.HumanoidBones.leftThumbDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexProximal, VrmLib.HumanoidBones.leftIndexProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexIntermediate, VrmLib.HumanoidBones.leftIndexIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftIndexDistal, VrmLib.HumanoidBones.leftIndexDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleProximal, VrmLib.HumanoidBones.leftMiddleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleIntermediate, VrmLib.HumanoidBones.leftMiddleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftMiddleDistal, VrmLib.HumanoidBones.leftMiddleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingProximal, VrmLib.HumanoidBones.leftRingProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingIntermediate, VrmLib.HumanoidBones.leftRingIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftRingDistal, VrmLib.HumanoidBones.leftRingDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleProximal, VrmLib.HumanoidBones.leftLittleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleIntermediate, VrmLib.HumanoidBones.leftLittleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.LeftLittleDistal, VrmLib.HumanoidBones.leftLittleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbProximal, VrmLib.HumanoidBones.rightThumbProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbIntermediate, VrmLib.HumanoidBones.rightThumbIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightThumbDistal, VrmLib.HumanoidBones.rightThumbDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexProximal, VrmLib.HumanoidBones.rightIndexProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexIntermediate, VrmLib.HumanoidBones.rightIndexIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightIndexDistal, VrmLib.HumanoidBones.rightIndexDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleProximal, VrmLib.HumanoidBones.rightMiddleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleIntermediate, VrmLib.HumanoidBones.rightMiddleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightMiddleDistal, VrmLib.HumanoidBones.rightMiddleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingProximal, VrmLib.HumanoidBones.rightRingProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingIntermediate, VrmLib.HumanoidBones.rightRingIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightRingDistal, VrmLib.HumanoidBones.rightRingDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleProximal, VrmLib.HumanoidBones.rightLittleProximal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleIntermediate, VrmLib.HumanoidBones.rightLittleIntermediate);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.RightLittleDistal, VrmLib.HumanoidBones.rightLittleDistal);
AssignHumanoid(m_model.Nodes, m_vrm.Humanoid.HumanBones.UpperChest, VrmLib.HumanoidBones.upperChest);
}
}
@@ -124,7 +122,7 @@ namespace UniVRM10
/// <returns></returns>
readonly ModelMap m_map = new ModelMap();
static void AssignHumanoid(List<Node> nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key)
static void AssignHumanoid(List<VrmLib.Node> nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key)
{
if (humanBone != null && humanBone.Node.HasValue)
{
@@ -620,28 +618,22 @@ namespace UniVRM10
return renderer;
}
public override void TransferOwnership(Func<UnityEngine.Object, bool> take)
public override void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
// VRM 固有のリソース(ScriptableObject)
if (take(m_humanoid))
{
m_humanoid = null;
}
take(SubAssetKey.Create(m_humanoid), m_humanoid);
m_humanoid = null;
if (m_meta != null)
{
if (take(m_meta))
{
m_meta = null;
}
take(VRM10MetaObject.SubAssetKey, m_meta);
m_meta = null;
}
foreach (var x in m_expressions)
{
if (take(x))
{
// do nothing
}
take(ExpressionKey.CreateFromClip(x).SubAssetKey, x);
// do nothing
}
m_expressions.Clear();
@@ -651,21 +643,19 @@ namespace UniVRM10
public override void Dispose()
{
Action<UnityEngine.Object> destroy = UnityResourceDestroyer.DestroyResource();
// VRM specific
if (m_humanoid != null)
{
destroy(m_humanoid);
UnityObjectDestoyer.DestroyRuntimeOrEditor(m_humanoid);
}
if (m_meta != null)
{
destroy(m_meta);
UnityObjectDestoyer.DestroyRuntimeOrEditor(m_meta);
}
foreach (var clip in m_expressions)
{
destroy(clip);
UnityObjectDestoyer.DestroyRuntimeOrEditor(clip);
}
base.Dispose();

View File

@@ -22,9 +22,9 @@ namespace UniVRM10.Sample
using (var loader = new Vrm10Importer(result.Parser, result.Vrm))
{
loader.Load();
loader.ShowMeshes();
return loader.DisposeOnGameObjectDestroyed().gameObject;
var loaded = loader.Load();
loaded.ShowMeshes();
return loaded.gameObject;
}
}

View File

@@ -31,7 +31,7 @@ namespace UniVRM10.Test
private (GameObject, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo>) ToUnity(byte[] bytes)
{
// Vrm => Model
if(!Vrm10Parser.TryParseOrMigrate("tpm.vrm", bytes, true, out Vrm10Parser.Result result, out string error))
if (!Vrm10Parser.TryParseOrMigrate("tpm.vrm", bytes, true, out Vrm10Parser.Result result, out string error))
{
throw new Exception();
}
@@ -44,9 +44,8 @@ namespace UniVRM10.Test
// Model => Unity
using (var loader = new Vrm10Importer(parser, vrm))
{
loader.Load();
loader.DisposeOnGameObjectDestroyed();
return (loader.Root, loader.MaterialFactory.Materials);
var loaded = loader.Load();
return (loaded.gameObject, loader.MaterialFactory.Materials);
}
}

View File

@@ -24,13 +24,13 @@ namespace UniVRM10.Test
{
using (var loader = new Vrm10Importer(parser, vrm))
{
loader.Load();
var loaded = loader.Load();
if (showMesh)
{
loader.ShowMeshes();
loaded.ShowMeshes();
}
loader.EnableUpdateWhenOffscreen();
return loader.DisposeOnGameObjectDestroyed().gameObject;
loaded.EnableUpdateWhenOffscreen();
return loaded.gameObject;
}
}

View File

@@ -0,0 +1,20 @@
using System;
namespace VRMShaders
{
public delegate void TakeResponsibilityForDestroyObjectFunc(SubAssetKey key, UnityEngine.Object obj);
/// <summary>
/// UnityObjectを破棄する責務。
///
/// この interface を実装するクラスは、利用後に破棄すべき UnityObject を保持する可能性があるので
/// Dispose により解放すること。
///
/// TransferOwnership により、破棄責任を移譲することができる。
///
/// </summary>
public interface IResponsibilityForDestroyObjects : IDisposable
{
void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93ab2216c7e8c684d84873bd2ae72c6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace VRMShaders
{
public static class KeyValuePariExtensions
{
public static void Deconstruct<T, U>(this KeyValuePair<T, U> pair, out T key, out U value)
{
key = pair.Key;
value = pair.Value;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7dd6ef3302d21eb4b83c4f8f2c1e47cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
@@ -9,7 +8,7 @@ namespace VRMShaders
{
public delegate Task<Texture> GetTextureAsyncFunc(TextureDescriptor texDesc);
public class MaterialFactory : IDisposable
public class MaterialFactory : IResponsibilityForDestroyObjects
{
private readonly IReadOnlyDictionary<SubAssetKey, Material> m_externalMap;
@@ -30,13 +29,15 @@ namespace VRMShaders
public struct MaterialLoadInfo
{
public SubAssetKey Key;
public readonly Material Asset;
public readonly bool UseExternal;
public bool IsSubAsset => !UseExternal;
public MaterialLoadInfo(Material asset, bool useExternal)
public MaterialLoadInfo(SubAssetKey key, Material asset, bool useExternal)
{
Key = key;
Asset = asset;
UseExternal = useExternal;
}
@@ -64,7 +65,7 @@ namespace VRMShaders
#if VRM_DEVELOP
// Debug.Log($"Destroy {x.Asset}");
#endif
UnityEngine.Object.DestroyImmediate(x.Asset, false);
UnityObjectDestoyer.DestroyRuntimeOrEditor(x.Asset);
}
}
}
@@ -79,24 +80,17 @@ namespace VRMShaders
///
/// </summary>
/// <param name="take"></param>
public void TransferOwnership(Func<UnityEngine.Object, bool> take)
public void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
var list = new List<Material>();
foreach (var x in m_materials)
foreach (var x in m_materials.ToArray())
{
if (!x.UseExternal)
{
// 外部の '.asset' からロードしていない
if (take(x.Asset))
{
list.Add(x.Asset);
}
take(x.Key, x.Asset);
m_materials.Remove(x);
}
}
foreach (var x in list)
{
Remove(x);
}
}
public Material GetMaterial(int index)
@@ -110,7 +104,7 @@ namespace VRMShaders
{
if (m_externalMap.TryGetValue(matDesc.SubAssetKey, out Material material))
{
m_materials.Add(new MaterialLoadInfo(material, true));
m_materials.Add(new MaterialLoadInfo(matDesc.SubAssetKey, material, true));
return material;
}
@@ -174,7 +168,7 @@ namespace VRMShaders
action(material);
}
m_materials.Add(new MaterialLoadInfo(material, false));
m_materials.Add(new MaterialLoadInfo(matDesc.SubAssetKey, material, false));
return material;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace VRMShaders
@@ -7,15 +6,16 @@ namespace VRMShaders
/// <summary>
/// UnityEditor.Experimental.AssetImporter.SourceAssetIdentifier に対応する
///
/// * SourceAssetIdentifier が UnityEditor なので、 Runtime でも使えるように
/// * SourceAssetIdentifier が UnityEditor なので、 Runtime でも使えるように作成
/// * Type が違うが Name が同じだと警告が出る。例えば、Material と 同じ名前の Texture がある場合。
/// Identifier uniqueness violation: 'Alicia_body'. Scripted Importers do not guarantee that subsequent imports of this asset will properly re-link to these targets.
/// * なので、SourceAssetIdentifier は、$"{Type.Name}.{UnityObject.name}" のように強制的に Unique にするのが良さそう
/// * 一方で、Extract したファイル名に $"{Type.Name}." が付属するのは煩わしいのでこれは無しにしたい。
///
/// public void AddRemap(SourceAssetIdentifier identifier, UnityEngine.Object externalObject);
///
/// の呼び出し時に、identifier.name と externalObject.name が同じでない運用にしてみる。
/// scriptedImporter.GetExternalObjectMap
///
/// に関係する。
///
/// SubAssetKey を新しく作る場所は集約して、不一致が起こらないように注意する
///
/// </summary>
public readonly struct SubAssetKey : IEquatable<SubAssetKey>
@@ -48,6 +48,11 @@ namespace VRMShaders
Name = obj.name;
}
public static SubAssetKey Create<T>(T obj) where T : UnityEngine.Object
{
return new SubAssetKey(typeof(T), obj.name);
}
public SubAssetKey(Type type, string name)
{
if (type == null || string.IsNullOrEmpty(name))

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace VRMShaders
{
public class TextureFactory : IDisposable
public class TextureFactory : IResponsibilityForDestroyObjects
{
private readonly ITextureDeserializer _textureDeserializer;
private readonly IReadOnlyDictionary<SubAssetKey, Texture> _externalMap;
@@ -33,7 +33,7 @@ namespace VRMShaders
{
foreach (var kv in _temporaryTextures)
{
DestroyResource(kv.Value);
UnityObjectDestoyer.DestroyRuntimeOrEditor(kv.Value);
}
_temporaryTextures.Clear();
_textureCache.Clear();
@@ -43,20 +43,12 @@ namespace VRMShaders
/// 所有権(Dispose権)を移譲する
/// </summary>
/// <param name="take"></param>
public void TransferOwnership(Func<UnityEngine.Object, bool> take)
public void TransferOwnership(TakeResponsibilityForDestroyObjectFunc take)
{
var transferredAssets = new HashSet<SubAssetKey>();
foreach (var x in _textureCache)
foreach (var (k, v) in _textureCache.ToArray())
{
if (take(x.Value))
{
transferredAssets.Add(x.Key);
}
}
foreach (var key in transferredAssets)
{
_textureCache.Remove(key);
take(k, v);
_textureCache.Remove(k);
}
}
@@ -81,80 +73,68 @@ namespace VRMShaders
switch (texDesc.TextureType)
{
case TextureImportTypes.NormalMap:
{
// no conversion. Unity's normal map is same with glTF's.
//
// > contrary to Unitys usual convention of using Y as “up”
// https://docs.unity3d.com/2018.4/Documentation/Manual/StandardShaderMaterialParameterNormalMap.html
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
{
// no conversion. Unity's normal map is same with glTF's.
//
// > contrary to Unitys usual convention of using Y as “up”
// https://docs.unity3d.com/2018.4/Documentation/Manual/StandardShaderMaterialParameterNormalMap.html
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
case TextureImportTypes.StandardMap:
{
Texture2D metallicRoughnessTexture = default;
Texture2D occlusionTexture = default;
if (texDesc.Index0 != null)
{
var data0 = await texDesc.Index0();
metallicRoughnessTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
}
if (texDesc.Index1 != null)
{
var data1 = await texDesc.Index1();
occlusionTexture = await _textureDeserializer.LoadTextureAsync(data1, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
}
Texture2D metallicRoughnessTexture = default;
Texture2D occlusionTexture = default;
var combinedTexture = OcclusionMetallicRoughnessConverter.Import(metallicRoughnessTexture,
texDesc.MetallicFactor, texDesc.RoughnessFactor, occlusionTexture);
combinedTexture.name = subAssetKey.Name;
combinedTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, combinedTexture);
DestroyResource(metallicRoughnessTexture);
DestroyResource(occlusionTexture);
return combinedTexture;
}
if (texDesc.Index0 != null)
{
var data0 = await texDesc.Index0();
metallicRoughnessTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
}
if (texDesc.Index1 != null)
{
var data1 = await texDesc.Index1();
occlusionTexture = await _textureDeserializer.LoadTextureAsync(data1, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
}
var combinedTexture = OcclusionMetallicRoughnessConverter.Import(metallicRoughnessTexture,
texDesc.MetallicFactor, texDesc.RoughnessFactor, occlusionTexture);
combinedTexture.name = subAssetKey.Name;
combinedTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, combinedTexture);
UnityObjectDestoyer.DestroyRuntimeOrEditor(metallicRoughnessTexture);
UnityObjectDestoyer.DestroyRuntimeOrEditor(occlusionTexture);
return combinedTexture;
}
case TextureImportTypes.sRGB:
{
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.sRGB);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
{
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.sRGB);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
case TextureImportTypes.Linear:
{
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
{
var data0 = await texDesc.Index0();
var rawTexture = await _textureDeserializer.LoadTextureAsync(data0, texDesc.Sampler.EnableMipMap, ColorSpace.Linear);
rawTexture.name = subAssetKey.Name;
rawTexture.SetSampler(texDesc.Sampler);
_textureCache.Add(subAssetKey, rawTexture);
return rawTexture;
}
default:
throw new ArgumentOutOfRangeException();
}
throw new NotImplementedException();
}
private static void DestroyResource(UnityEngine.Object o)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(o);
}
else
{
UnityEngine.Object.DestroyImmediate(o);
}
}
}
}

View File

@@ -0,0 +1,19 @@
using UnityEngine;
namespace VRMShaders
{
public static class UnityObjectDestoyer
{
public static void DestroyRuntimeOrEditor(UnityEngine.Object o)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(o);
}
else
{
UnityEngine.Object.DestroyImmediate(o);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b4d1043455aa2c489e9ad8250a80fc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: