Merge pull request #1473 from ousttrue/fix10/expression_migration_fallback

vrm-0.x の仕様で、preset: unknown のときに name を preset として解釈するに対応
This commit is contained in:
ousttrue
2022-01-18 21:33:52 +09:00
committed by GitHub
4 changed files with 78 additions and 24 deletions

View File

@@ -9,6 +9,8 @@ namespace UniVRM10
[Serializable]
public sealed class VRM10ObjectExpression
{
public const string NEUTRAL_KEY = "Neutral";
#region Preset
[SerializeField, Header("Emotion")]
public VRM10Expression Happy;

View File

@@ -427,6 +427,14 @@ namespace UniVRM10
{
var key = ExpressionKey.CreateCustom(name);
var preset = ExpressionPreset.custom;
if (preset == ExpressionPreset.custom && name == VRM10ObjectExpression.NEUTRAL_KEY)
{
// TODO:
// 注意JsonSchema の更新待ち?
key = ExpressionKey.CreateFromPreset(ExpressionPreset.neutral);
Debug.Log($"set neutral");
preset = ExpressionPreset.neutral;
}
var clip = GetOrLoadExpression(key.SubAssetKey, preset, expression);
if (clip != null)
{

View File

@@ -40,6 +40,20 @@ namespace UniVRM10
return MigrateVrm(gltf, bin, data.Json.ParseAsJson()["extensions"]["VRM"]);
}
/// <summary>
/// dst が null の場合だけ代入する。
/// 先に来た方を有効にしたい。
/// </summary>
/// <param name="dst"></param>
/// <param name="src"></param>
static void SetIfNull(ref UniGLTF.Extensions.VRMC_vrm.Expression dst, UniGLTF.Extensions.VRMC_vrm.Expression src)
{
if (dst == null)
{
dst = src;
}
}
static byte[] MigrateVrm(glTF gltf, ArraySegment<byte> bin, JsonNode vrm0)
{
var meshToNode = CreateMeshToNode(gltf);
@@ -65,25 +79,38 @@ namespace UniVRM10
{
switch (preset)
{
case ExpressionPreset.happy: vrm1.Expressions.Preset.Happy = expression; break;
case ExpressionPreset.angry: vrm1.Expressions.Preset.Angry = expression; break;
case ExpressionPreset.sad: vrm1.Expressions.Preset.Sad = expression; break;
case ExpressionPreset.relaxed: vrm1.Expressions.Preset.Relaxed = expression; break;
case ExpressionPreset.surprised: vrm1.Expressions.Preset.Surprised = expression; break;
case ExpressionPreset.aa: vrm1.Expressions.Preset.Aa = expression; break;
case ExpressionPreset.ih: vrm1.Expressions.Preset.Ih = expression; break;
case ExpressionPreset.ou: vrm1.Expressions.Preset.Ou = expression; break;
case ExpressionPreset.ee: vrm1.Expressions.Preset.Ee = expression; break;
case ExpressionPreset.oh: vrm1.Expressions.Preset.Oh = expression; break;
case ExpressionPreset.blink: vrm1.Expressions.Preset.Blink = expression; break;
case ExpressionPreset.blinkLeft: vrm1.Expressions.Preset.BlinkLeft = expression; break;
case ExpressionPreset.blinkRight: vrm1.Expressions.Preset.BlinkRight = expression; break;
case ExpressionPreset.lookUp: vrm1.Expressions.Preset.LookUp = expression; break;
case ExpressionPreset.lookDown: vrm1.Expressions.Preset.LookDown = expression; break;
case ExpressionPreset.lookLeft: vrm1.Expressions.Preset.LookLeft = expression; break;
case ExpressionPreset.lookRight: vrm1.Expressions.Preset.LookRight = expression; break;
case ExpressionPreset.neutral: vrm1.Expressions.Custom[customName] = expression; break;
case ExpressionPreset.custom: vrm1.Expressions.Custom[customName] = expression; break;
case ExpressionPreset.happy: SetIfNull(ref vrm1.Expressions.Preset.Happy, expression); break;
case ExpressionPreset.angry: SetIfNull(ref vrm1.Expressions.Preset.Angry, expression); break;
case ExpressionPreset.sad: SetIfNull(ref vrm1.Expressions.Preset.Sad, expression); break;
case ExpressionPreset.relaxed: SetIfNull(ref vrm1.Expressions.Preset.Relaxed, expression); break;
case ExpressionPreset.surprised: SetIfNull(ref vrm1.Expressions.Preset.Surprised, expression); break;
case ExpressionPreset.aa: SetIfNull(ref vrm1.Expressions.Preset.Aa, expression); break;
case ExpressionPreset.ih: SetIfNull(ref vrm1.Expressions.Preset.Ih, expression); break;
case ExpressionPreset.ou: SetIfNull(ref vrm1.Expressions.Preset.Ou, expression); break;
case ExpressionPreset.ee: SetIfNull(ref vrm1.Expressions.Preset.Ee, expression); break;
case ExpressionPreset.oh: SetIfNull(ref vrm1.Expressions.Preset.Oh, expression); break;
case ExpressionPreset.blink: SetIfNull(ref vrm1.Expressions.Preset.Blink, expression); break;
case ExpressionPreset.blinkLeft: SetIfNull(ref vrm1.Expressions.Preset.BlinkLeft, expression); break;
case ExpressionPreset.blinkRight: SetIfNull(ref vrm1.Expressions.Preset.BlinkRight, expression); break;
case ExpressionPreset.lookUp: SetIfNull(ref vrm1.Expressions.Preset.LookUp, expression); break;
case ExpressionPreset.lookDown: SetIfNull(ref vrm1.Expressions.Preset.LookDown, expression); break;
case ExpressionPreset.lookLeft: SetIfNull(ref vrm1.Expressions.Preset.LookLeft, expression); break;
case ExpressionPreset.lookRight: SetIfNull(ref vrm1.Expressions.Preset.LookRight, expression); break;
case ExpressionPreset.neutral:
// TODO: 仕様確定待ち
// Presetに格上げするか、小文字にする
vrm1.Expressions.Custom[VRM10ObjectExpression.NEUTRAL_KEY] = expression;
break;
case ExpressionPreset.custom:
if (vrm1.Expressions.Custom.ContainsKey(customName))
{
// 同名が既存。不採用
}
else
{
vrm1.Expressions.Custom[customName] = expression;
}
break;
default: throw new NotImplementedException();
}
}

View File

@@ -8,12 +8,29 @@ namespace UniVRM10
{
public static class MigrationVrmExpression
{
static ExpressionPreset ToPreset(JsonNode json)
/// <summary>
/// preset 名の文字列から ExpressionPreset を確定させる。
///
/// 0.x の特殊な挙動として、
/// preset名が "unknown" の場合に、
/// "name" を preset 名として解釈を試みる。
/// </summary>
/// <param name="json"></param>
/// <param name="name"></param>
/// <returns></returns>
static ExpressionPreset ToPreset(JsonNode json, string name)
{
switch (json.GetString().ToLower())
var src = json.GetString().ToLowerInvariant();
if (src == "unknown")
{
case "unknown": return ExpressionPreset.custom;
// VRM 0.x では以下の実装が存在した。
// Preset が unknown で Name が Joy の表情があったときに
// それは Preset が Joy であるとみなしてロードしていた。
src = name.ToLowerInvariant();
}
switch (src)
{
// https://github.com/vrm-c/vrm-specification/issues/185
case "neutral": return ExpressionPreset.neutral;
@@ -39,7 +56,7 @@ namespace UniVRM10
case "lookright": return ExpressionPreset.lookRight;
}
throw new NotImplementedException();
return ExpressionPreset.custom;
}
static IEnumerable<UniGLTF.Extensions.VRMC_vrm.MorphTargetBind> ToMorphTargetBinds(JsonNode json,
@@ -199,7 +216,7 @@ namespace UniVRM10
{
isBinary = isBinaryNode.GetBoolean();
}
var preset = ToPreset(blendShapeClip["presetName"]);
var preset = ToPreset(blendShapeClip["presetName"], name);
var expression = new UniGLTF.Extensions.VRMC_vrm.Expression
{
IsBinary = isBinary,