Merge pull request #760 from ousttrue/feature/destroy_on_destroy

Feature/destroy on destroy
This commit is contained in:
ousttrue 2021-03-01 14:39:58 +09:00 committed by GitHub
commit 47853d3a7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 676 additions and 477 deletions

View File

@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// Editor で Asset 化する場合専用
///
/// GameObject を prefab 化するので、prefab の元になった GameObject は破棄対象となる。
///
/// </summary>
public class EditorImporterContext : IDisposable
{
ImporterContext m_context;
public EditorImporterContext(ImporterContext context)
{
m_context = context;
}
public void Dispose()
{
m_context.Dispose();
if (m_context.Root != null)
{
// Destroy the GameObject that became the basis of Prefab
GameObject.DestroyImmediate(m_context.Root);
}
}
public virtual IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
{
foreach (var x in m_context.TextureFactory.ObjectsForSubAsset())
{
yield return x;
}
foreach (var x in m_context.MaterialFactory.ObjectsForSubAsset())
{
yield return x;
}
foreach (var x in m_context.Meshes) { yield return x.Mesh; }
foreach (var x in m_context.AnimationClips) { yield return x; }
}
/// <summary>
/// Destroy assets that created ImporterContext. This function is clean up for importer error.
/// </summary>
public virtual void EditorDestroyRootAndAssets()
{
// Remove hierarchy
if (m_context.Root != null) GameObject.DestroyImmediate(m_context.Root);
// Remove resources. materials, textures meshes etc...
foreach (var o in ObjectsForSubAsset())
{
UnityEngine.Object.DestroyImmediate(o, true);
}
}
public virtual UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o, bool meshAsSubAsset)
{
if (o is Material)
{
var materialDir = prefabPath.GetAssetFolder(".Materials");
var materialPath = materialDir.Child(o.name.EscapeFilePath() + ".asset");
return materialPath;
}
else if (o is Texture2D)
{
var textureDir = prefabPath.GetAssetFolder(".Textures");
var texturePath = textureDir.Child(o.name.EscapeFilePath() + ".asset");
return texturePath;
}
else if (o is Mesh && !meshAsSubAsset)
{
var meshDir = prefabPath.GetAssetFolder(".Meshes");
var meshPath = meshDir.Child(o.name.EscapeFilePath() + ".asset");
return meshPath;
}
else
{
return default(UnityPath);
}
}
public virtual bool AvoidOverwriteAndLoad(UnityPath assetPath, UnityEngine.Object o)
{
if (o is Material)
{
var loaded = assetPath.LoadAsset<Material>();
// replace component reference
foreach (var mesh in m_context.Meshes)
{
foreach (var r in mesh.Renderers)
{
for (int i = 0; i < r.sharedMaterials.Length; ++i)
{
if (r.sharedMaterials.Contains(o))
{
r.sharedMaterials = r.sharedMaterials.Select(x => x == o ? loaded : x).ToArray();
}
}
}
}
return true;
}
return false;
}
public void SaveAsAsset(UnityPath prefabPath, bool meshAsSubAsset = false)
{
m_context.ShowMeshes();
//var prefabPath = PrefabPath;
if (prefabPath.IsFileExists)
{
// clear SubAssets
foreach (var x in prefabPath.GetSubAssets().Where(x => !(x is GameObject) && !(x is Component)))
{
GameObject.DestroyImmediate(x, true);
}
}
//
// save sub assets
//
var paths = new List<UnityPath>(){
prefabPath
};
foreach (var o in ObjectsForSubAsset())
{
if (o == null) continue;
var assetPath = GetAssetPath(prefabPath, o, meshAsSubAsset);
if (!assetPath.IsNull)
{
if (assetPath.IsFileExists)
{
if (AvoidOverwriteAndLoad(assetPath, o))
{
// 上書きせずに既存のアセットからロードして置き換えた
continue;
}
}
// アセットとして書き込む
assetPath.Parent.EnsureFolder();
assetPath.CreateAsset(o);
paths.Add(assetPath);
}
else
{
// save as subasset
prefabPath.AddObjectToAsset(o);
}
}
// Create or update Main Asset
if (prefabPath.IsFileExists)
{
Debug.LogFormat("replace prefab: {0}", prefabPath);
var prefab = prefabPath.LoadAsset<GameObject>();
#if UNITY_2018_3_OR_NEWER
PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, prefabPath.Value, InteractionMode.AutomatedAction);
#else
PrefabUtility.ReplacePrefab(Root, prefab, ReplacePrefabOptions.ReplaceNameBased);
#endif
}
else
{
Debug.LogFormat("create prefab: {0}", prefabPath);
#if UNITY_2018_3_OR_NEWER
PrefabUtility.SaveAsPrefabAssetAndConnect(m_context.Root, prefabPath.Value, InteractionMode.AutomatedAction);
#else
PrefabUtility.CreatePrefab(prefabPath.Value, Root);
#endif
}
foreach (var x in paths)
{
x.ImportAsset();
}
}
/// <summary>
/// Extract images from glb or gltf out of Assets folder.
/// </summary>
/// <param name="prefabPath"></param>
public void ExtractImages(UnityPath prefabPath)
{
var prefabParentDir = prefabPath.Parent;
// glb buffer
var folder = prefabPath.GetAssetFolder(".Textures");
//
// https://answers.unity.com/questions/647615/how-to-update-import-settings-for-newly-created-as.html
//
int created = 0;
for (int i = 0; i < m_context.GLTF.textures.Count; ++i)
{
folder.EnsureFolder();
var gltfTexture = m_context.GLTF.textures[i];
var gltfImage = m_context.GLTF.images[gltfTexture.source];
var src = m_context.Storage.GetPath(gltfImage.uri);
if (UnityPath.FromFullpath(src).IsUnderAssetsFolder)
{
// asset is exists.
}
else
{
var byteSegment = m_context.GLTF.GetImageBytes(m_context.Storage, gltfTexture.source);
var textureName = gltfTexture.name;
// path
var dst = folder.Child(textureName + gltfImage.GetExt());
File.WriteAllBytes(dst.FullPath, byteSegment.ToArray());
dst.ImportAsset();
// make relative path from PrefabParentDir
gltfImage.uri = dst.Value.Substring(prefabParentDir.Value.Length + 1);
++created;
}
}
if (created > 0)
{
AssetDatabase.Refresh();
}
// texture will load from assets
m_context.TextureFactory.ImageBaseDir = prefabParentDir;
}
}
}

View File

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

View File

@ -2,11 +2,7 @@
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UniGLTF.AltTask;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UniGLTF
{
@ -217,278 +213,56 @@ namespace UniGLTF
public List<AnimationClip> AnimationClips = new List<AnimationClip>();
#endregion
protected virtual IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
/// <summary>
/// Importに使った一時オブジェクトを破棄する
///
/// 変換のあるテクスチャで、変換前のもの
/// normal, occlusion, metallicRoughness
/// </summary>
public virtual void Dispose()
{
foreach (var x in TextureFactory.ObjectsForSubAsset())
foreach (var x in m_textureFactory.Textures)
{
yield return x;
}
foreach (var x in MaterialFactory.ObjectsForSubAsset())
{
yield return x;
}
foreach (var x in Meshes) { yield return x.Mesh; }
foreach (var x in AnimationClips) { yield return x; }
}
#if UNITY_EDITOR
#region Assets
public bool MeshAsSubAsset = false;
protected virtual UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o)
{
if (o is Material)
{
var materialDir = prefabPath.GetAssetFolder(".Materials");
var materialPath = materialDir.Child(o.name.EscapeFilePath() + ".asset");
return materialPath;
}
else if (o is Texture2D)
{
var textureDir = prefabPath.GetAssetFolder(".Textures");
var texturePath = textureDir.Child(o.name.EscapeFilePath() + ".asset");
return texturePath;
}
else if (o is Mesh && !MeshAsSubAsset)
{
var meshDir = prefabPath.GetAssetFolder(".Meshes");
var meshPath = meshDir.Child(o.name.EscapeFilePath() + ".asset");
return meshPath;
}
else
{
return default(UnityPath);
}
}
public virtual bool AvoidOverwriteAndLoad(UnityPath assetPath, UnityEngine.Object o)
{
if (o is Material)
{
var loaded = assetPath.LoadAsset<Material>();
// replace component reference
foreach (var mesh in Meshes)
if (!x.IsUsed)
{
foreach (var r in mesh.Renderers)
{
for (int i = 0; i < r.sharedMaterials.Length; ++i)
{
if (r.sharedMaterials.Contains(o))
{
r.sharedMaterials = r.sharedMaterials.Select(x => x == o ? loaded : x).ToArray();
}
}
}
// Destroy temporary texture object
UnityEngine.Object.Destroy(x.Texture);
}
return true;
}
return false;
}
public void SaveAsAsset(UnityPath prefabPath)
{
ShowMeshes();
//var prefabPath = PrefabPath;
if (prefabPath.IsFileExists)
{
// clear SubAssets
foreach (var x in prefabPath.GetSubAssets().Where(x => !(x is GameObject) && !(x is Component)))
{
GameObject.DestroyImmediate(x, true);
}
}
//
// save sub assets
//
var paths = new List<UnityPath>(){
prefabPath
};
foreach (var o in ObjectsForSubAsset())
{
if (o == null) continue;
var assetPath = GetAssetPath(prefabPath, o);
if (!assetPath.IsNull)
{
if (assetPath.IsFileExists)
{
if (AvoidOverwriteAndLoad(assetPath, o))
{
// 上書きせずに既存のアセットからロードして置き換えた
continue;
}
}
// アセットとして書き込む
assetPath.Parent.EnsureFolder();
assetPath.CreateAsset(o);
paths.Add(assetPath);
}
else
{
// save as subasset
prefabPath.AddObjectToAsset(o);
}
}
// Create or update Main Asset
if (prefabPath.IsFileExists)
{
Debug.LogFormat("replace prefab: {0}", prefabPath);
var prefab = prefabPath.LoadAsset<GameObject>();
#if UNITY_2018_3_OR_NEWER
PrefabUtility.SaveAsPrefabAssetAndConnect(Root, prefabPath.Value, InteractionMode.AutomatedAction);
#else
PrefabUtility.ReplacePrefab(Root, prefab, ReplacePrefabOptions.ReplaceNameBased);
#endif
}
else
{
Debug.LogFormat("create prefab: {0}", prefabPath);
#if UNITY_2018_3_OR_NEWER
PrefabUtility.SaveAsPrefabAssetAndConnect(Root, prefabPath.Value, InteractionMode.AutomatedAction);
#else
PrefabUtility.CreatePrefab(prefabPath.Value, Root);
#endif
}
foreach (var x in paths)
{
x.ImportAsset();
}
}
/// <summary>
/// Extract images from glb or gltf out of Assets folder.
/// Root ヒエラルキーで使っているリソース
/// </summary>
/// <param name="prefabPath"></param>
public void ExtractImages(UnityPath prefabPath)
/// <returns></returns>
public virtual IEnumerable<UnityEngine.Object> ModelOwnResources()
{
var prefabParentDir = prefabPath.Parent;
// glb buffer
var folder = prefabPath.GetAssetFolder(".Textures");
//
// https://answers.unity.com/questions/647615/how-to-update-import-settings-for-newly-created-as.html
//
int created = 0;
for (int i = 0; i < GLTF.textures.Count; ++i)
foreach (var mesh in Meshes)
{
folder.EnsureFolder();
var gltfTexture = GLTF.textures[i];
var gltfImage = GLTF.images[gltfTexture.source];
var src = Storage.GetPath(gltfImage.uri);
if (UnityPath.FromFullpath(src).IsUnderAssetsFolder)
{
// asset is exists.
}
else
{
var byteSegment = GLTF.GetImageBytes(Storage, gltfTexture.source);
var textureName = gltfTexture.name;
// path
var dst = folder.Child(textureName + gltfImage.GetExt());
File.WriteAllBytes(dst.FullPath, byteSegment.ToArray());
dst.ImportAsset();
// make relative path from PrefabParentDir
gltfImage.uri = dst.Value.Substring(prefabParentDir.Value.Length + 1);
++created;
}
yield return mesh.Mesh;
}
if (created > 0)
foreach (var material in m_materialFactory.Materials)
{
AssetDatabase.Refresh();
yield return material.Asset;
}
// texture will load from assets
m_textureFactory.ImageBaseDir = prefabParentDir;
}
#endregion
#endif
/// <summary>
/// This function is used for clean up after create assets.
/// </summary>
/// <param name="destroySubAssets">Ambiguous arguments</param>
[Obsolete("Use Dispose for runtime loader resource management")]
public void Destroy(bool destroySubAssets)
{
if (Root != null) GameObject.DestroyImmediate(Root);
if (destroySubAssets)
foreach (var texture in m_textureFactory.Textures)
{
#if UNITY_EDITOR
foreach (var o in ObjectsForSubAsset())
{
UnityEngine.Object.DestroyImmediate(o, true);
}
#endif
yield return texture.Texture;
}
foreach (var animation in AnimationClips)
{
yield return animation;
}
}
public void Dispose()
public UnityResourceDestroyer DisposeOnGameObjectDestroyed()
{
DestroyRootAndResources();
}
/// <summary>
/// Destroy resources that created ImporterContext for runtime load.
/// </summary>
public void DestroyRootAndResources()
{
if (!Application.isPlaying)
var destroyer = Root.AddComponent<UnityResourceDestroyer>();
foreach (var x in ModelOwnResources())
{
Debug.LogWarningFormat("Dispose called in editor mode. This function is for runtime");
destroyer.Resources.Add(x);
}
// Remove hierarchy
if (Root != null) GameObject.Destroy(Root);
// Remove resources. materials, textures meshes etc...
foreach (var x in Meshes)
{
UnityEngine.Object.DestroyImmediate(x.Mesh, true);
}
foreach (var x in AnimationClips)
{
UnityEngine.Object.DestroyImmediate(x, true);
}
MaterialFactory.Dispose();
TextureFactory.Dispose();
return destroyer;
}
#if UNITY_EDITOR
/// <summary>
/// Destroy the GameObject that became the basis of Prefab
/// </summary>
public void EditorDestroyRoot()
{
if (Root != null) GameObject.DestroyImmediate(Root);
}
/// <summary>
/// Destroy assets that created ImporterContext. This function is clean up for importer error.
/// </summary>
public void EditorDestroyRootAndAssets()
{
// Remove hierarchy
if (Root != null) GameObject.DestroyImmediate(Root);
// Remove resources. materials, textures meshes etc...
foreach (var o in ObjectsForSubAsset())
{
UnityEngine.Object.DestroyImmediate(o, true);
}
}
#endif
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 5d2d27884d6c4780b08c745e5cc5c5b5
timeCreated: 1537261040

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 79721770f23ba6748abc1720cd99ad74
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using UnityEngine;
namespace UniGLTF
{
public interface ITextureConverter
{
Texture2D GetImportTexture(Texture2D texture);
Texture2D GetExportTexture(Texture2D texture);
}
}

View File

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

View File

@ -0,0 +1,67 @@
using UnityEngine;
namespace UniGLTF
{
public class MetallicRoughnessConverter : ITextureConverter
{
private float _smoothnessOrRoughness;
public MetallicRoughnessConverter(float smoothnessOrRoughness)
{
_smoothnessOrRoughness = smoothnessOrRoughness;
}
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Export, null);
return converted;
}
public Color32 Import(Color32 src)
{
// Roughness(glTF): dst.g -> Smoothness(Unity): src.a (with conversion)
// Metallic(glTF) : dst.b -> Metallic(Unity) : src.r
var pixelRoughnessFactor = (src.g * _smoothnessOrRoughness) / 255.0f; // roughness
var pixelSmoothness = 1.0f - Mathf.Sqrt(pixelRoughnessFactor);
return new Color32
{
r = src.b,
g = 0,
b = 0,
// Bake roughness values into a texture.
// See: https://github.com/dwango/UniVRM/issues/212.
a = (byte)Mathf.Clamp(pixelSmoothness * 255, 0, 255),
};
}
public Color32 Export(Color32 src)
{
// Smoothness(Unity): src.a -> Roughness(glTF): dst.g (with conversion)
// Metallic(Unity) : src.r -> Metallic(glTF) : dst.b
var pixelSmoothness = (src.a * _smoothnessOrRoughness) / 255.0f; // smoothness
// https://blogs.unity3d.com/jp/2016/01/25/ggx-in-unity-5-3/
var pixelRoughnessFactorSqrt = (1.0f - pixelSmoothness);
var pixelRoughnessFactor = pixelRoughnessFactorSqrt * pixelRoughnessFactorSqrt;
return new Color32
{
r = 0,
// Bake smoothness values into a texture.
// See: https://github.com/dwango/UniVRM/issues/212.
g = (byte)Mathf.Clamp(pixelRoughnessFactor * 255, 0, 255),
b = src.r,
a = 255,
};
}
}
}

View File

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

View File

@ -0,0 +1,46 @@
using UnityEngine;
namespace UniGLTF
{
public class NormalConverter : ITextureConverter
{
private Material m_decoder;
private Material GetDecoder()
{
if (m_decoder == null)
{
m_decoder = new Material(Shader.Find("UniGLTF/NormalMapDecoder"));
}
return m_decoder;
}
private Material m_encoder;
private Material GetEncoder()
{
if (m_encoder == null)
{
m_encoder = new Material(Shader.Find("UniGLTF/NormalMapEncoder"));
}
return m_encoder;
}
// GLTF data to Unity texture
// ConvertToNormalValueFromRawColorWhenCompressionIsRequired
public Texture2D GetImportTexture(Texture2D texture)
{
var mat = GetEncoder();
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
return converted;
}
// Unity texture to GLTF data
// ConvertToRawColorWhenNormalValueIsCompressed
public Texture2D GetExportTexture(Texture2D texture)
{
var mat = GetDecoder();
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
return converted;
}
}
}

View File

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

View File

@ -0,0 +1,42 @@
using UnityEngine;
namespace UniGLTF
{
public class OcclusionConverter : ITextureConverter
{
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Export, null);
return converted;
}
public Color32 Import(Color32 src)
{
return new Color32
{
r = 0,
g = src.r,
b = 0,
a = 255,
};
}
public Color32 Export(Color32 src)
{
return new Color32
{
r = src.g,
g = 0,
b = 0,
a = 255,
};
}
}
}

View File

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

View File

@ -9,11 +9,6 @@ using UnityEditor;
namespace UniGLTF
{
public interface ITextureConverter
{
Texture2D GetImportTexture(Texture2D texture);
Texture2D GetExportTexture(Texture2D texture);
}
public static class TextureConverter
{
@ -176,144 +171,6 @@ namespace UniGLTF
}
}
public class MetallicRoughnessConverter : ITextureConverter
{
private float _smoothnessOrRoughness;
public MetallicRoughnessConverter(float smoothnessOrRoughness)
{
_smoothnessOrRoughness = smoothnessOrRoughness;
}
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Metallic, Export, null);
return converted;
}
public Color32 Import(Color32 src)
{
// Roughness(glTF): dst.g -> Smoothness(Unity): src.a (with conversion)
// Metallic(glTF) : dst.b -> Metallic(Unity) : src.r
var pixelRoughnessFactor = (src.g * _smoothnessOrRoughness) / 255.0f; // roughness
var pixelSmoothness = 1.0f - Mathf.Sqrt(pixelRoughnessFactor);
return new Color32
{
r = src.b,
g = 0,
b = 0,
// Bake roughness values into a texture.
// See: https://github.com/dwango/UniVRM/issues/212.
a = (byte)Mathf.Clamp(pixelSmoothness * 255, 0, 255),
};
}
public Color32 Export(Color32 src)
{
// Smoothness(Unity): src.a -> Roughness(glTF): dst.g (with conversion)
// Metallic(Unity) : src.r -> Metallic(glTF) : dst.b
var pixelSmoothness = (src.a * _smoothnessOrRoughness) / 255.0f; // smoothness
// https://blogs.unity3d.com/jp/2016/01/25/ggx-in-unity-5-3/
var pixelRoughnessFactorSqrt = (1.0f - pixelSmoothness);
var pixelRoughnessFactor = pixelRoughnessFactorSqrt * pixelRoughnessFactorSqrt;
return new Color32
{
r = 0,
// Bake smoothness values into a texture.
// See: https://github.com/dwango/UniVRM/issues/212.
g = (byte)Mathf.Clamp(pixelRoughnessFactor * 255, 0, 255),
b = src.r,
a = 255,
};
}
}
public class NormalConverter : ITextureConverter
{
private Material m_decoder;
private Material GetDecoder()
{
if (m_decoder == null)
{
m_decoder = new Material(Shader.Find("UniGLTF/NormalMapDecoder"));
}
return m_decoder;
}
private Material m_encoder;
private Material GetEncoder()
{
if (m_encoder == null)
{
m_encoder = new Material(Shader.Find("UniGLTF/NormalMapEncoder"));
}
return m_encoder;
}
// GLTF data to Unity texture
// ConvertToNormalValueFromRawColorWhenCompressionIsRequired
public Texture2D GetImportTexture(Texture2D texture)
{
var mat = GetEncoder();
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
return converted;
}
// Unity texture to GLTF data
// ConvertToRawColorWhenNormalValueIsCompressed
public Texture2D GetExportTexture(Texture2D texture)
{
var mat = GetDecoder();
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Normal, null, mat);
return converted;
}
}
public class OcclusionConverter : ITextureConverter
{
public Texture2D GetImportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Import, null);
return converted;
}
public Texture2D GetExportTexture(Texture2D texture)
{
var converted = TextureConverter.Convert(texture, glTFTextureTypes.Occlusion, Export, null);
return converted;
}
public Color32 Import(Color32 src)
{
return new Color32
{
r = 0,
g = src.r,
b = 0,
a = 255,
};
}
public Color32 Export(Color32 src)
{
return new Color32
{
r = src.g,
g = 0,
b = 0,
a = 255,
};
}
}
}

View File

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

View File

@ -0,0 +1,27 @@
using System.Collections.Generic;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// Mesh, Material, Texture などを抱えておいて確実に破棄できるようにする
/// </summary>
public class UnityResourceDestroyer : MonoBehaviour
{
List<UnityEngine.Object> m_resources = new List<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);
}
}
}
}

View File

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

View File

@ -1,7 +1,8 @@
{
"name": "UniGLTF.Tests",
"references": [
"UniGLTF"
"UniGLTF",
"UniGLTF.Editor"
],
"optionalUnityReferences": [
"TestAssemblies"

View File

@ -133,7 +133,8 @@ namespace UniGLTF
GameObject.DestroyImmediate(go);
if (context != null)
{
context.EditorDestroyRootAndAssets();
var editor = new EditorImporterContext(context);
editor.EditorDestroyRootAndAssets();
}
}
}

View File

@ -318,6 +318,7 @@ namespace VRM.Samples
await m_texts.UpdateMetaAsync(context);
await context.LoadAsync();
context.DisposeOnGameObjectDestroyed();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
@ -333,6 +334,7 @@ namespace VRM.Samples
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.DisposeOnGameObjectDestroyed();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();
@ -348,6 +350,7 @@ namespace VRM.Samples
var context = new UniGLTF.ImporterContext(parser);
context.Load();
context.DisposeOnGameObjectDestroyed();
context.ShowMeshes();
context.EnableUpdateWhenOffscreen();
context.ShowMeshes();

View File

@ -0,0 +1,91 @@
using System.Collections;
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
namespace VRM
{
public class VRMEditorImporterContext : EditorImporterContext
{
VRMImporterContext m_context;
public VRMEditorImporterContext(VRMImporterContext context) : base(context)
{
m_context = context;
}
public override IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
{
foreach (var x in base.ObjectsForSubAsset())
{
yield return x;
}
yield return m_context.AvatarDescription;
yield return m_context.HumanoidAvatar;
if (m_context.BlendShapeAvatar != null && m_context.BlendShapeAvatar.Clips != null)
{
foreach (var x in m_context.BlendShapeAvatar.Clips)
{
yield return x;
}
}
yield return m_context.BlendShapeAvatar;
yield return m_context.Meta;
}
public override bool AvoidOverwriteAndLoad(UnityPath assetPath, UnityEngine.Object o)
{
if (o is BlendShapeAvatar)
{
var loaded = assetPath.LoadAsset<BlendShapeAvatar>();
var proxy = m_context.Root.GetComponent<VRMBlendShapeProxy>();
proxy.BlendShapeAvatar = loaded;
return true;
}
if (o is BlendShapeClip)
{
return true;
}
return base.AvoidOverwriteAndLoad(assetPath, o);
}
public override UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o, bool meshAsSubAsset)
{
if (o is BlendShapeAvatar
|| o is BlendShapeClip)
{
var dir = prefabPath.GetAssetFolder(".BlendShapes");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is Avatar)
{
var dir = prefabPath.GetAssetFolder(".Avatar");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is VRMMetaObject)
{
var dir = prefabPath.GetAssetFolder(".MetaObject");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is UniHumanoid.AvatarDescription)
{
var dir = prefabPath.GetAssetFolder(".AvatarDescription");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else
{
return base.GetAssetPath(prefabPath, o, meshAsSubAsset);
}
}
}
}

View File

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

View File

@ -53,7 +53,8 @@ namespace VRM
var parser = new GltfParser();
parser.ParseGlb(File.ReadAllBytes(path));
var context = new VRMImporterContext(parser);
context.ExtractImages(prefabPath);
var editor = new VRMEditorImporterContext(context);
editor.ExtractImages(prefabPath);
EditorApplication.delayCall += () =>
{
@ -61,8 +62,8 @@ namespace VRM
// after textures imported
//
context.Load();
context.SaveAsAsset(prefabPath);
context.EditorDestroyRoot();
editor.SaveAsAsset(prefabPath);
editor.Dispose();
};
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UniGLTF;
using UnityEditor;
using UnityEngine;
@ -53,7 +52,8 @@ namespace VRM
// save texture assets !
var context = new VRMImporterContext(parser);
context.ExtractImages(prefabPath);
var editor = new VRMEditorImporterContext(context);
editor.ExtractImages(prefabPath);
EditorApplication.delayCall += () =>
{
@ -61,8 +61,8 @@ namespace VRM
// after textures imported
//
context.Load();
context.SaveAsAsset(prefabPath);
context.EditorDestroyRoot();
editor.SaveAsAsset(prefabPath);
editor.Dispose();
};
}
}

View File

@ -16,7 +16,7 @@ namespace VRM
private void OnEnable()
{
m_VRMMetaObjectProp = serializedObject.FindProperty("Meta");
m_VRMMetaObjectProp = serializedObject.FindProperty(nameof(VRMMeta.Meta));
m_Inspector = Editor.CreateEditor(m_VRMMetaObjectProp.objectReferenceValue);
}

View File

@ -3,7 +3,6 @@ using System.Linq;
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
using System.IO;
using UniJSON;
using UniGLTF.AltTask;
@ -299,80 +298,22 @@ namespace VRM
return meta;
}
protected override IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
public override IEnumerable<UnityEngine.Object> ModelOwnResources()
{
foreach (var x in base.ObjectsForSubAsset())
foreach (var x in base.ModelOwnResources())
{
yield return x;
}
yield return AvatarDescription;
// VRM 固有のリソース(ScriptableObject)
yield return HumanoidAvatar;
if (BlendShapeAvatar != null && BlendShapeAvatar.Clips != null)
yield return AvatarDescription;
yield return Meta;
foreach (var x in BlendShapeAvatar.Clips)
{
foreach (var x in BlendShapeAvatar.Clips)
{
yield return x;
}
yield return x;
}
yield return BlendShapeAvatar;
yield return Meta;
}
#if UNITY_EDITOR
public override bool AvoidOverwriteAndLoad(UnityPath assetPath, UnityEngine.Object o)
{
if (o is BlendShapeAvatar)
{
var loaded = assetPath.LoadAsset<BlendShapeAvatar>();
var proxy = Root.GetComponent<VRMBlendShapeProxy>();
proxy.BlendShapeAvatar = loaded;
return true;
}
if (o is BlendShapeClip)
{
return true;
}
return base.AvoidOverwriteAndLoad(assetPath, o);
}
protected override UnityPath GetAssetPath(UnityPath prefabPath, UnityEngine.Object o)
{
if (o is BlendShapeAvatar
|| o is BlendShapeClip)
{
var dir = prefabPath.GetAssetFolder(".BlendShapes");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is Avatar)
{
var dir = prefabPath.GetAssetFolder(".Avatar");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is VRMMetaObject)
{
var dir = prefabPath.GetAssetFolder(".MetaObject");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else if (o is UniHumanoid.AvatarDescription)
{
var dir = prefabPath.GetAssetFolder(".AvatarDescription");
var assetPath = dir.Child(o.name.EscapeFilePath() + ".asset");
return assetPath;
}
else
{
return base.GetAssetPath(prefabPath, o);
}
}
#endif
}
}