On this page
この機能はまだ開発中です。現在の機能は未完成で変更される予定であり、 ドキュメントが手薄だったり、なかったりします。 これを使用するときは、そのことに我慢してください。

APEX Scriptを使用すると、ユーザはグラフ要素にアクセスして操作したり、グラフロジックを別のグラフに直接追加したり、グラフ内から他のグラフを呼び出すことができます。 APEX Scriptの紹介は、グラフ構築するためのAPEX Scriptを参照してください。

グラフ入力および出力を指定する

BindInput()およびBindOutput()は、グラフの入力と出力を定義している特殊関数です。 BindInput()およびBindOutput()の使用方法については、この例を参照してください。

以下の例では、様々なタイプのグラフ入力を指定する方法を示します:

# float値を初期化します
f = BindInput(3.1)

# 初期化されていないstring型
s: String = BindInput()

# 空っぽの配列に初期化します
a = BindInput(DictArray())

# デフォルトの辞書のキーと値のペア: {'<key>': <value>}
d = BindInput({'abc': 1.5})

# 複数のグラフ入力を作成します
x, y, z = BindInput(2.6, 'test', Dict())

# 初期化時の型変換
i = BindInput(Int(Float(1.5)))

Note

グラフ入力の型を指定しない場合、警告が表示されます。変数をどのように使用するかを正確に把握している場合にのみ、以下のように指定します:

a = BindInput()

このように定義された入力ポート a は、型が曖昧であるため、APEXネットワークビューに表示されません。

グラフの入力および出力ポートの名前は、キーワード引数(構文<key>=<value>の引数)を使用して変更できます:

i: Int = BindInput(int_test=3)

x,y = BindInput(2, my_str='hello')

BindOutput(y, int_test=i)

Note

キーワード引数は、位置指定引数(非キーワード引数)の後に配置する必要があります。

グラフ入力および出力を名前変更

__dot__ を含むキーワード引数は'.'に置き換えられます。これにより、APEX ScriptはBase.skelBase.shpなどのジオメトリ名を持つリグを処理できます:

x = BindInput(Base__dot__shp=Geometry())

Base__dot__skel: Geometry = BindInput()

BindOutput(Base__dot__skel, Base__dot__shp=x)
グラフ入力および出力でのリグのジオメトリ名

辞書入力を指定する

この例では、2つの辞書の値をAPEX Script SOPの入力として使用します:

APEX Script SOPの辞書入力

Attribute Adjust Dictionary SOP

Attribute Adjust Dictionary SOPは、入力値の辞書を定義します。 ここでは2つのAttribute Adjust Dictionary SOPに対して以下の値を設定します:

input_dictionary1

  • Attribute Name = parms1。デフォルトでは Attribute ClassDetail に設定されているので、parms1という名前のDetailアトリビュートが追加されます。

  • Set Values セクションでは、2つの辞書エントリーを設定します:

    • Key = int1, Type = Integer, Value = 2

    • Key = abc, Type = String, Value = hi

input_dictionary2

  • Attribute Name = parms2

  • Set Values セクション:

    • Key = int2, Type = Integer, Value = 4

    • Key = abc, Type = String, Value = hi again

Geometry Spreadsheetでそれらの新しいparms1辞書とparms2辞書を確認するには:

  • どちらかのAttribute Adjust Dictionary SOPを選択します。

  • ペインの上部にある New Tabアイコンをクリックして、 New Pane Tab Type ▸ Inspectors ▸ Geometry Spreadsheet を選択します。

  • 上部のツールバーの Detailを選択します:

    parms1: {"abc": "hi", "int1": 2 }
    
    parms2: {"abc": "hi again", "int2": 4 }
    

APEX Script SOP

  1. Snippet パラメータに以下のコードを記述します:

    int1: Int = BindInput()
    int2: Int = BindInput()
    abc: String = BindInput()
    
    BindOutput(int1,int2,abc)
    

    Note

    出力をバインドしない、または、入力値に対して何も行なわない場合は、入力に対して何も行なわれないので、グラフには何のロジックも表示されません。

  2. 入力辞書を指定します。 Invocation セクションで:

    • Input1 BindingsDictionary To Bind をオンにして、APEX Script SOPの1番目の入力に接続する辞書、この例では(Attribute Adjust Dictionary SOPの Attribute Name パラメータで指定した)parms1を指定します。

    • Input2 BindingsDictionary To Bind をオンにして、APEX Script SOPの2番目の入力に接続する辞書、この例ではparms2を指定します。

    このAPEX Script SOPは、それらの入力辞書のparms1parms2を見て、int1int2abcのキーを持つエントリーを探します。 複数の辞書にそれらのキーが存在する場合、後者の辞書エントリーが使用されます。 この例では、どちらの辞書にもabcキーのエントリーがあるので、2番目の辞書のabcエントリーが使用されます。 さらに、このAPEX Script SOPには警告が出ます。

  3. デフォルトでは、 Output Dictionary Bindings の1番目のエントリーには、以下の内容が設定されます:

    • Apex Outputs Groupoutputに設定されます。これは、グラフ内の出力ノードの名前です。

    • Output Attribparmsに設定されます。ここには、出力辞書の名前を設定することができます。

    Geometry Spreadsheetでグラフ出力を確認するには:

    • Geometry Spreadsheetで、ノード名の横にあるドロップダウンメニューから Invoked を選択します。

    • 上部のツールバーの Detailをクリックします。グラフ出力は、 Output Attrib で指定された辞書、この例ではparmsに格納されています:

      parms: {"abc": "hi again", "int1": 2, "int2": 4 }
      

複数の出力のバインド

特殊関数引数__nameを持つBindInput関数とBindOutput関数を使用してノードに名前を付けることで、グラフが複数の入力ノードと出力ノードを持つように設定することができます:

  1. APEX Script SOPで、 Snippet パラメータに以下のコードを記述します:

    # デフォルトの'parms'名が使用されます。
    f = BindInput(3.1)
    
    # 2番目の入力ノードの名前を'input2'にします。
    s: String = BindInput('abc', __name='input2')
    
    # デフォルトの'output'名が使用されます。
    BindOutput(f)
    
    # 2番目の出力ノードの名前を'output2'にします。
    BindOutput(s, __name='output2')
    
    複数の入力ノードと出力ノードを持つグラフ
  2. デフォルトでは、 Output Dictionary Bindings の1番目のエントリーには、以下の内容が設定されます:

    • Apex Outputs Groupoutputに設定されます。これは、グラフ内の出力ノードの名前です。

    • Output Attribparmsに設定されます。ここには、出力辞書の名前を設定することができます。

    Geometry Spreadsheetでグラフ出力を確認するには:

    • Geometry spreadsheetで、ノード名の横にあるドロップダウンメニューから Invoked を選択します。

    • 上部のツールバーの Detailをクリックします。APEX Script SOPではoutputノードの値のみを出力するようにしたので、parms辞書のみが表示されています。

  3. output2ノードの値も出力するようにするには:

    • Output Dictionary Bindings の横にあるをクリックします。

    • 新しいエントリーには、 Apex Outputs Groupoutput2に、 Output Attrib を例えばparms2に設定します。

    すると、Geometry Spreadsheetには、parmsparms2の2つの出力辞書が表示されるようになります:

    parms:  {"f": 3.1 }
    
    parms2: {"s": "abc" }
    

グラフノードおよびポート

APEX Scriptには、様々なグラフオペレーションを実行したり、ノードやポートなどの要素にアクセスできる関数が用意されています。これらの関数は主に、リギングでキャラクタのリグロジックを構築するために使用されます。APEX Scriptで可能なグラフオペレーションについては、graph::*ノードを参照してください。

特定のノード名を持つグラフノードを検索する構文:

graph.<node_name>

ノード上の特定の入力または出力ポートを検索する構文:

graph.<node_name>.<port_name>_[in|out]

2つのポートを接続:

# グラフを作成します
graph = ApexGraphHandle()

# グラフに2つのTransformObjectノードを追加します
a = graph.addNode('test_a', 'TransformObject')
b = graph.addNode('test_b', 'TransformObject')

# ポート変数を設定します
p_a = graph.test_a.xform_out
p_b = graph.test_b.xform_in

# ポートを接続します
graph.addWire(p_a, p_b)

パターンに基づいてすべてのポートを検索:

# グラフを作成します
graph = ApexGraphHandle()

# グラフに2つのTransformObjectノードを追加します
a = graph.addNode('test_a', 'TransformObject')
b = graph.addNode('test_b', 'TransformObject')

# 'test'で始まるすべてのノードを検索します
n = graph.findNodes('test*')

ノード上のポートを検索:

# グラフを作成します
graph = ApexGraphHandle()

# グラフにTransformObjectノードを追加します
a = graph.addNode('test_a', 'TransformObject')

# ノード上の入力ポート'xform'を検索します
p = graph.findPort(a, 'xform[in]')

ノードおよびポートのデータを取得(data()関数の使用方法については関数のマッピングを参照):

# グラフを作成します
graph = ApexGraphHandle()

# グラフにTransformObjectノードを追加します
a = graph.addNode('test_a', 'TransformObject')

# ノードデータを取得します
(a_name, a_callback, a_pos, a_color, a_parms) = a.data()

# ノードデータを出力します
BindOutput(a_name, a_callback, a_pos, a_color, a_parms)

# TransformObjectノードの'xform'出力ポート
p = a.xform_out

# ポートデータを取得します
(p_name, p_alias, p_datatype, p_porttype, p_isconnected, p_ispromoted) = p.data()

# ポートデータを出力します
BindOutput(p_name, p_alias, p_datatype, p_porttype, p_isconnected, p_ispromoted)

関数から返されるポートのリストを確認:

# xはAPEXポートIDの配列です
x = graph.matchPorts('*xform*')

# 文字列の配列を初期化します
arr = StringArray()

# 配列にポート名を追加します
for p in x:
    p_name = p.data()
    arr.append(p_name)

# ポート名の配列を出力します
BindOutput(arr)

可変長ポート

可変長ポートは、複数の接続を受け取ることができるポートです。可変長ポートに接続すると、ノード上にサブポートが作成されます。

可変長入力

APEX Scriptでは、可変長入力は以下のキーと値のペアで辞書に格納されます:

  • キー - サブポート名

  • 値 - サブポート名

以下の例では、3つの値が追加されます。1つ目の引数は通常の入力で、2つ目の引数は2つのエントリで辞書として格納された可変長入力です。可変長入力のサブポート名は、明示的に設定されます:

x = 3

sum = Add_Int(1, {'bbb': 2, 'ccc': x})
命名された可変長入力のサブポート

可変長入力がノードの最後のポートである場合、サブポート名を指定する必要はありません:

x = 3

sum = Add_Int(1, 2, x)

非可変長ポートに値が指定されない場合、可変長ポートの名前を以下の構文で指定する必要があります:

<function>(<variadic_port>={<subport1>:<value1>, <subport2>:<value2>, ...})

sum = Add_Int(b={'x': 4, 'y': 5})

可変長出力

可変長出力のサブポートに名前を付けるには、キーワード引数<variadic_arg_name>_out=[<subport_names>]を使用します。ここで<subport_names>は文字列の配列です。

以下の例は、IntBitMaskToBoolから可変長出力を取得します:

input: Int = BindInput(8)

# 'aa'、'bb'、'cc'、'dd'と命名される可変長出力のサブポート
a,b,c,d = input.IntBitMaskToBool.v2_0(mask__out=['aa', 'bb', 'cc', 'dd'])

# サブポート値を出力します
BindOutput(input,a,b,c,d)
命名された可変長出力のサブポート

キーワード引数が指定されない場合、サブポート名は変数名に設定されます:

input: Int = BindInput(8)

# 'a'、'b'、'c'、'd'と命名される可変長出力のサブポート
a,b,c,d = input.IntBitMaskToBool.v2_0()

# サブポート値を出力します
BindOutput(input,a,b,c,d)
APEX Script変数名に設定された可変長出力のサブポート

辞書エントリは任意の型が可能であるため、dict::Extractを使用して辞書エントリを抽出するには、辞書エントリを抽出したい変数の型を最初に指定する必要があります:

# 辞書エントリの型を指定する
a: Int
b: Float
c: Vector3

dict_test = {
    'aa': 5,
    'bb': 0.2,
    'cc': (5,10,15)
}

a,b,c = dict_test.extract(args__out=['aa', 'bb', 'cc'])

BindOutput(a,b,c)
dict::Extractから可変長出力のサブポートを取得

グラフテンプレート

APEX Scriptでは、関数をグラフテンプレートのように扱うことで、既存のグラフにロジックを簡単に追加できます。APEX Scriptを使用して、エクスプレッションとロジックを1つの関数として記述し、この関数を既存のグラフに直接挿入して、その機能を変更することができます。

APEXリギングでは、キャラクタリグはグラフとして表現されます。リバースフットやLook Atの機能を持つ関数がある場合、この関数を入力キャラクタリググラフに挿入して、キャラクタの最終的なリグをプロシージャルに構築できます。

Note

関数を呼び出すと、現在のAPEX Scriptの関数ロジックが実行されるだけです。関数ロジックを別のグラフ(入力リグなど)で使用するには、関数を入力グラフに挿入する必要があります。

この例では、入力ノードと出力ノードのみを含む入力リググラフから始めます。

元のリググラフ

次にAPEX Script SOPを使用して、入力リググラフに簡単な数学的演算を追加します:

リグにロジックを追加
  1. APEX Script SOPで、定義済みのヘッダを使用して、入力グラフを受け取って変更するAPEX Scriptコマンドを自動的に追加します:

    • Header パラメータをオンにします。

    • Header セクションで、 TemplateGraph に設定します。

  2. APEX Script SOPへの入力を指定します。 Invocation セクションの Input1 Bindings で、 Bind To Geometry Parameter をオンにして、そのパラメータをgeoに設定します。

  3. 更新されたリググラフを出力するには、 Bind Output Geometryoutput:geoに設定します。

  4. 以下のコードを Snippet パラメータに追加します。このコードは、graph::AddSubnetを使用して、関数testサブネットとして入力グラフに追加します:

    # 入力グラフに追加する機能
    def test(a: vector3, b: float) -> tuple(vector3, float):
        a = a * b
        b = b + 1.0
        return a, b
    
    # 関数'test'を'my_test'という名前のサブネットとして入力グラフに追加します
    my_subnet = graph.addSubnet(test, 'my_test')
    
    # サブネットを入力グラフの入力ノードに接続します
    my_subnet.a_in.promote('aa')
    my_subnet.b_in.promote('bb')
    
    # サブネットを入力グラフの出力ノードに接続します
    my_subnet.a_out.promote('aa')
    my_subnet.b_out.promote('bb')
    
  5. APEXネットワークビューで更新されたリググラフを確認するには:

    • APEX Script SOPの Visualizer セクションで、 ShowOutput 1 に設定します。

      または

    • APEX Script SOPの1番目の出力をNull SOPに接続し、Null SOPを選択します。

    更新されたリググラフ

    my_testサブネットの中に入り、APEX Scriptコードから関数testのグラフロジックを表示します:

    サブネット'my_test'の内容

Note

上記の例では、graph::AddSubnetを使用して、関数をサブネットとして入力グラフに追加しています。また、graph::Mergeを使用すると、関数をサブネットにパックすることなく、入力グラフに直接結合することも可能です。ただし、結果のグラフには複数のグラフ入力および出力ノードが含まれる可能性があり、その場合はそれらを適切なノードに接続しなければなりません。graph::AddSubnetを使用する方法の方がすっきりとしています。

グラフテンプレートなしでリグロジックを追加する

関数をテンプレートとして使用しない場合、前の例と同じロジックを作成するAPEX Scriptコードは、はるかに複雑になります。この場合では、入力リググラフに機能を追加する唯一の方法は以下の通りです:

  1. 個々の数学的なノードを追加します。

  2. 各ノード接続をスクリプト化します。

  3. 上のロジックをサブネットにパックします。

  4. サブネットをメイングラフに接続します。

以下は、関数をグラフテンプレートとして使用しないで前の例と同じロジックを作成したコードです:

# グラフにノードを追加します
mult = graph.addNode('MultiplyExpr', 'Multiply<Vector3,Float>')
add = graph.addNode('AddExpr', 'Add<Float>')
val = graph.addNode('Value_right', 'Value<Float>', parms={'value':1.0})

# Multiplyノードをグラフ入力および出力に接続します
mult.a_in.promote()
mult.b_in.promote('b')
mult.result_out.promote('a')

# Addノードをグラフ入力および出力に接続します
add.a_in.promote('b')
add.result_out.promote('b')

# ValueノードをAddノードに接続します
val.value_out.connect(add.b_in)

# ノードを(接続を維持しながら)サブネットにパックします
# サブネットの出力名はデフォルト値に設定されます
node_arr: ApexNodeIDArray = [mult, add, val]
graph.packSubnet('my_test', node_arr)

別のグラフを呼び出す

InvokeOutputs()は、別のグラフを実行するために使用される特殊関数です。入力がグラフである場合、InvokeOutputs()を使用してそのグラフ入力を実行できます。

この例では、InvokeOutputs()は関数fooを実行します:

def foo (a: Int, b: Int) -> tuple[Int, Int]:
    return b, a

x: Int
y: Int

x, y = InvokeOutputs(foo, parms={"a": 1, "b": 2}, outputs=["output:a", "output:b"])
別のグラフを呼び出すロジック
関数fooを呼び出す

InvokeOutputs()の構文:

InvokeOutputs(<function>, parms=<dict>, outputs=[array of strings])

ここでは:

  • parms - 関数に渡すパラメータ値の辞書。

  • outputs - 関数によって返される値を指定する文字列の配列。文字列の形式は<output_node>:<output_port>で、<output_node>は関数グラフの出力ノードです(ここでは関数foo)。

outputs引数は、関数の戻り値と一致します。上記の例では:

  • output:aは関数の戻り値aに設定されます。変数xoutput:aに設定されます。

  • output:bは関数の戻り値bに設定されます。変数youtput:bに設定されます。

関数のreturnステートメントにエクスプレッションが含まれる場合、outputs引数をresult<x>に設定します。ここでxは、0で始まる関数の戻り値の位置です:

def foo(a: Int):
    return a+1

x: Int = InvokeOutputs(foo, parms={"a": 1}, outputs=["output:result0"])

# 戻り値の型を指定する別の方法
y = Int(InvokeOutputs(foo, parms={"a": 2}, outputs=["output:result0"]))

関数のreturnステートメントにエクスプレッションが含まれる場合、戻り値の順序が重要です。エクスプレッションではない戻り値の場合、対応するoutputs引数をoutput:<variable>に設定する必要があります:

# エクスプレッションを使用した関数の戻り値(a+bおよびa*b)
def foo(a: Int, b: Int):
    return a+b, a, a*b

x: Int
y: Int
z: Int

# 関数はoutput:result0でa+bを返し
# output:result2でa*bを返します
x, y, z = InvokeOutputs(foo, parms={"a": 1, "b": 2}, outputs=["output:result0", "output:a", "output:result2"])

Tip

関数がエクスプレッションではなく、変数のみを返すようにすると、読み取りやすいうえ、エラーが発生しにくくなります。

関数から特定の値のみを取得します:

def foo(a: Int, b: Int):
    return a+b, a, a*b

x: Int

# 関数fooからa*bの戻り値のみを取得します
x = InvokeOutputs(foo, parms={"a": 1, "b": 2}, outputs=["output:result2"])

APEXノードIDをグラフに関連付ける

複数のグラフがある場合、特殊関数setGraph()を使用して、ノードIDを特定のグラフに関連付けることができます:

graph1: ApexGraphHandle = BindInput()
graph2 = ApexGraphHandle()

my_node: ApexNodeID = BindInput()

# my_nodeとgraph2を関連付けます
my_node.setGraph(graph2)

複数のノードIDを異なるグラフに関連付けます:

graph1: ApexGraphHandle = BindInput()
graph2 = ApexGraphHandle()

node_arr = ApexNodeIDArray()

# APEXノードIDを配列に追加します
for i in range(4):
    node_arr.append(Value_ApexNodeID_())

# node_arr[1]のノードIDをgraph2に関連付けます
x = node_arr[1]
x.setGraph(graph2)

# node_arr[2]のノードIDをgraph1に関連付けます
# setGraph()を呼び出す別の方法
y = node_arr[2]
setGraph(y, graph1)

グラフをAPEX Scriptコードに変換する

APEX ScriptAPEX Autorig ComponentAPEX Rigscript Component SOPには、グラフをAPEX Scriptコードに変換するためのオプションが用意されています。

APEX Script SOPの場合:

  1. APEX Script SOPの2番目の入力に既存のグラフを接続します。

  2. Decompile セクションで、ドロップダウンメニューを Second Input に設定します。

  3. Convert to Snippet ボタンをクリックします。

APEX Scriptコードが Snippet パラメータに表示されます。

逆コンパイルされたコードに追加できる特殊関数を参照してください。

How to

To...Do this

関数から返されるポートを確認する

単一のポートIDを表示します:

# xはAPEXポートIDです
name = x.data()
BindOutput(name)

ポートIDのリストを表示します:

# xはAPEXポートIDの配列です
x = graph.matchPorts('*xform*')

# 文字列の配列を初期化します
arr = StringArray()

# 配列にポート名を追加します
for p in x:
    p_name = p.data()
    arr.append(p_name)

# ポート名の配列を出力します
BindOutput(arr)

ポート名を表示するには:

  1. APEX Script SOPInvocation セクションで、 Output Dictionary Bindings の横にあるをクリックします。

  2. Geometry Spreadsheetで、上部のツールバーの Detailをクリックします。

KineFX

概要

キャラクタ要素の準備

APEXグラフを使用したリギング

APEXスクリプトを使用したリググラフの構築

リグコンポーネントを使用したリギング

ビューポート内でアニメーションを付ける

SOPベースのアニメーション

変形

アニメーションのリターゲット

H20以前

ペイン

別表