HOME

[移行記事]入力値に応じた対象選択ができるパラメータを作成する

ジョイントリダクションの前準備のためにDeleteをSubnetの外から入力値に応じて指定する仕組みをつくる ※次の記事でその行動自体は不要になったけど。

元記事のデータ

記載日:2024 9/9
https://www.notion.so/55a45ede2b3047c4b5223d9980854e2f?pvs=4
移行する際に目的がわかりづらいなと感じる部分があったので一部加筆、修正しています。
(タイトルも変えました)


概要

subnetworkの中を制御するためのパラメータを作成する際に、操作対象のノードに入力されたポイントの中で制御対象のnameをプルダウンメニューから指定できるようにする。
※記事内ではDeleteによってジョイントを削除していますが、構造を保持する場合はJointDeleteノードを使うことを推奨させていただきます。

環境

Houdini Indie 20.5.332
モデル、モーションはmixamoのY-Botを利用させてもらった

入力ノードのジョイント名をノードパラメータから参照する

比較的頻繁に入力を変更する可能性があり、都度中身が変わるような入力を想定している。
具体的には色んな構造の種類があるジョイント入力に対し、nameでジョイントを指定したい。
このとき、毎回ジョイント名を文字列として入力するのは面倒なのでSubNetworkのパラメータ上で入力ジョイントの一覧から選べるようにする。
また、複数種類の対象を選択できるようにMultiParamBlockで選択対象を指定できるようにする。

  1. SubNetworkを作成し、入力②にボーン構造、入力②にアニメーションを入力するように設定
    入力①のジョイントの一覧から削除対象を選択できるようにする想定
  2. SubNetworkを右クリックしてEditParamaterInterfaceWindowを開く
  3. Folderを作成し、その中にStringアトリビュートを追加
  4. Folderを選択し、FolderTypeをMulitParamBlockに設定
    これでグループ以下のアトリビュートのグループをユーザーが動的に追加できるようになる
  5. 次に追加したStringを選択し、UseMenuにチェック、これでその下のタブからメニュー挙動を操作するPythonを記入できるようになる。
    また、UseMenuの隣のコンボボックスで選択形態をReplaceに変更する。
    ※デフォルトのモードだとバグがあるっぽい?ようでReplaceモードでなら正しく文字列のアトリビュートを認識できた。
  6. 以下のスクリプトをMenuScriptに設定すると入力①のポイントが持つnameアトリビュートの値をリストし、選択項目として設定することができる
    メニュースクリプトはtoriiさんという方のQiita記事が判り易い(後述の参考文献)
    inputs = hou.pwd().inputs() 
    result = []
    
    if len(inputs):
        geo_0 = inputs[0].geometry()
        select_str_list = []
        for _point in geo_0.points():
            current_joint_name = _point.attribValue("name")
            select_str_list.append(current_joint_name)
        result = sum(zip(select_str_list, select_str_list),())
    
    return result

MultiParamBlockの値を参照してジョイントを削除する

次はpamaterで設定した値を取得する。
MultiParamBlockの値を参照するのは微妙にわかりづらいので注意。

  1. SubNetworkの中に入りDetailWrangleとPointWrangleを作成して画像のように接続する
  2. detailWrangleでMultiParamBlockから値を参照するために以下のスクリプトを設定する 1行目のchsはBlockの数、6行目のchsはブロック内のパラメータを指定している 1 行目の方はパラメータ右クリック→PasteRelativeReferenceで参照元の値をペーストできるが、 6行目の方はどのブロックのアトリビュートかを指定するために名称の末尾に1始まりの数字を追加しなければならない
    int mulit_param_count = `chs("../xn__jointremove_1ka")`;
    s[]@remove_target = {};
    
    for (int i=1; i<mulit_param_count+1; i++){
        string s_i = itoa(i);
        push(@remove_target, chs("../target_joint"+s_i));
    } 
  3. pointwrangleに以下のスクリプトを設定する detailWrangleから取得したnameと一致したpointを削除している
    string remove_target[] = detail(1, "remove_target");
    
    foreach(string _delete_target; remove_target){
        if(@name==_delete_target){
            removepoint(0, @ptnum);
        }
    }

これでSubNetworkから入力されたジョイントに合わせてDeleteの対象グループを選択できるようになった。

fish_ball

プロシージャル魚類