MAXScriptで効率UP!! ~Fume&ThinkingParticles編~
2014/8/4
お久しぶりです。最近はこの暑さに負けて溶けそうな山城です。去年は夏バテになってしんどい二週間を過ごしました…orz
夏バテや熱中症にならないように皆さんも気をつけて下さい!私も気をつけますッ
ということで本題に…前回の記事の時に「DotNetを使用したMAXScriptのツールやUI周りを書こうかな」と宣言していましたが
やっぱりもう少し需要がありそうなネタを…DotNetは次回に回します!
今回はMAXユーザーでは入れている方も多いFumeとThinkingParticles(以下TP)へMAXScriptでアクセスする方法を紹介しようかなと思います!
弊社でもこの二つのPluginに関しては使用頻度も高い為、幾つかツールを用意しております。
キャッシュの差し替え、書き出し、TPのアトリビュートの一括変更ツールなど。
手動でやるには面倒だけど、Scriptを書きたくても資料などが余り無いから…と手動でやってたり
フリーのスクリプト探してみたりなどしている方も居るのではないでしょうか?
今回はデザイナーさん向けにFumeとTPの簡単な作業効率UPスクリプトを少し紹介していきます。
MaxScriptの基本の部分は前回の記事をご覧下さい。
https://dftalk.jp/cp-bin/wordpress/?p=11583
ではまずはFumeから紹介します。
【Script動作環境】
3dsMax -> 2013
ThinkingParticles -> 5.3
FumeFX -> 3.5.2
上記のバージョンを使用しております。
FumeFX編
シーン内に複数のFumeコンテナを配置して一つ一つキャッシュを変更…メンドクサイ!!
こんな時に一括で変更出来るScriptがあればッ!!!という時に便利なキャッシュを一括で変更させるScriptを紹介したいと思います♪
◇FumeObjectの取得
まずはシーン内のFumeObjectの取得方法です。
--選択されているObjectを取得 selectobj = selection --シーン内にある全てのObjectを取得 sceneobj = objects --リストの作成 FumeObj = #() --Fumeを探してリストで返す関数 fumelist = GetFumeObjects sceneobj FumeObj function GetFumeObjects SearchObj FumeList = ( if SearchObj.count != 0 then ( for obj in SearchObj do ( --objのクラスを取得 GetClass = classof obj --クラスがFumeFXだった場合 if GetClass == FumeFX then ( print ("FumeObj :" as string + obj.Name as string) --リストに追加します append FumeList obj ) ) ) return FumeList )
これでシーン内にあるFumeObjが取得出来ます。
選択されているものから取りたい場合は「GetFumeObjects」に渡す引数を
sceneobjからselectobjに変更してみて下さい。
Fumeのアトリビュートはほぼ全てが、スクリプトからアクセスする事が出来ます。
数が多いので探す時間と体力が掛かりますが…頑張ればUI自体をカスタマイズする事も可能です~
◇CachePath差し替えScript
Fumeの取得部分と合わせてCachePathを変更させるScriptが下記のものになります。
【使用方法】
・差し替えるCacheが入っているフォルダのパスをChangePathに入れる
・MAXScriptEditorで実行
-- ChangePath : 差し替えるキャッシュが入っているフォルダを指定 -- FumeObj : 取得したFume -- FumeDir : キャッシュパスのTypeを指定 [default or wavelet or retimer] function Cache_Replace ChangePath FumeObj FumeDir= ( -- FumeのCachePathを取得 FumePath = FumeObj.GetPath FumeDir -- ディレクトリの取得 dir = getDirectories ChangePath -- FumeFX_Test_0000.fxdだと「FumeFX_Test_」の部分を取得する fFile = getFiles(dir[1] + "*.fxd") -- ファイル名を取得 filename = getFilenameFile fFile[1] tokens = filterString filename "_" Newfilename = "" for i=1 to tokens.count - 1 do ( Newfilename = Newfilename + tokens[i] + "_" ) ChangePath = (ChangePath+"\\" + Newfilename + ".fxd") print ("PATH = " as string + FumePath as string + " >>>> " as string + "CHANGE : " as string + ChangePath as string) -- CachePathを変更 FumeObj.SetPath ChangePath #(FumeDir) ) function GetFumeObjects SearchObj FumeList = ( if SearchObj.count != 0 then ( for obj in SearchObj do ( --objのクラスを取得 GetClass = classof obj --クラスがFumeFXだった場合 if GetClass == FumeFX then ( print ("FumeObj :" as string + obj.Name as string) --リストに追加します append FumeList obj ) ) ) return FumeList ) --選択されているObjectを取得 selectobj = selection --シーン内にある全てのObjectを取得 secenobj = objects --リストの作成 FumeObj = #() --差し替えたいCacheがあるフォルダのパス ChangePath = "" --Fumeを探してリストで返す関数 fumelist = GetFumeObjects secenobj FumeObj for obj in fumelist do ( Cache_Replace ChangePath obj "default" )
実際に使用する際はChangePathに任意のパスを入れてから使用して下さい!
上記のScriptではシーン内の全てのFumeのパスを変えるようになっています。
選択したものだけを変えたい場合は上記でも記載したようにGetFumeObjectsに渡す
引数を変更して見て下さい。
キャッシュパスのTypeはFumeFXUIのPathsのTypeになります。
[ default ] or [ wavelet ] or [ retimer ]の中でパスを変更したいTypeを指定して下さい。
キャッシュの差し替え以外にもアトリビュートの値を変更したい場合なども、Fumeのリスト
が取得出来ればさまざまなアトリビュートが一括変更出来るようになります。
一つ一つポチポチするのが面倒な時などに使用して見て下さい。
Objが持っているパラメーターを見るには前回の記事でも書いたようにShowコマンドを使用すると
中身がを見ることが出来ます。
ThinkingParticles編
重たいシーンになるとキャッシュを書き出すのにも結構時間がかかると思います。
帰りに複数のシーンを書き出したいけど…という時用のScriptを紹介したいと思います。
Script内に記載されているますがObjectの取得はFumeの時にClassの名前をFumeFX と指定していたと思いますが
この部分をThinkingに変更するとTPのObjectだけを取得する事が出来ます!
基本的にObjectのClass名は作成する時のObjectTypeの名前と一緒です!
以下のScriptは複数のシーン内にあるTPのMasterDynamicのキャッシュを書き出すものになります。
【使用方法】
・Cacheを書き出したい.maxデータを一つのフォルダにまとめていれる
・まとめたフォルダのPathをfloderPathにいれる
・MAXScriptEditorで実行
-- フォルダ内にあるmaxデータを取得 function file_Search folderpath = ( SearchPath = folderpath + "/*.max" -- .max拡張子のファイルを取得 getList = getFiles SearchPath return getList ) -- main function exeSim fPath quit = ( getList = file_Search fPath for file in getList do ( -- maxfileの読み込み loadMaxFile file useFileUnits:true -- Cacheの書き出し tp_cacherecord() -- new sceneにする actionMan.executeAction 0 "16" ) if quit == true then ( -- Maxを終了する quitMax #noPrompt ) ) -- 書き出したいTPのシーンをまとめてあるフォルダパス floderPath = "" -- 処理が終了したときにMAXを閉じるかどうか quit = true exeSim floderPath quit function tp_cacherecord = ( if maxFileName != "" then ( -- シーン内にあるTPを取得 リストで返って来ます。 tps = for o in objects where ( classOf o == Thinking ) collect o for tp in tps do ( MD = tp.masterDynamic -- maxFilePath = シーンのパス cachePath = maxFilePath + "_cache/" -- 「_cache」フォルダを作成 makeDir cachePath -- maxFileName = シーン名 -- ファイル名を取得 filename = getFilenameFile maxFileName record = cachePath + filename + ".tps" -- 書き出しファイルの指定 MD.recordFile = record if MD.recordFile != undefined then ( -- Cacheの書き出し MD.CacheRecord record false false MD.Play = 0 ) ) ) )
このScriptはデータが入っているフォルダ内に新しくcacheフォルダを作成し、その中に書き出すようになっています。
MasterDynamic以外(DynamicSet)のキャッシュも書き出したい場合もあると思います!
MasterDynamicの取得は簡単なんですが、その子を辿っていく方法が分からなくて調べるのが結構大変でしたorz
下記のScriptはシーン内にあるTPのMasterDynamicと全てのDynamicSetのCacheを書き出す物になります。
このScriptは開いているシーンに対して行なわれるものになりますが、上記のScriptのように複数の.maxデータの全てのキャッシュを書き出したい場合は
フォルダ内を検索しデータ開く部分を書き加えれば同じような事が出来ます。
また、書き出したくないものがある場合などは名前指定などの分岐をAllChildrenExportCache関数内に入れて見て下さい。
-- MasterDynamicの子(DynamicSet)のCacheを書き出す function AllChildrenExportCache DSNodes cachePath = ( for child in DSNodes do ( print (" child.name >> " + child.name as string) -- DynamicSetの名前部分を取得 tpname = substitutestring child.name "DS: " "" print tpname record = cachePath + tpname + ".tps" -- Cacheパスを設定 child.CacheFilename = record -- オブジェクトの取得 cObj = child.GetObject() -- Cacheの書き出し cObj.CacheRecord record true true theChildren = (for i = 4 to child.numsubs where (matchpattern child[i].name pattern:"DS:*" ) collect child[i]) AllChildrenExportCache theChildren cachePath ) ) -- MasterDynamicのCacheを書き出す関数 function MasterCacheExport cachePath masterdyn = ( record = cachePath + "MasterDynamic.tps" masterdyn.recordFile = record if masterdyn.recordFile != undefined then ( masterdyn.CacheRecord record false false masterdyn.Play = 0 ) ) -- Cacheを書き出すパスを指定 folderPath = "F:/Fume/test" -- シーン内のTPを取得 scenetps = for o in objects where classof o == Thinking collect o for tp in scenetps do ( -- MasterDynamicの取得 masterdyn = tp.MasterDynamic cachePath = folderPath + "cache/" + tp.name as string + "/" print (" cachePath >> " + cachePath as string) -- cacheフォルダの作成 makeDir cachePath MasterCacheExport cachePath masterdyn -- MasterDynamicの子になっているDynamicSetを取得 DSNodes = (for i = 4 to masterdyn.numsubs where (matchpattern masterdyn[i].name pattern:"DS:*" ) collect masterdyn[i]) AllChildrenExportCache DSNodes cachePath )
資料とかもTPに関しては殆ど無いので何かの参考になればと思います。
取得が出来れば色々と代用が効くと思いますのでキャッシュ意外にも
アトリビュートの変更などにも使用してみて下さい。
この子を辿っていく方法はGroupManagerの方でも同じやり方で取得する事が可能です。
今回のScriptにはUIは付いていませんので、ファイルブラウザなどをつけておくだけでも
だいぶ使いやすくなると思います!
またMaxには簡易にUIを作成できる「Visual MAXScript Editor」というツールが
用意されています。
msファイルへの保存も出来ますので、ここでUIを作成してScript内に組み込めば
簡単にUIを作成する事が出来ますので良かったらお試し下さい。
次回は今回お話出来なかったDotNetを使用したUIの作成についてお話したいと思います!
最後までお付き合いいただきありがとう御座いました!
※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください
コメント
コメントフォーム