« C4D C.O.F.F.E.E.のグローバル変数 | トップページ | C4D C.O.F.F.E.E.SDK GeModalDialogの頁の誤 »

C4D C.O.F.F.E.E.Undo…

なんて事だ…

今まで、Undoの解釈を間違って覚えていたなんて…
Undoを参考にされた方、ごめんなさい…

賢い方は、気付いていたかも知れませんが…

さて、Undoについて、なぜ間違いに気付いたのか?
と、言う所からお話しましょう。

C4Dには、C.O.F.F.E.E.(ユーザスクリプト)を作成する為の簡単な支援機能があります。

ご存知のように、属性マネージャ等の項目をスクリプトマネージャやエクスプレッソエディタ等にドロップができ、項目へのアクセスする為の定数が自動入力されます。

R10以降には更に、コマンドマネージャからのドロップは、CallCommand()が、コマンドID付で自動入力されます。

R11からは、属性マネージャ等の項目を右クリック(Win)(Mac:Cmd+クリック)すると現れるコンテキストメニューから「スクリプトを作成...」を実行すると、スクリプトマネージャが開かれ、現在の値が入力されるスクリプトが自動生成されます。

例えば、立方体のサイズX/Y/Zについて、

Undo_01_3 Undo_03 Undo_02_2 Undo_03_2 Undo_04_2

その生成されたスクリプトを見てみましょう。
object()関数が使われているので、選択された全てのオブジェクトを対象にオブジェクトのPRIM_CUBE_LINEが示す項目にvector(200 , 200 , 200)を設定。

ENABLE=TRUE;

var i;
for (i=0; object(i); i++)
{
  doc->AddUndo(UNDO_CHANGE_SMALL,object(i));
  object(i)#PRIM_CUBE_LEN=vector(200,200,200);
  object(i)->Message(MSG_UPDATE);
}

このスクリプトの欠点は、クラスチェックが無いから、立方体以外のオブジェクトが選択されているとエラーが起こります。

自分がこのスクリプトから得られる知識は…
BaseDocument::AddUndo()とBaseList2D::Message()かな…

BaseList2D::Message()
BaseList2Dメンバ関数のMessage()は、今まで「ポイントオブジェクトのポイントの座標」や「スプラインのハンドルベクトル(Tangent)」を変更した時のみ実行していました。
が、これを見るとプリミティブのサイズを変えたときにも実行しなければいけないと言う事だろうか。

C.O.F.F.E.E. SDKには、「オブジェクトの何かが変わった。例えばポイントの位置…」

その「何か」とは?オブジェクトを構成するもの1つでも変化したら…という事かな。
半信半疑ではあるが…

BaseDocument::AddUndo()
このスクリプトには自分が記述していたStartAndo()とEndAndo()がありません。

変更するオブジェクトが一個の時は、

doc->StartUndo();
doc->AddUndo(UNDO_OBJECT_BASEDATA , op);
doc->EndUndo();

複数の時は

doc->StartUndo()
for(c = 0 ; object(c) ; c++){
  doc->AddUndo(UNDO_OBJECT_BASEDATA , object(c));
}
doc->EndUndo();

//オブジェクトに対しての変更する処理

もしくは、

doc->StartUndo()

for(c = 0 ; object(c) ; c++){
  doc->AddUndo(UNDO_OBJECT_BASEDATA , object(c));

  //オブジェクトに対しての変更する処理

}

doc->EndUndo();

と、1回のスクリプト実行単位でStartUndo()とEndUndo()の中に変更する前のオブジェクトをAddUndo()で記録していました。

自動生成されたスクリプト見る限りでは、AddUndo()単体で、変更する全てのオブジェクトを記録しています。

確かC.O.F.F.E.E.SDKには…
「複数のUndoはStartUndo()とEndUndo()の間になければいけない。さもなければ、おかしな事が起こる…。」

まるで、タタリでも起きそうな…そんな風に書いてあったような記憶がある。
英語が苦手だから、微妙なところがわからないんだよね。読み違いか?解釈の違いか?

もしかすると、「実行スクリプト単位で複数のUndo」ではなく、「複数のオブジェクトのUndo」でもなく、「1つのオブジェクトに対して複数のUndo」なのだろうか?

だから、自動生成されたスクリプトには、AddUndo()単体しかないのだろうか?

でも、1つのオブジェクトに複数回Undoを記録することはあるだろうか?

スクリプト実行直後に対象オブジェクトをAddUndo()で記録。
そのあと、オブジェクトに好きなだけ変更処理を加えスクリプトを終了。
スクリプト終了後、取り消しを実行すればスクリプト中のたった1回のAddUndo()でもスクリプト実行前の状態に戻れますが…

結論は出せず今のところ、予測でしかありません。
もう少し、SDKを読んでみます。

|

« C4D C.O.F.F.E.E.のグローバル変数 | トップページ | C4D C.O.F.F.E.E.SDK GeModalDialogの頁の誤 »