prefab only

This commit is contained in:
ousttrue 2022-05-18 15:19:55 +09:00
parent 81422e22be
commit 7eb564feea
5 changed files with 110 additions and 57 deletions

View File

@ -4,6 +4,7 @@ using UnityEditorInternal;
using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
namespace VRM
{
@ -107,6 +108,21 @@ namespace VRM
var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab");
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath.Value);
}
// once more, with string-based method. search same folder *.prefab
if (prefab == null)
{
var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent;
foreach (var file in Directory.EnumerateFiles(parent.FullPath))
{
var ext = Path.GetExtension(file).ToLower();
if (ext == ".prefab")
{
var prefabPath = UniGLTF.UnityPath.FromFullpath(file);
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath.Value);
break;
}
}
}
return prefab;
}

View File

@ -134,38 +134,41 @@ namespace VRM
// v0.45 Added. Binary flag
EditorGUILayout.PropertyField(m_isBinaryProp, true);
EditorGUILayout.Space();
//m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES);
m_mode = GUILayout.Toolbar(m_mode, MODES);
switch (m_mode)
if (m_targetObject.m_prefab != null)
{
case 0:
{
ClipGUI();
}
break;
case 1:
{
if (GUILayout.Button("Clear"))
EditorGUILayout.Space();
//m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES);
m_mode = GUILayout.Toolbar(m_mode, MODES);
switch (m_mode)
{
case 0:
{
m_changed = true;
m_valuesProp.arraySize = 0;
ClipGUI();
}
m_ValuesList.DoLayoutList();
}
break;
break;
case 2:
{
if (GUILayout.Button("Clear"))
case 1:
{
m_changed = true;
m_materialsProp.arraySize = 0;
if (GUILayout.Button("Clear"))
{
m_changed = true;
m_valuesProp.arraySize = 0;
}
m_ValuesList.DoLayoutList();
}
m_MaterialValuesList.DoLayoutList();
}
break;
break;
case 2:
{
if (GUILayout.Button("Clear"))
{
m_changed = true;
m_materialsProp.arraySize = 0;
}
m_MaterialValuesList.DoLayoutList();
}
break;
}
}
m_serializedObject.ApplyModifiedProperties();
@ -231,6 +234,10 @@ namespace VRM
// すべてのSkinnedMeshRendererを列挙する
foreach (var renderer in m_items.Select(x => x.SkinnedMeshRenderer))
{
if(renderer==null)
{
continue;
}
var mesh = renderer.sharedMesh;
if (mesh != null && mesh.blendShapeCount > 0)
{

View File

@ -13,17 +13,18 @@ namespace VRM
/// </summary>
public static class VRMMeshIntegratorUtility
{
public static void FollowBlendshapeRendererChange(List<MeshIntegrationResult> results, GameObject root, string assetFolder)
public static List<BlendShapeClip> FollowBlendshapeRendererChange(List<MeshIntegrationResult> results, GameObject root, string assetFolder)
{
var clips = new List<BlendShapeClip>();
var proxy = root.GetComponent<VRMBlendShapeProxy>();
if (proxy == null || proxy.BlendShapeAvatar == null)
{
return;
return clips;
}
var result = results.FirstOrDefault(x => x.IntegratedRenderer.sharedMesh.blendShapeCount > 0);
if (result == null)
{
return;
return clips;
}
var rendererDict = new Dictionary<string, SkinnedMeshRenderer>();
@ -36,19 +37,19 @@ namespace VRM
// copy modify and write
var clipAssetPathList = new List<string>();
var sb = new StringBuilder();
var clips = new List<BlendShapeClip>();
foreach (var src in proxy.BlendShapeAvatar.Clips)
{
if (src == null) continue;
// copy
var clip = BlendShapeClip.Instantiate(src);
clip.Prefab = null;
var copy = ScriptableObject.CreateInstance<BlendShapeClip>();
copy.CopyFrom(src);
copy.Prefab = null;
// modify
for (var i = 0; i < clip.Values.Length; ++i)
for (var i = 0; i < copy.Values.Length; ++i)
{
var val = clip.Values[i];
var val = copy.Values[i];
if (rendererDict.ContainsKey(val.RelativePath))
{
var srcRenderer = rendererDict[val.RelativePath];
@ -62,16 +63,16 @@ namespace VRM
val.RelativePath = dstPath;
val.Index = newIndex;
}
clip.Values[i] = val;
copy.Values[i] = val;
}
// write
var assetPath = $"{assetFolder}/{clip.name}.asset";
var assetPath = $"{assetFolder}/{copy.name}.asset";
sb.AppendLine($"write: {assetPath}");
AssetDatabase.CreateAsset(clip, assetPath);
AssetDatabase.CreateAsset(copy, assetPath);
clipAssetPathList.Add(assetPath);
clips.Add(clip);
clips.Add(copy);
}
Debug.Log(sb.ToString());
@ -81,7 +82,7 @@ namespace VRM
{
// create blendshape avatar & replace
var copy = BlendShapeAvatar.CreateInstance<BlendShapeAvatar>();
var copy = ScriptableObject.CreateInstance<BlendShapeAvatar>();
copy.Clips.AddRange(clips);
var assetPath = $"{assetFolder}/blendshape.asset";
AssetDatabase.CreateAsset(copy, assetPath);
@ -93,6 +94,8 @@ namespace VRM
// assign
proxy.BlendShapeAvatar = copy;
}
return clips;
}
}
}

View File

@ -26,6 +26,7 @@ namespace VRM
None,
NoTarget,
HasParent,
NotPrefab,
}
[SerializeField]
@ -100,7 +101,6 @@ namespace VRM
private void OnEnable()
{
Clear(HelpMessage.Ready, ValidationError.None);
m_root = Selection.activeGameObject;
OnValidate();
}
@ -165,12 +165,19 @@ namespace VRM
void OnValidate()
{
isValid = false;
if (m_root == null)
{
Clear(HelpMessage.SetTarget, ValidationError.NoTarget);
return;
}
if (m_root.GetGameObjectType() != GameObjectType.AssetPrefab)
{
Clear(HelpMessage.SetTarget, ValidationError.NotPrefab);
return;
}
if (m_root.transform.parent != null)
{
Clear(HelpMessage.InvalidTarget, ValidationError.HasParent);
@ -225,7 +232,7 @@ namespace VRM
/// 2022.05 仕様変更
///
/// * scene or prefab どっちでも動作する
/// * prefab 専用
/// * backup するのではなく 変更した copy を作成する。元は変えない
/// * copy 先の統合前の renderer を disable で残さず destroy する
/// * 実行すると mesh, blendshape, blendShape を新規に作成する
@ -234,6 +241,11 @@ namespace VRM
///
void Integrate()
{
if (m_root.GetGameObjectType() != GameObjectType.AssetPrefab)
{
throw new Exception("for prefab only");
}
String folder = "Assets";
var prefab = m_root.GetPrefab();
if (prefab != null)
@ -276,7 +288,7 @@ namespace VRM
}
// 統合した結果を反映した BlendShapeClip を作成して置き換える
VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder);
var clips = VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder);
// 用が済んだ 統合前 の renderer を削除する
foreach (var result in results)
@ -298,23 +310,27 @@ namespace VRM
firstperson.Reset();
}
if (prefab != null)
// prefab
var prefabPath = $"{assetFolder}/VrmIntegrated.prefab";
Debug.Log(prefabPath);
PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success);
if (!success)
{
// prefab
var prefabPath = $"{assetFolder}/VrmIntegrated.prefab";
Debug.Log(prefabPath);
PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success);
if (!success)
{
throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}");
}
// destroy scene
UnityEngine.Object.DestroyImmediate(copy);
throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}");
}
else
// destroy scene
UnityEngine.Object.DestroyImmediate(copy);
var prefabReference = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
foreach (var clip in clips)
{
// do nothing. keep scene
var so = new SerializedObject(clip);
so.Update();
// clip.Prefab = copy;
var prop = so.FindProperty("m_prefab");
prop.objectReferenceValue = prefabReference;
so.ApplyModifiedProperties();
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using UnityEngine;
@ -79,7 +80,7 @@ namespace VRM
/// Preview 用のObject参照
/// </summary>
[SerializeField]
GameObject m_prefab;
public GameObject m_prefab;
public GameObject Prefab
{
set { m_prefab = value; }
@ -142,5 +143,15 @@ namespace VRM
/// </summary>
[SerializeField]
public bool IsBinary;
public void CopyFrom(BlendShapeClip src)
{
IsBinary = src.IsBinary;
MaterialValues = src.MaterialValues.ToArray();
Values = src.Values.ToArray();
Preset = src.Preset;
name = src.name;
Prefab = src.Prefab;
}
}
}