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.skel
やBase.shp
などのジオメトリ名を持つリグを処理できます:
x = BindInput(Base__dot__shp=Geometry()) Base__dot__skel: Geometry = BindInput() BindOutput(Base__dot__skel, Base__dot__shp=x)

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

Attribute Adjust Dictionary SOP
Attribute Adjust Dictionary SOPは、入力値の辞書を定義します。 ここでは2つのAttribute Adjust Dictionary SOPに対して以下の値を設定します:
input_dictionary1
-
Attribute Name =
parms1
。デフォルトでは Attribute Class が Detail に設定されているので、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 }
-
Snippet パラメータに以下のコードを記述します:
int1: Int = BindInput() int2: Int = BindInput() abc: String = BindInput() BindOutput(int1,int2,abc)
Note
出力をバインドしない、または、入力値に対して何も行なわない場合は、入力に対して何も行なわれないので、グラフには何のロジックも表示されません。
-
入力辞書を指定します。 Invocation セクションで:
-
Input1 Bindings の Dictionary To Bind をオンにして、APEX Script SOPの1番目の入力に接続する辞書、この例では(Attribute Adjust Dictionary SOPの Attribute Name パラメータで指定した)
parms1
を指定します。 -
Input2 Bindings の Dictionary To Bind をオンにして、APEX Script SOPの2番目の入力に接続する辞書、この例では
parms2
を指定します。
このAPEX Script SOPは、それらの入力辞書の
parms1
とparms2
を見て、int1
、int2
、abc
のキーを持つエントリーを探します。 複数の辞書にそれらのキーが存在する場合、後者の辞書エントリーが使用されます。 この例では、どちらの辞書にもabc
キーのエントリーがあるので、2番目の辞書のabc
エントリーが使用されます。 さらに、このAPEX Script SOPには警告が出ます。 -
-
デフォルトでは、 Output Dictionary Bindings の1番目のエントリーには、以下の内容が設定されます:
-
Apex Outputs Group は
output
に設定されます。これは、グラフ内の出力ノードの名前です。 -
Output Attrib は
parms
に設定されます。ここには、出力辞書の名前を設定することができます。
Geometry Spreadsheetでグラフ出力を確認するには:
-
Geometry Spreadsheetで、ノード名の横にあるドロップダウンメニューから Invoked を選択します。
-
上部のツールバーの
Detailをクリックします。グラフ出力は、 Output Attrib で指定された辞書、この例では
parms
に格納されています:parms: {"abc": "hi again", "int1": 2, "int2": 4 }
-
複数の出力のバインド ¶
特殊関数引数の__name
を持つBindInput
関数とBindOutput
関数を使用してノードに名前を付けることで、グラフが複数の入力ノードと出力ノードを持つように設定することができます:
-
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')
複数の入力ノードと出力ノードを持つグラフ -
デフォルトでは、 Output Dictionary Bindings の1番目のエントリーには、以下の内容が設定されます:
-
Apex Outputs Group は
output
に設定されます。これは、グラフ内の出力ノードの名前です。 -
Output Attrib は
parms
に設定されます。ここには、出力辞書の名前を設定することができます。
Geometry Spreadsheetでグラフ出力を確認するには:
-
Geometry spreadsheetで、ノード名の横にあるドロップダウンメニューから Invoked を選択します。
-
上部のツールバーの
Detailをクリックします。APEX Script SOPでは
output
ノードの値のみを出力するようにしたので、parms
辞書のみが表示されています。
-
-
output2
ノードの値も出力するようにするには:-
Output Dictionary Bindings の横にある
をクリックします。
-
新しいエントリーには、 Apex Outputs Group を
output2
に、 Output Attrib を例えばparms2
に設定します。
すると、Geometry Spreadsheetには、
parms
とparms2
の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)

辞書エントリは任意の型が可能であるため、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)

グラフテンプレート ¶
APEX Scriptでは、関数をグラフテンプレートのように扱うことで、既存のグラフにロジックを簡単に追加できます。APEX Scriptを使用して、エクスプレッションとロジックを1つの関数として記述し、この関数を既存のグラフに直接挿入して、その機能を変更することができます。
APEXリギングでは、キャラクタリグはグラフとして表現されます。リバースフットやLook Atの機能を持つ関数がある場合、この関数を入力キャラクタリググラフに挿入して、キャラクタの最終的なリグをプロシージャルに構築できます。
Note
関数を呼び出すと、現在のAPEX Scriptの関数ロジックが実行されるだけです。関数ロジックを別のグラフ(入力リグなど)で使用するには、関数を入力グラフに挿入する必要があります。
この例では、入力ノードと出力ノードのみを含む入力リググラフから始めます。

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

-
APEX Script SOPで、定義済みのヘッダを使用して、入力グラフを受け取って変更するAPEX Scriptコマンドを自動的に追加します:
-
Header パラメータをオンにします。
-
Header セクションで、 Template を Graph に設定します。
-
-
APEX Script SOPへの入力を指定します。 Invocation セクションの Input1 Bindings で、 Bind To Geometry Parameter をオンにして、そのパラメータを
geo
に設定します。 -
更新されたリググラフを出力するには、 Bind Output Geometry を
output:geo
に設定します。 -
以下のコードを 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')
-
APEXネットワークビューで更新されたリググラフを確認するには:
-
APEX Script SOPの Visualizer セクションで、 Show を Output 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コードは、はるかに複雑になります。この場合では、入力リググラフに機能を追加する唯一の方法は以下の通りです:
-
個々の数学的なノードを追加します。
-
各ノード接続をスクリプト化します。
-
上のロジックをサブネットにパックします。
-
サブネットをメイングラフに接続します。
以下は、関数をグラフテンプレートとして使用しないで前の例と同じロジックを作成したコードです:
# グラフにノードを追加します 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"])


InvokeOutputs()の構文:
InvokeOutputs(<function>, parms=<dict>, outputs=[array of strings])
ここでは:
-
parms - 関数に渡すパラメータ値の辞書。
-
outputs - 関数によって返される値を指定する文字列の配列。文字列の形式は
<output_node>:<output_port>
で、<output_node>
は関数グラフの出力ノードです(ここでは関数foo)。
outputs
引数は、関数の戻り値と一致します。上記の例では:
-
output:a
は関数の戻り値a
に設定されます。変数x
はoutput:a
に設定されます。 -
output:b
は関数の戻り値b
に設定されます。変数y
はoutput: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 Script、APEX Autorig Component、
APEX Rigscript Component SOPには、グラフをAPEX Scriptコードに変換するためのオプションが用意されています。
APEX Script SOPの場合:
-
APEX Script SOPの2番目の入力に既存のグラフを接続します。
-
Decompile セクションで、ドロップダウンメニューを Second Input に設定します。
-
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) ポート名を表示するには:
|