max8では正常動作していたスクリプトをmax9で走らせると一部不具合が判明した。
不具合があった箇所というのは、複数のmaxファイルを外部参照オブジェクトとして読み込み、Offset, Rotation, Scaleを
予め用意しておいた数値でアニメーションキーを自動的に打つ部分。
max9では新たなアトリビュートとして「外部参照コントローラ」なるものが用意されていた。
コントローラも外部参照として扱われているので、シーン内でそのオブジェクトに新規にキーを打つことができない状態になっていた。
では、外部参照コントローラだけをシーン合成行うにはスクリプトでどうすればいいか調べてみたところ・・・
・
・
・
結論から言うと、スクリプトのみでは方法が「ない」んです。
maxscriptで外部参照オブジェクトに関して操作する場合、objXRefMgrインタフェースを使用します。
+ MAXScript 言語リファレンス
+ 3ds Max オブジェクト
+ インタフェース
+ コア インタフェース
+ コア インタフェースのドキュメント
+ インタフェース: objXRefMgr
maxscriptリファレンスの上記ツリーを確認してみると、
<Interface>AddXRefItemsFromFile <filename>fileName promptObjNames:<bool> objNames:<string array> xrefOptions:<&enum array>
promptObjNames default value:false
objNames default value: #()
xrefOptions enums:{#asProxy|#xrefModifiers|#dropModifiers|#mergeModifiers|#mergeManipulators|#selectNodes|#mergeMaterials}
xrefOptions default value: #()
xrefOptions は In パラメータです
指定されたレコードに名前の配列を追加します。
とあります。この xrefOptions で本来であれば存在していなければならない #mergeControllers がありません。
つまり max9 においてスクリプトレベルでの制御は不可能ということです。
仕方がないので外部参照オブジェクトを読み込むルーチンのみをプラグインで書き、
スクリプト側からプラグインの関数を呼び出すようにしました。
以下はそのソース。
#include <Maxscrpt/Maxscrpt.h>
#include <maxscrpt/Strings.h>
#include <maxscrpt/arrays.h>
#include <maxscrpt/numbers.h>
#include <maxscrpt/maxobj.h>
#include <maxscrpt/definsfn.h>
#include <XRef/iXrefObjMgr8.h>
def_visible_primitive( MergeXRefControllersFromFile, "MergeXRefControllersFromFile" );
Value* MergeXRefControllersFromFile_cf(Value** arg_list, int count)
{
check_arg_count_with_keys(MergeXRefControllersFromFile, 2, count);
type_check(arg_list[0], String, "第1引数は外部参照オブジェクト先のmaxファイルパスじゃないとダメ");
type_check(arg_list[1], Array , "第2引数は読み込むノード名配列");
try
{
char* full_path_filename = arg_list[0]->to_string();
Array* node_names_array = static_cast<Array*>(arg_list[1]);
Tab<char*> tab_node;
char** node_names = new char*[node_names_array->size];
for( int i=0; i<node_names_array->size; ++i ) {
node_names[i] = node_names_array->data[i]->to_string();
}
tab_node.Append(node_names_array->size, node_names);
IObjXRefManager8* xref_manager = IObjXRefManager8::GetInstance();
IObjXRefRecord* ixrRecord = xref_manager->AddXRefItemsFromFile(full_path_filename, false, &tab_node, XREF_MERGE_CONTROLLERS);
delete[] node_names;
}
catch(...)
{
return new Integer(-1);
}
return new Integer(0);
}
これで、スクリプト側から
MergeXRefControllersFromFile "C:\\hoge.max" #("node1", "node2")
のような感じで呼び出せます。
とりあえず、上記対策を行って正常動作することは確認しました。
っが正直なところ、これくらいは maxscript で対応してくれてもよさそうです。
手元にある max2008 の maxscriptリファレンスを見ても、対応してませんでした。
max2009 はどうなんでしょうね・・