136 lines
4.6 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using UniGLTF;
using UnityEngine;
namespace VRM
{
public static class glTF_VRMExtensions
{
[Obsolete("Use Create(root, meshes, binding)")]
public static glTF_VRM_BlendShapeBind Cerate(Transform root, BlendShapeBinding binding,
gltfExporter exporter)
{
return Create(root, binding, exporter);
}
public static glTF_VRM_BlendShapeBind Create(Transform root, BlendShapeBinding binding,
gltfExporter exporter)
{
if (root == null || exporter == null)
{
return null;
}
if (string.IsNullOrEmpty((binding.RelativePath)))
{
Debug.LogWarning("binding.RelativePath is null");
return null;
}
var found = root.transform.Find(binding.RelativePath);
if (found == null)
{
var name = binding.RelativePath.Split('/').Last();
found = root.GetComponentsInChildren<Transform>().FirstOrDefault(x => x.name == name);
if (found == null)
{
Debug.LogWarning($"{binding.RelativePath} not found");
return null;
}
else
{
Debug.LogWarning($"fall back '{binding.RelativePath}' => '{found.RelativePathFrom(root)}'");
}
}
var renderer = found.GetComponent<SkinnedMeshRenderer>();
if (renderer == null)
{
return null;
}
if (!renderer.gameObject.activeInHierarchy)
{
return null;
}
var mesh = renderer.sharedMesh;
var meshIndex = exporter.Meshes.IndexOf(mesh);
if (meshIndex == -1)
{
return null;
}
if (!exporter.MeshBlendShapeIndexMap.TryGetValue(mesh, out Dictionary<int, int> blendShapeIndexMap))
{
// この Mesh は エクスポートされていない
return null;
}
if (!blendShapeIndexMap.TryGetValue(binding.Index, out int blendShapeIndex))
{
// この blendShape は エクスポートされていない(空だった?)
return null;
}
return new glTF_VRM_BlendShapeBind
{
mesh = meshIndex,
index = blendShapeIndex,
weight = binding.Weight,
};
}
public static void Add(this glTF_VRM_BlendShapeMaster master,
BlendShapeClip clip, gltfExporter exporter)
{
master.blendShapeGroups.Add(clip.Serialize(exporter));
}
public static glTF_VRM_BlendShapeGroup Serialize(this BlendShapeClip clip, gltfExporter exporter)
{
var bindList = new List<glTF_VRM_BlendShapeBind>();
if (clip.Values != null && exporter != null)
{
foreach (var value in clip.Values)
{
var bind = Create(exporter.Copy.transform, value, exporter);
if (bind == null)
{
// Debug.LogFormat("{0}: skip blendshapebind", clip.name);
continue;
}
bindList.Add(bind);
}
}
var materialValueBinds = new List<glTF_VRM_MaterialValueBind>();
if (clip.MaterialValues != null)
{
materialValueBinds.AddRange(clip.MaterialValues.Select(y => new glTF_VRM_MaterialValueBind
{
materialName = y.MaterialName,
propertyName = y.ValueName,
targetValue = y.TargetValue.ToArray(),
}));
}
return new glTF_VRM_BlendShapeGroup
{
name = clip.BlendShapeName,
presetName = clip.Preset.ToString().ToLowerInvariant(),
isBinary = clip.IsBinary,
binds = bindList,
materialValues = materialValueBinds,
};
}
public static void Apply(this glTF_VRM_DegreeMap map, CurveMapper mapper)
{
map.curve = mapper.Curve.keys.SelectMany(x => new float[] { x.time, x.value, x.inTangent, x.outTangent }).ToArray();
map.xRange = mapper.CurveXRangeDegree;
map.yRange = mapper.CurveYRangeDegree;
}
}
}