AssetLibrary(HDA)


はじめに

プロダクトで使用しているHDAやツールを少しずつ紹介できればと思い投稿いたします。
今回はFBXファイルを読み込むアセットライブラリーツールです。本使用しているものの機能を一部ご紹介します。

前提条件

Houdini Core 17.0.352にて作成しています。
尚Houdini 18.0.287にて動作確認済みです。

どんなもの?

他のDCCツールにて作成したアセットを読み込むためのHDAです。
FBXファイルを指定したディレクトリに配置するとプルダウンメニューで選択可能となります。

ディレクトリ構造

AssetsLibrayの直下に各カテゴリー毎のフォルダが有り、更にそれぞれShotogunに登録されているID毎のフォルダにデータが格納されています。
ID毎のフォルダは作業用のファイルも格納するようにしているため仕様書(図面)、作業用ファイル(.max .maya)、Shotgun登録用サムネイル画像、FBXファイルが存在します。

必要になった経緯

アセットは都度作成しているため、都度読込用の設定をするのは手間なので
作成されるディレクトリを自動認識してプルダウンメニューで選べるようにしました。

Python

Parameter Callback Script

HDA埋め込みスクリプト


import os
import fnmatch

def norm_dir(path):
    return path.replace("\\", '/')

def CollectCategory(node):
    root = norm_dir(node.parm('lib_root').eval())
    cat = []
    for i in os.listdir(os.path.join(root)):
        if os.path.isdir(os.path.join(root,i)):
            cpath = norm_dir(os.path.join(root, i))
            cat.append(cpath.split('/')[-1])
    return sorted(cat)

def CategoryMenu(node):
    menu = []
    for i in CollectCategory(node):
        menu.append(i)
        menu.append(i)
    return menu

def CollectLib(node):
    root = node.parm('lib_root').eval()
    cat = node.parm('cat').eval()
    path= norm_dir(os.path.join(root, cat))
    matches = []
    for i in os.listdir(path):
        filename = os.path.join(path, i, i+".fbx")
        if os.path.exists(filename):
            matches.append(i)    

    return sorted(matches)

def LibMenu(node):
    menu = []
    for i in CollectLib(node):
        menu.append(i)
        menu.append(i)
    return menu

def GetFilename(node):
    assets = CollectLib(node)
    name = node.parm('lib_name').eval()
    if not name in assets:
        name = assets[0]

    root = node.parm('lib_root').eval()
    cat = node.parm('cat').eval()
    path = norm_dir(os.path.join(root, cat, name, name+".fbx"))
    if os.path.exists(path):
        return path

    return ""

Library Root で指定したディレクトリ以下のディレクトリ、パスを取得してfbxファイルのパスを取得します。また、プルダウンメニュー用に配列を生成します。
def は関数の定義。

Prameter Description

HDAのパラメーターに使用するスクリプト

Menu Script

プルダウンメニューを生成する
Parameter Callback Script のdef CollectCategory(node)def LibMenu(node)で生成した配列をプルダウンメニューに呼び出します。

Channels Script

Parameter Callback Script のdef GetFilename(node)で取得したfbxファイルのパスを呼び出します。

ノードネットワーク

ネットワーク自体はfbxファイルを読み込んでスケール調整用のノードとアトリビュート削除を追加しているシンプルなものです。
※ 3dsMaxでアセットを作成していた場合は attribdeleteMaxHandle UDP3DSMAX を削除する。これは3dsMax→Mayaの場合も同様。
chs() 入力したパスのパラメータの文字列を返す。

使用方法


Library Root

ライブラリーのルートパスを指定します。
ここでは仮に$HIP/AssetsLibrary としています。
JOB でも構いません。ただしこの場合はhipファイルを保存する前やプロジェクト設定せずにこのHDAを呼び出すとスクリプトエラーとなります。
したがって本プロジェクトにおいては予め AssetLibrary ディレクトリを環境変数(houdini.env)にセットしておいて $~で呼び出しています。

Category

アセットを種類毎に分類していてプルダウンメニューから選択できます。

Library Name

Category で選択されたディレクトリ内に格納されているFBXファイルを選択することができます。

Filename

FBXファイルのパスを取得するのにパラメーターを作成はしていますが、触る必要がないので非表示にしています。

Scaling

配置後にスケール調整をできるようにしてあります。

実際には

上記で紹介したものは実際に使用しているものを分かりやすくしたものです。
実際は

  • 上位カテゴリーがあるためもう少しディレクトリ構造が複雑。
  • カテゴリー名やライブラリー名をアトリビュートに付与している。
  • 方向判別のためのポイント追加。
  • Parameter Callback Script にpython moduleの他に HDAを作成した時に実行される OnCreated にデフォルト値を設定。

のように少々手を加えています。
上記の目的は他の工程からこのHDAを呼び出し自動でアセットを判別、配置させるためです。アセットの自動選択はShoutGunに登録されている情報と紐付けて処理を行っています。

終わりに

品番管理されているアセットなどを読み込むライブラリーツールとして重宝していますが、もう既に別の手法で良い方法があるかもしれません。作成したヴァージョンもHoudini17.0時点ですので少々古くなってしまっています。何かのヒントになれば幸いです。

参考

Python スクリプトの場所
hou.HDAModule
soptoolutils module
HoudiniのParameter Interfaceで使えるPython ① - Qiita
HoudiniのParameter Interfaceで使えるPython② - Qiita
Menu scripts in HDA
サルにもわかる Houdini: houdini environment variables
Houdini × Python
Pythonで関数を定義・呼び出し(def, return) | note.nkmk.me