Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/extract key #872

Merged
merged 6 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 13 additions & 21 deletions Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/EditorMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,25 @@ public static void OnGUI(ScriptedImporter importer, GltfParser parser, Enumerate
s_foldMaterials = EditorGUILayout.Foldout(s_foldMaterials, "Remapped Materials");
if (s_foldMaterials)
{
importer.DrawRemapGUI<UnityEngine.Material>(parser.GLTF.materials.Select(x => x.name));
importer.DrawRemapGUI<UnityEngine.Material>(parser.GLTF.materials.Select(x => new SubAssetKey(typeof(Material), x.name)));
}

s_foldTextures = EditorGUILayout.Foldout(s_foldTextures, "Remapped Textures");
if (s_foldTextures)
{
var names = enumTextures(parser)
.Select(x =>
importer.DrawRemapGUI<UnityEngine.Texture2D>(enumTextures(parser)
.Where(x =>
{
if (x.TextureType != TextureImportTypes.StandardMap && !string.IsNullOrEmpty(x.Uri))
var (key, param) = x;
if ((param.TextureType == TextureImportTypes.sRGB || param.TextureType == TextureImportTypes.NormalMap) && !string.IsNullOrEmpty(param.Uri))
{
// GLTF の 無変換テクスチャーをスキップする
return null;
}

switch (x.TextureType)
{
case TextureImportTypes.NormalMap:
return x.GltfName;

default:
return x.ConvertedName;
return false;
}
return true;
})
.Where(x => !string.IsNullOrEmpty(x))
;
importer.DrawRemapGUI<UnityEngine.Texture2D>(names);
.Select(x => x.Key)
);
}

if (GUILayout.Button("Clear"))
Expand All @@ -100,9 +92,9 @@ static void ExtractMaterialsAndTextures(ScriptedImporter self, GltfParser parser
return;
}

Action<Texture2D> addRemap = externalObject =>
Action<SubAssetKey, Texture2D> addRemap = (key, externalObject) =>
{
self.AddRemap(new AssetImporter.SourceAssetIdentifier(typeof(UnityEngine.Texture2D), externalObject.name), externalObject);
self.AddRemap(new AssetImporter.SourceAssetIdentifier(key.Type, key.Name), externalObject);
};
Action<IEnumerable<UnityPath>> onCompleted = _ =>
{
Expand Down Expand Up @@ -133,9 +125,9 @@ public static void ExtractMaterials(this ScriptedImporter importer)
Directory.CreateDirectory(path);
}

foreach (var asset in importer.GetSubAssets<Material>(importer.assetPath))
foreach (var (key, asset) in importer.GetSubAssets<Material>(importer.assetPath))
{
asset.ExtractSubAsset($"{path}/{asset.name}.mat", false);
asset.ExtractSubAsset($"{path}/{key.Name}.mat", false);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,34 @@ public static void ClearExternalObjects<T>(this ScriptedImporter importer) where
AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate);
}

public static IEnumerable<T> GetSubAssets<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
public static IEnumerable<(SubAssetKey, T)> GetSubAssets<T>(this ScriptedImporter importer, string assetPath) where T : UnityEngine.Object
{
return AssetDatabase
.LoadAllAssetsAtPath(assetPath)
.Where(x => AssetDatabase.IsSubAsset(x))
.Where(x => x is T)
.Select(x => x as T);
.Select(x => (new SubAssetKey(typeof(T), x.name), x as T));
}

public static void DrawRemapGUI<T>(this ScriptedImporter importer, IEnumerable<string> names) where T : UnityEngine.Object
public static void DrawRemapGUI<T>(this ScriptedImporter importer, IEnumerable<SubAssetKey> keys) where T : UnityEngine.Object
{
EditorGUI.indentLevel++;
{
var map = importer.GetExternalObjectMap()
.Select(x => (x.Key.name, x.Value as T))
.Where(x => x.Item2 != null)
.ToDictionary(x => x.Item1, x => x.Item2)
;
foreach (var name in names)
var map = importer.GetExternalObjectMap();
foreach (var key in keys)
{
if (string.IsNullOrEmpty(name))
if (string.IsNullOrEmpty(key.Name))
{
throw new System.ArgumentNullException();
continue;
}

EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(name);
map.TryGetValue(name, out T value);
EditorGUILayout.PrefixLabel(key.Name);
map.TryGetValue(new AssetImporter.SourceAssetIdentifier(key.Type, key.Name), out UnityEngine.Object value);
var asset = EditorGUILayout.ObjectField(value, typeof(T), true) as T;
if (asset != value)
{
// update
importer.SetExternalUnityObject(new AssetImporter.SourceAssetIdentifier(value), asset);
}
EditorGUILayout.EndHorizontal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static void Import(ScriptedImporter scriptedImporter, AssetImportContext
using (var loader = new ImporterContext(parser, externalObjectMap.Concat(externalTextures)))
{
// settings TextureImporters
foreach (var textureInfo in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
foreach (var (key, textureInfo) in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
{
TextureImporterConfigurator.Configure(textureInfo, loader.TextureFactory.ExternalMap);
}
Expand All @@ -69,7 +69,7 @@ public static void Import(ScriptedImporter scriptedImporter, AssetImportContext
GltfParser parser, UnityPath dir)
{
var used = new HashSet<Texture2D>();
foreach (var texParam in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
foreach (var (key, texParam) in GltfTextureEnumerator.EnumerateAllTexturesDistinct(parser))
{
switch (texParam.TextureType)
{
Expand Down
50 changes: 29 additions & 21 deletions Assets/UniGLTF/Editor/UniGLTF/ScriptedImporter/TextureExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using UnityEngine;
using UnityEditor;
using UniGLTF;
using System.Linq;
using VRMShaders;

Expand All @@ -18,11 +19,11 @@ public class TextureExtractor
public glTF GLTF => m_parser.GLTF;
public IStorage Storage => m_parser.Storage;

public readonly Dictionary<UnityPath, TextureImportParam> Textures = new Dictionary<UnityPath, TextureImportParam>();
UnityEngine.Texture2D[] m_subAssets;
public readonly Dictionary<SubAssetKey, UnityPath> Textures = new Dictionary<SubAssetKey, UnityPath>();
(SubAssetKey Key, UnityEngine.Texture2D Value)[] m_subAssets;
UnityPath m_textureDirectory;

public TextureExtractor(GltfParser parser, UnityPath textureDirectory, UnityEngine.Texture2D[] subAssets)
public TextureExtractor(GltfParser parser, UnityPath textureDirectory, (SubAssetKey, UnityEngine.Texture2D)[] subAssets)
{
m_parser = parser;
m_textureDirectory = textureDirectory;
Expand All @@ -41,28 +42,29 @@ public static string GetExt(string mime, string uri)
return Path.GetExtension(uri).ToLower();
}

public void Extract(TextureImportParam param)
public void Extract(SubAssetKey key, TextureImportParam param)
{
if (Textures.Values.Contains(param))
if (Textures.ContainsKey(key))
{
return;
}

UnityPath targetPath = default;
if (!string.IsNullOrEmpty(param.Uri) && !param.ExtractConverted)
{
targetPath = m_textureDirectory.Child(param.GltfFileName);
// use GLTF external
// targetPath = m_textureDirectory.Child(key.Name);
}
else
{
UnityPath targetPath = default;

switch (param.TextureType)
{
case TextureImportTypes.StandardMap:
{
// write converted texture
var subAsset = m_subAssets.FirstOrDefault(x => x.name == param.ConvertedName);
targetPath = m_textureDirectory.Child(param.ConvertedFileName);
var (_, subAsset) = m_subAssets.FirstOrDefault(x => x.Equals(key));
targetPath = m_textureDirectory.Child($"{key.Name}.png");
File.WriteAllBytes(targetPath.FullPath, subAsset.EncodeToPNG().ToArray());
targetPath.ImportAsset();
break;
Expand All @@ -71,15 +73,14 @@ public void Extract(TextureImportParam param)
default:
{
// write original bytes
targetPath = m_textureDirectory.Child(param.GltfFileName);
targetPath = m_textureDirectory.Child($"{key.Name}{param.Ext}");
File.WriteAllBytes(targetPath.FullPath, param.Index0().Result.ToArray());
targetPath.ImportAsset();
break;
}
}
Textures.Add(key, targetPath);
}

Textures.Add(targetPath, param);
}

/// <summary>
Expand All @@ -93,37 +94,44 @@ public void Extract(TextureImportParam param)
/// <param name="dirName"></param>
/// <param name="onCompleted"></param>
public static void ExtractTextures(GltfParser parser, UnityPath textureDirectory,
EnumerateAllTexturesDistinctFunc textureEnumerator, Texture2D[] subAssets, Action<Texture2D> addRemap,
EnumerateAllTexturesDistinctFunc textureEnumerator, (SubAssetKey, Texture2D)[] subAssets,
Action<SubAssetKey, Texture2D> addRemap,
Action<IEnumerable<UnityPath>> onCompleted = null)
{
var extractor = new TextureExtractor(parser, textureDirectory, subAssets);
foreach (var x in textureEnumerator(parser))
foreach (var (key, x) in textureEnumerator(parser))
{
extractor.Extract(x);
extractor.Extract(key, x);
}

EditorApplication.delayCall += () =>
{
// Wait for the texture assets to be imported

foreach (var kv in extractor.Textures)
foreach (var (key, targetPath) in extractor.Textures)
{
var targetPath = kv.Key;
var param = kv.Value;

// remap
var externalObject = targetPath.LoadAsset<Texture2D>();
if (externalObject != null)
{
addRemap(externalObject);
addRemap(key, externalObject);
}
}

if (onCompleted != null)
{
onCompleted(extractor.Textures.Keys);
onCompleted(extractor.Textures.Values);
}
};
}
}

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;
}
}
}
6 changes: 3 additions & 3 deletions Assets/UniGLTF/Editor/UniGLTF/TextureImporterConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static void Configure(TextureImportParam textureInfo, IDictionary<string,
{
case TextureImportTypes.NormalMap:
{
if (ExternalMap.TryGetValue(textureInfo.GltfName, out Texture2D external))
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
{
ConfigureSize(external);
ConfigureNormalMap(external);
Expand All @@ -78,7 +78,7 @@ public static void Configure(TextureImportParam textureInfo, IDictionary<string,

case TextureImportTypes.StandardMap:
{
if (ExternalMap.TryGetValue(textureInfo.ConvertedName, out Texture2D external))
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
{
ConfigureSize(external);
ConfigureLinear(external);
Expand All @@ -88,7 +88,7 @@ public static void Configure(TextureImportParam textureInfo, IDictionary<string,

case TextureImportTypes.sRGB:
{
if (ExternalMap.TryGetValue(textureInfo.GltfName, out Texture2D external))
if (ExternalMap.TryGetValue(textureInfo.UnityObjectName, out Texture2D external))
{
ConfigureSize(external);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public GameObject ExportRoot
value = prefab;
isPrefab = true;
}
catch (ArgumentException ex)
catch (ArgumentException)
{
// Debug.LogWarning(ex);
}
Expand Down
25 changes: 15 additions & 10 deletions Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfPBRMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ private enum BlendMode
Transparent
}

public static TextureImportParam BaseColorTexture(GltfParser parser, glTFMaterial src)
public static (SubAssetKey, TextureImportParam Param) BaseColorTexture(GltfParser parser, glTFMaterial src)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(SubAssetKey, TextureImportParam Param) 、もはや自明な型に定義してよさそうw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct SubAssetObject
{
public SubAssetKey Key;
public UnityEngine.Object Object;
}

的な。

{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.baseColorTexture);
return GltfTextureImporter.CreateSRGB(parser, src.pbrMetallicRoughness.baseColorTexture.index, offset, scale);
}

public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial src)
public static (SubAssetKey, TextureImportParam) StandardTexture(GltfParser parser, glTFMaterial src)
{
var metallicFactor = 1.0f;
var roughnessFactor = 1.0f;
Expand All @@ -65,15 +65,17 @@ public static TextureImportParam StandardTexture(GltfParser parser, glTFMaterial
roughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
}
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.pbrMetallicRoughness.metallicRoughnessTexture);
return GltfTextureImporter.CreateStandard(parser,
var param = GltfTextureImporter.CreateStandard(parser,
src.pbrMetallicRoughness?.metallicRoughnessTexture?.index,
src.occlusionTexture?.index,
offset, scale,
metallicFactor,
roughnessFactor);
var key = new SubAssetKey(typeof(Texture2D), param.UnityObjectName);
return (key, param);
}

public static TextureImportParam NormalTexture(GltfParser parser, glTFMaterial src)
public static (SubAssetKey, TextureImportParam Param) NormalTexture(GltfParser parser, glTFMaterial src)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.normalTexture);
return GltfTextureImporter.CreateNormal(parser, src.normalTexture.index, offset, scale);
Expand All @@ -95,7 +97,8 @@ public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportPa
{
if (src.pbrMetallicRoughness.metallicRoughnessTexture != null || src.occlusionTexture != null)
{
standardParam = StandardTexture(parser, src);
SubAssetKey key;
(key, standardParam) = StandardTexture(parser, src);
}

if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4)
Expand All @@ -106,7 +109,7 @@ public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportPa

if (src.pbrMetallicRoughness.baseColorTexture != null && src.pbrMetallicRoughness.baseColorTexture.index != -1)
{
var textureParam = BaseColorTexture(parser, src);
var (key, textureParam) = BaseColorTexture(parser, src);
param.TextureSlots.Add("_MainTex", textureParam);
}

Expand All @@ -128,7 +131,7 @@ public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportPa
if (src.normalTexture != null && src.normalTexture.index != -1)
{
param.Actions.Add(material => material.EnableKeyword("_NORMALMAP"));
var textureParam = NormalTexture(parser, src);
var (key, textureParam) = NormalTexture(parser, src);
param.TextureSlots.Add("_BumpMap", textureParam);
param.FloatValues.Add("_BumpScale", src.normalTexture.scale);
}
Expand All @@ -142,7 +145,8 @@ public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportPa
if (src.emissiveFactor != null
|| (src.emissiveTexture != null && src.emissiveTexture.index != -1))
{
param.Actions.Add(material => {
param.Actions.Add(material =>
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
});
Expand All @@ -155,12 +159,13 @@ public static bool TryCreateParam(GltfParser parser, int i, out MaterialImportPa
if (src.emissiveTexture != null && src.emissiveTexture.index != -1)
{
var (offset, scale) = GltfMaterialImporter.GetTextureOffsetAndScale(src.emissiveTexture);
var textureParam = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
var (key, textureParam) = GltfTextureImporter.CreateSRGB(parser, src.emissiveTexture.index, offset, scale);
param.TextureSlots.Add("_EmissionMap", textureParam);
}
}

param.Actions.Add(material => {
param.Actions.Add(material =>
{
BlendMode blendMode = BlendMode.Opaque;
// https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980
switch (src.alphaMode)
Expand Down
Loading