« スクリプトマネージャの「メニューの状態」 | トップページ | 前回のスクリプトのやり直し »

選択された複数のオブジェクトを処理

オブジェクトマネージャでオブジェクトが複数選択されるとmain()関数に渡される変数opはNULLになる。もちろんBaseDocumentクラスのGetActiveObject()メンバ関数もNULLを返す。
そこで、BaseList2DクラスのSearchNext()メンバ関数を使う。このSearchNext()関数はアクティブオブジェクト以外にもアクティブタグやアクティブマテリアルにも使える。では具体的にアクティブオブジェクトを探すにはどうするのか?

aobj = obj->SearchNext(BIT_AOBJ);//次のアクティブオブジェクトを探せ

現在、変数objが指し示しているオブジェクト(アクティブか否かは関係なく)に対してリスト上次のアクティブオブジェクトを変数aobjに返す。示しているオブジェクト以下にアクティブオブジェクトがなければ変数aobjにNULLを返す。SearchNext()関数へ渡す数値は、定数BIT_AOBJ。
では、選択した全てのオブジェクトをグローバル座標の原点(0.0 , 0.0  , 0.0)へ配置するスクリプト。

/*
選択した全てのオブジェクトをグローバル座標の
原点(0.0 , 0.0 , 0.0)に配置

Copyright(c)2008/5/23 村人とC4D
*/

var gm = new(Matrix);//グローバル座標(0.0 , 0.0 , 0.0)のためのマトリクス
var ob = doc->GetFirstObject();//リストの最初のオブジェクトを得る

if(!(ob->GetBit(BIT_AOBJ)))ob = ob->SearchNext(BIT_AOBJ);//リストの最初のオブジェクトが最初のアクティブオブジェクトでなければ本当の最初のアクティブオブジェクトを探す

if(!ob)return;//アクティブオブジェクトが1つもなかったら処理を中断

//アクティブオブジェクトの捜索
while(ob){
  ob->SetMg(gm);//デフォルトのグローバルマトリクスを適用

  ob = ob->SearchNext(BIT_AOBJ);//次のアクティブオブジェクトを探す
}

GetFirstObject()はリストの最初のオブジェクトなだけなので、必ずこれがアクティブか否かを確かめなければなりません。BaseList2DクラスのGetBit()メンバ関数でアクティブオブジェクトか否かを確かめます。渡す定数はSearchNext()関数と共通。共通ということはSearchNext()関数同様アクティブタグやアクティブマテリアルにも使えるということですね。アクティブならTRUE、でなければFALSEが返る。
なんとなくこれで良いような気がするが…確かに動作します。オブジェクトが複数選択されていても、まったく選択されていなくてもエラーは起こりません。今回の「複数選択」に対しては、良いでしょう。ただしグローバル座標(0.0 , 0.0 , 0.0)に配置という点ではNGですよね。確かに座標はOKなんですが、回転とスケールも(0.0 , 0.0 , 0.0)(1.0 , 1.0 , 1.0)になってしまいますよね。思い込みでザックリ打ってみたらこういう事になりがちなんだよね。これはコードが超短いから良いけど、長いと結構見付けずらいかも…

var gm;//宣言のみで初期化しない
var
ob = doc->GetFirstObject();

if(!(ob->GetBit(BIT_AOBJ)))ob = ob->SearchNext(BIT_AOBJ);
if(!ob)return;

while(ob){
  gm = ob->GetMg();//アクティブオブジェクトのグローバルマトリクスを得る
  gm->SetV0(vector(0.0));//マトリクスの座標にあたるV0を(0.0 , 0.0 , 0.0)にする
  ob->SetMg(gm);

  ob = ob->SearchNext(BIT_AOBJ);
}

と、こんな感じですね。ただし選択されたアクティブオブジェクトのみグローバル座標(0.0 , 0.0 , 0.0)にして、その子オブジェクトはグローバル座標上変化させないのであれば、子オブジェクトのグローバルマトリクスを記憶してアクティブオブジェクトを座標移動してから、子オブジェクトに記憶したグローバルマトリクスを適用、複数子オブジェクトがあるなら子オブジェクトを数えて複数記憶するすると…今回は複数選択だからやらない。
後は「メニューの状態」。これは1個でもアクティブオブジェクトがあればENABLEはTRUE、出なければFALSE。

var obj = doc->GetFirstObject();
if((obj->GetBit(BIT_AOBJ)) || (obj->SearchNext(BIT_AOBJ)))ENABLE = TRUE;
else ENABLE = FALSE;

複数選択でも1個でも、何も選択しなくてもエラーは起きてませんね。「メニューの状態」で変数の宣言をしてみました。問題なく動いてますね。これで変数の宣言も可能だということが分かります。スクリプトは「Global_to_00.ZIP」です。時間が無かったので説明が薄いですね。次の更新で…?
ここで重要なことが抜けています。解る人には解る重要な事。それはいつの日か…
さらに続く。

|

« スクリプトマネージャの「メニューの状態」 | トップページ | 前回のスクリプトのやり直し »

コメント

この記事へのコメントは終了しました。