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

Fix blendshape uppercase bug. #399

Merged
merged 1 commit into from
May 18, 2020

Conversation

sh-akira
Copy link
Contributor

#330 で行われた破壊的変更により独自に設定したキーがモデルからキーの一覧を取得した際に大文字で返ってくるため、小文字で設定したキーの適用が不可能になっていた問題を修正しました。

また、この時の変更によりデフォルトのJOYやFUN等のキーが文字列での指定をすることが不可能になってしまったため、アプリ開発者側で変更が必要になっています。
以前new BlendShapeKey("JOY")はBlendShapePreset.Joyを指していましたが、
BlendShapePreset.Unknownの名前がJOYのキーを指すようになってしまっています。
(標準のキーはEnumでの指定しか出来ないようにした仕様変更と理解していますが、意図したものかの確認をお願いします。)

テストコード

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using VRM;

public class UniVRMTest : MonoBehaviour
{

    [SerializeField]
    private VRMBlendShapeProxy proxy;

    private List<string> keyList;

    // Start is called before the first frame update
    void Start()
    {
        keyList = proxy.BlendShapeAvatar.Clips.Select(d => BlendShapeKey.CreateFrom(d).Name).ToList();

        foreach (var key in keyList)
        {
            Debug.Log($"BlendShapeKey:{key}");
        }
    }

    public Vector2 scrollPosition = Vector2.zero;

    private void OnGUI()
    {
        int width = 200, height = 30, left = 30, top = 30, margin = 5;

        scrollPosition = GUI.BeginScrollView(new Rect(10, 10, width + left * 2 + 20, Screen.height - top * 2), scrollPosition, new Rect(0, 0, width + left * 2 + 10, top * 2 + (height + margin) * keyList.Count));
        foreach (var key in keyList)
        {
            if (GUI.Button(new Rect(left, top, width, height), key))
            {
                SetBlendShapeKey(key);
            }
            top += height + margin;
        }
        GUI.EndScrollView();
    }

    private void SetBlendShapeKey(string key)
    {
        foreach(var keyName in keyList)
        {
            BlendShapeAccumulate(keyName, 0.0f);
        }
        BlendShapeAccumulate(key, 1.0f);
        proxy.Apply();
    }
    private void BlendShapeAccumulate(string key,float value)
    {
        var preset = BlendShapePreset.Unknown;
        foreach (BlendShapePreset p in Enum.GetValues(typeof(BlendShapePreset)))
        {
            if (p.ToString() == key)
            {
                preset = p;
                break;
            }
        }
        var blendShapeKey = new BlendShapeKey(key, preset);
        proxy.AccumulateValue(blendShapeKey, value);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このテストコードではすべてのBlendShapeKeyを文字列で列挙
proxy.BlendShapeAvatar.Clips.Select(d => BlendShapeKey.CreateFrom(d).Name).ToList()
し、ボタンでその表情に変更するサンプルです。
しかし、標準の表情はNameで取得できるにもかかわらず、new BlendShapeKey(Name)をしてしまうと、Unknown_が付加されてしまうため、Enum.GetValues(typeof(BlendShapePreset))から同名のキーを見つけた際にそちらを利用しています(0.53までの動作を再現するのに必要なコードです)。

テストに使用したVRMモデル:
8801565727279527051.zip
テスト用に"TEST1","Test2","test3"のBlendShapeKeyが追加されたモデルです。
大文字のみ、大文字小文字、小文字のみのキーです。
0.53以前は全て大文字として扱われ動作します。
0.55では大文字小文字を区別するが、Nameを取得するとToUpperで返されるため、TEST1しか動作しません。

テストコードを実行した画面:
image

現在UniVRM0.55を利用して同じ動作をさせるためにprivateなm_nameをリフレクションして取得するコードがすでに作られているので取り込んでいただけると助かります。

よろしくおねがいします

@hiroj hiroj added this to the v0.56 milestone May 18, 2020
@hiroj
Copy link
Contributor

hiroj commented May 18, 2020

プルリクエストありがとうございます。
Name が ToUpper である必要は無さそうなので、修正を取り込ませていただきます。
PresetはEnum指定しか出来ないようにした変更になりますが、取り扱うインターフェースが不十分であるため以下の関数を追加&変更しようと思います。

BlendShapeClipから直接Keyを入手出来るプロパティを追加
public BlendShapeClip.Key -> BlendShapeKey.CreateFromClip(this);

BlendShapeKeyのコンストラクタをprivateにし、CreateFromXXX経由でKeyを生成するように変更
private BlendShapeKey()
public static BlendShapeKey BlendShapeKey.CreateFromName(string)
public static BlendShapeKey BlendShapeKey.CreateFromPreset(preset)
public static BlendShapeKey BlendShapeKey.CreateFromClip(clip)

Name(string)は人間がつけるためかつ表示用ラベルであり、実装としては BlendShapeKey を取り回してもらいたいという意図がありました。

@hiroj hiroj merged commit 7f64a3c into vrm-c:master May 18, 2020
ousttrue added a commit to ousttrue/UniVRM that referenced this pull request Jun 9, 2020
vrm-c#399 vrm-c#400

* BlendShapeClip.Key 追加
* BlendShapeKey(string name, BlendShapePreset preset) を private に。代わりに、CreateFromPreset または CreateUnknown を使用してください
* BlendShapeKey.CreateFromClip(BlendShapeKey.CreateFrom からリネーム)
* BlendShapeKey.CreateFromPreset(new BlendShpaeKey(BlendShapePreset)からリネーム)
* BlendShapeKey.CreateUnknown(new BlendShpaeKey(string)からリネーム)
* BlendShapeKey.m_name, Preset を readonly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants