リグユニットの開発

grisはモジュラーリギングシステムを採用しています。 モジュラーリギングは目的に応じたリグをユニット単位で作成する事によって、 組み合わせによる汎用性を目指しています。

ここではリグユニットの仕様と新たに作成する方法について解説します。

仕様

Unit

リグのモジュールはUnitと呼ばれるオブジェクトが全体管理を行います。 ユニットには以下のような情報が格納されています。

ユニット名

ユニットの名前

位置情報

このユニットが扱う位置情報(左、右など)

サフィックス

同じユニットを復数使用する場合につける識別用サフィックス

また、ユニットにはリグを構築する上で必用な情報も保持しています。

  • リグ作成に必用なジョイントの情報

  • リグ作成時に必用なオプション情報

ユニットはこれらの情報を保持し、 必用に応じて後述するJointCreatorやRigCreatorに提供されます。

blockdiag unit JointCreator RigCreator info info

重要なメソッド

unitName()

ユニットの名前を返します。

position()

このユニットが扱う位置情報(左、右など)を返します。

suffix()

識別用サフィックスを返します。

addMember(label=str, nodes=list)

ジョイントをユニットに紐付ける場合に使用します。 紐付けられたジョイントは、 後にgetMember(label)で取得する事が出来るようになります。

getMember(keyword=str)

addMemberで紐付けられたジョイントを取得します。

JointCreatorとRigCreator

リグのモジュールを作成するにあたって、 girsではベースとなるジョイント作成を担うJointCreatorクラスと、 リグ作成を担うRigCreatorクラスの2つが重要な要素を担っています。

これらモジュールはgris本体が管理しており、 必用なタイミングでJointCreatorやRigCreatorが呼ばれるようになっています。

開発者は各クラスのprocessメソッドを上書きする事により、 目的のジョイントやリグを作成します。

Constructorクラス含め、 これらクラスは全てrigScript.BaseCreatorクラスのサブクラスとなっています。 そのため、Constructorと共通のメソッドを多数持っています。

blockdiag BaseCreator StandardCreator JointCreator RigCreator BasicConstructor rigScripts constructor

共通の重要メソッド

メソッド名

戻り値

説明

unit()

grisNode.Unit:

このモジュールが管理するユニットノードを返します。 ユニットノードにはリグを作成する際に使用するメタ情報を残すのに使用します。

参考

ユニットについては Unit をご覧下さい。

addLockedList(nodelist=list)

None

引数にはTransformノードの名前か、そのリストを渡します。 このリストに登録されたノードはリグ作成完了時にtransformアトリビュートがロックされます。

removeLockedList(self, nodelist=list)

None

addLockedListに登録したノードの登録を解除したい場合はこのメソッドを使用します。

JointCreator

このクラスはジョイントの作成と、ファイナライズの管理を行うクラスです。 基本的なジョイントの作成は process メソッド内に記述し、ファイナライズの処理は finalize メソッド内に記述します。

JointCreatorが呼ばれるタイミング

JointCreatorには前述の通り2つの機能があります。 この2つの機能はそれぞれ違うタイミングで呼ばれます。

process

これはユニットの作成時にに呼ばれ、 ユニットの情報を持つmetaノードと一緒にジョイントを作成する目的で使用されます。 簡易的に作成する場合は以下のコマンドで作成することで実行すうることができます。

from gris3 import core
core.createJoint(unitType, baseName, position, suffix, parent, options)

引数は以下の通りです。

引数

説明

unitType

str

作成するユニットの名前を指定します。

baseName

str

作成するユニットと、その関連オブジェクトにつける名前のベースとなる文字列を指定します。

position

str or int

0~9の整数、またはL、Rなど位置を表す文字列を指定します。

suffix

str

ベースネームに追加するサフィックスを指定します。

同じユニットが複数ある場合、このサフィックスを変えて指定して、名前の重複を防ぎます。

parent

str

ユニットの関連オブジェクトの親となるノード名を指定します。

options

dict

ユニット固有のオプションが指定できる場合、辞書型で指定することができます。

戻り値としてはJointCreatorオブジェクトが返されます。

finalize

gris用finalize関数が呼ばれた際に一緒に呼ばれます。 finalize関数は以下の方法で呼ぶ事ができます。

from gris3 import core
core.finalizeBaseSkeleton()

この関数は通常コンストラクタ内で呼ばれるため開発者は意識する必要はありませんが、 モジュール開発中にデバッグとして使用したい場合に便利です。

上記関数はGUIからもアクセスできます。 FactoryWidgetのMiscタブのFinalizeBaseSkeletonをクリックする事により実行可能です。

../_images/0021.png

現在のgrisでは、 この機能はスクリプトベースのリギング内で使用する事が想定されているため不可逆機能であり、 戻るためにはUndoを使用する以外の方法はサポートしていません。 従って開発者は現在のところfinalize前の状態に戻るための関数を実装する必要はありません。

UnitのaddMemberメソッド

JointCreatorによって作成されるジョイントなどのノードは、 後に呼ばれるRigCreatorクラスが必要に応じてアクセス出来るようになっている必要があります。

JointCreatorが作成したノードを、後々RigCreatorが呼べるようにするためには、 Unitに必要な情報を残しておく必要があります。

そこでJointCreator内で作成したノードのうちRigCreatorが必要となるノードは、 UnitオブジェクトのaddMemberメソッドを使用してUnitに登録しておきましょう。

addMemberの第1引数は、後でRigCreatorがノードにアクセスする際のキーワードとなります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
name = self.basenameObject()    #ベースとなる名前オブジェクトを取得。
parent = self.parent()          #親ノードを取得。
unit = self.unit()              #Unitオブジェクトを取得。

name.setName('sampleRoot')
jnt = node.createNode('joint', n=name(), p=parent)
# 作成したジョイントをrootJointとして登録。
unit.addMember('rootJoint', jnt)

# 登録したジョイントの取得。(基本的に使用するのはfinalize内かrigCreator内)
root_jnt = unit.getMember('rootJoint')

JointCreator固有の重要メソッド

メソッド名

戻り値

説明

basenameObject()

system.AbstractNameRule:

予め設定された情報を元に作成された名前ルールオブジェクトを返します。

作成するジョイントの名前をつける際にこのオブジェクトを使用すると、 開発者はユニットがどの位置のものなのかや、 オプションとして指定されたサフィックスを意識することなく名前付けを行う事ができます。

基本的に名前をつける際にはこのオブジェクトを使用する事を推奨しています。

asRoot(*joints)

None

引数に作成した任意のジョイントやトランスフォームノードを渡します。 渡されたノードはルートノードとして設定され、 ユニットのルートであることを示すロケータが追加されます。

この機能は視認性以外には特に効果はありません。

parent()

node.Transform

このユニットの親となるノード名を返します。 原則、ジョイントを作成する場合はこのノードの下階層に作成して下さい。

RigCreator

このクラスはJointCreatorによって作成されたジョイントに対し、 リグを追加する事を目的として設計されたクラスです。

このクラスのprocessメソッド内にコントローラ作成用のスクリプトを記述します。 processメソッドは必ずJointCreatorで任意のジョイントが作成され、 Finalizeを経た後に呼ばれる事が前提になっています。

JointCreatorが作成したノードを取得する

コントローラやリグを作成する場合、 当然予め作成されたノードをベースに作成していきます。

この予め作成されたノードを取得するにはUnitオブジェクトの getMember メソッドを使用します。

getMemberの第1引数には、取得したいノードを登録した際に使用したキーワードを渡します。 キーワードはJointCreator内でaddMemberを使用した際に用いられた第1引数になります。

RigCreator固有の重要メソッド

メソッド名

戻り値

説明

axisX()

str:

ユニットのposition設定にもとづいて、X軸が正方向か負方向かを返します。

ユニットのposition情報が「R」の場合-Xを、それ以外の場合は+Xを返します。

vectorX()

list

ユニットのposition設定にもとづいて、X軸が正方向か負方向かを返します。

ユニットのposition情報が「R」の場合[-1, 0, 0]を、 それ以外の場合は[1, 0, 0]を返します。

animSet()

grisNode.AnimSet

このユニットが使用するAnimSetを返します。 モジュール内で作成したコントローラは必ずこのAnimSetに登録して下さい。

プリセット

任意のリグユニットを組み合わせたものを、プリセットとして提供する事が出来ます。 プリセットはpyファイルによって定義されます。 プリセットのpyファイルはリグユニットと同じ階層に作成する事で機能するようになります。

プリセットファイルの仕様

クラスの定義

プリセットファイルをプリセットと認識させるには、ファイル内に Preset クラスを定義します。

grisはクラス名でプリセットかどうかを判断しているため、必ずクラス名は Preset にして下さい。

Preset クラスはgris3.rigScriptsモジュールのPresetクラスを継承させます。

1
2
3
4
from gris3 import rigScripts, node

class Preset(rigScripts.Preset):
    pass

メソッドをオーバーライドする

Presetクラスを定義したら、次は任意のメソッドをオーバーライドします。 オーバーライドするメソッド名は以下をご参照下さい。

メソッド名

戻り値

説明

name()

str:

ユーザーに提示するプリセット名を返します。

description()

str

ユーザーにプリセットの内容を説明するためのテキストを返します。

includes()

list

このプリセットが使用するユニット名をリストとして返します。 リストにはrigScripts.PresetElementクラスのインスタンスを任意の数だけ 入れておきます。

詳細については PresetElement をご確認下さい。

create(creators)

None

引き数creatorsにはincludesで登録されているリグユニットが辞書形式で渡されます。 デフォルトではincludesメソッドで登録されているリグユニットを すべて使用してbaseJointを作成します。 挙動を変える場合はこのメソッドをオーバーライドします。 詳細は プリセットのサンプル をご覧下さい。

PresetElement

プリセットで使用するリグユニットを登録する際に、このクラスを使用します。 まずは登録する場合のサンプルコードをご覧下さい。

1
2
3
4
5
6
7
8
9
def includes(self):
    return [
        rigScripts.PresetElement('humanSpineRig', 1),
        rigScripts.PresetElement('humanClavicleRig', 2),
        rigScripts.PresetElement('humanArmRig', 2),
        rigScripts.PresetElement('humanClavicleRig', 3),
        rigScripts.PresetElement('humanArmRig', 3),
        rigScripts.PresetElement('humanHandRig', 3),
    ]

includesメソッドはリストを返す必要があります。 リスト内には rigScripts.PresetElement のインスタンスを任意のリグユニットの数だけ入れておきます。

PresetElementクラスはインスタンス生成時に引き数を渡す以外には特に操作する必要はありません。

引き数

説明

unitName

str

使用するユニット名を指定します。

position

int

位置を表す整数です。 使用できる整数の範囲は0~8です。 代表的な数字は 1:センター 2:左 3:右 になります。

suffix

str

同じユニットを複数使用する場合、識別用につけるサフィックスです。

プリセットのサンプル

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# -*- coding:utf-8 -*-
from gris3 import rigScripts, node

class Preset(rigScripts.Preset):
    def name(self):
        return 'Basic Human'

    def description(self):
        return u'ベーシックな人型のリグプリセット。'

    def includes(self):
        return [
            rigScripts.PresetElement('humanSpineRig', 1),
            rigScripts.PresetElement('humanHeadRig', 1),
            rigScripts.PresetElement('humanClavicleRig', 2),
            rigScripts.PresetElement('humanArmRig', 2),
            rigScripts.PresetElement('humanHandRig', 2),
            rigScripts.PresetElement('humanLegRig', 2),
            rigScripts.PresetElement('humanClavicleRig', 3),
            rigScripts.PresetElement('humanArmRig', 3),
            rigScripts.PresetElement('humanHandRig', 3),
            rigScripts.PresetElement('humanLegRig', 3),
        ]
    def create(self, creators):
        parent = node.selected()
        if not parent:
            parent = self.jointRoot()
        else:
            parent = parent[0]

        # 背骨の作成。
        spine = creators['humanSpineRig-C']
        spine.createBaseJoint(parent)

        # 頭部の作成。
        head = creators['humanHeadRig-C']
        head.createBaseJoint(spine.unit().getMember('spineEnd'))

        for side in ('LR'):
            clv = creators['humanClavicleRig-'+side]
            clv.createBaseJoint(spine.unit().getMember('spineEnd'))
            
            arm = creators['humanArmRig-'+side]
            arm.createBaseJoint(clv.unit().getMember('clavicle'))

            hand = creators['humanHandRig-'+side]
            hand.createBaseJoint(arm.unit().getMember('hand'))

            leg = creators['humanLegRig-'+side]
            leg.createBaseJoint(spine.unit().getMember('hip'))

サンプル

新規で作成する

リグのモジュールの雛形はコマンドで作成できるようになっています。 以下のコマンドを実行することにより、リグモジュールを作成する事ができます。 (ver.0.9.5.3から)

1
2
3
4
5
from gris3 import scriptTemplates
c = scriptTemplates.RigUnitCreator()
c.setCategory('Sample')
c.setFileName('sampleRig')
c.create()

setCategory メソッドは、リグユニット一覧の時にカテゴライズする名前を設定します。 同じカテゴリになるとGUI上では一つにまとめられます。 指定しなければどのカテゴリにも属さず、トップ階層にリストされます。

../_images/0012.png

setFileName メソッドは作成するリグの名前を指定します。 このメソッドは必ず指定する必要があり、 既存のリグスクリプトと重複している場合は作成が無視されます。