« C4D XZ平面のスプラインを基に、XPressoで坂道ポリゴンオブジェクトを整形させてみました。 | トップページ | C4D C.O.F.F.E.E. 列挙? enum »

C4D C.O.F.F.E.E. 関数のプロトタイプ

C.O.F.F.E.E.で関数を作る場合、通常main()関数の前に記述しますよね。

/*
ユーザスクリプト
*/


functionA(p1 , p2)
{
  var res;
    :
    :
  return res;
}


main(doc , op)
{
  var pos = functionA(p1 , p2);//関数functionA()を使用して返ってきた値を変数posへ代入 
}

普通に組むと、この様になるだろう。

でも、関数をmain()関数の後ろに記述する事ができます。

今回は、関数のプロトタイプのネタです。知っている人は読み飛ばしてください。

そもそも、main()関数の後ろに記述しないんで、自分には必要ないなぁ…って思った人もいるだろう。

関数もそんなに作らないし…そんな人もいるだろう。

ユーザスクリプトで、簡単なものを作っているだけなら必要ないだろう。

/*
ユーザスクリプト
*/


main(doc , op)
{
  var pos = functionA(p1 , p2);//関数functionA()を使用して返ってきた値を変数posへ代入 
}


functionA(p1 , p2)
{
  var res;
    :
    :
  return res;
}

通常、この様にスクリプトを組むと、コンソールに…

[FAIL] Script 'xxxx' Line 10 Pos 47 : Variable or Function expectid

エラーが表示されます。

使用する関数が、使用前に定義されていないと言う事。

未定義の関数をmain()関数で使用した為にエラーが起こります。

では、これにプロトタイプ宣言をして見ます。

/*
ユーザスクリプト
*/


functionA(p1 , p2); //プロトタイプ宣言です。

main(doc , op)
{
  var pos = functionA(p1 , p2);//関数functionA()を使用して返ってきた値を変数posへ代入 
}


functionA(p1 , p2)
{
  var res;
    :
    :
  return res;
}

スクリプトの先頭部分で、プロトタイプを記述すると、関数がmain()関数の後ろに記述しても、エラーは起こらず、スクリプトも正常に動きます。

これから使う関数が、どのような物なのか関数名と引数を宣言します。

注)上のスクリプトはイメージなので、別のエラーが出ます。実行しないでください。

これだけ見ると、プロトタイプ宣言が増えるだけで全く意味の無い状態です。

確かに、これだけ単純な構造だと必要ないし、手間が増えるだけですね。

さて、それではプロトタイプは、必要ない機能なのだろうか?

では、具体的なスクリプトで、実験してみます。

C.O.F.F.E.E.SDK R9.5です。

  • 現在選択されているオブジェクトの数を返す関数
  • 現在選択されているオブジェクト全てを配列変数で返す関数

この2つの関数を使って選択されているオブジェクトの名前をコンソールに表示してみます。

通常組み立てると、単純で明快なスクリプトなのですが、あえて複雑にしました。

現在選択されているオブジェクトの数を返す関数

//選択されたオブジェクトの数
GetActiveObjectCount(doc)
{
  var obj = GetActiveObject(doc);
  var c = 0;
  while(obj){
    obj = obj->SearchNext(BIT_AOBJ);
    c++;
  }
  return c;
}

選択されたオブジェクトが無ければ0を返します。
選択されていれば、オブジェクトの数を返します。

選択されたオブジェクト全てを配列変数で返す関数

//全ての選択オブジェクトの配列変数
GetActiveObjectAll(doc)
{
  if(!GetActiveObject(doc))return;
  var objs = new(array , GetActiveObjectCount(doc));
  var c;
  objs[0] = GetActiveObject(doc);
  for(c = 1 ; c < GetActiveObjectCount(doc) ; c++){
    objs[c] = objs[c - 1]->SearchNext(BIT_AOBJ);
  }
  return objs;
}

選択オブジェクトが無ければnilを返します。
選択されていれば、全てのオブジェクトを格納した配列が返ります。

ではmain()関数です。

//全ての選択オブジェクトの名前をコンソールに表示
main
(doc , op)
{
  var c = 0;
  var obj = GetActiveObjectAll(doc);
  if(!obj)return;
  for(c = 0 ; c < GetActiveObjectCount(doc) ; c++){
    println(obj[c]->GetName());
  }
}

これを、上から順に1つのスクリプトにまとめるわけです。

/*
コンソールに選択オブジェクトを返します。
2009.7.3
*/


//選択されたオブジェクトの数
GetActiveObjectCount(doc)
{
  var obj = GetActiveObject(doc);
  var c = 0;
  while(obj){
    obj = obj->SearchNext(BIT_AOBJ);
    c++;
  }
  return c;
}

//全ての選択オブジェクトの配列変数
GetActiveObjectAll(doc)
{
  if(!GetActiveObject(doc))return;
  var objs = new(array , GetActiveObjectCount(doc));
  var c;
  objs[0] = GetActiveObject(doc);
  for(c = 1 ; c < GetActiveObjectCount(doc) ; c++){
    objs[c] = objs[c - 1]->SearchNext(BIT_AOBJ);
  }
  return objs;
}


//全ての選択オブジェクトの名前をコンソールに表示
main(doc , op)
{
  var c = 0;
  var obj = GetActiveObjectAll(doc);
  if(!obj)return;
  for(c = 0 ; c < GetActiveObjectCount(doc) ; c++){
    println(obj[c]->GetName());
  }
}

これで、問題なく動作します。
関数を使ったので、main()関数がシンプルですね。

では、プロトタイプはどうした?
そう思っているだろう。

この様に、関数を複数定義しました。
定義した関数から、他の定義した関数を使用しています。

では、複数定義した関数…今回は2個ですが、この2個の定義の順番を逆にしたらどうでしょう。

/*
コンソールに選択オブジェクトを返します。
2009.7.3
*/


//全ての選択オブジェクトの配列変数
GetActiveObjectAll(doc)
{
  if(!GetActiveObject(doc))return;
  var objs = new(array , GetActiveObjectCount(doc));
  var c;
  objs[0] = GetActiveObject(doc);
  for(c = 1 ; c < GetActiveObjectCount(doc) ; c++){
    objs[c] = objs[c - 1]->SearchNext(BIT_AOBJ);
  }
  return objs;
}

//選択されたオブジェクトの数

GetActiveObjectCount(doc)
{
  var obj = GetActiveObject(doc);
  var c = 0;
  while(obj){
    obj = obj->SearchNext(BIT_AOBJ);
    c++;
  }
  return c;
}


//全ての選択オブジェクトの名前をコンソールに表示
main(doc , op)
{
  var c = 0;
  var obj = GetActiveObjectAll(doc);
  if(!obj)return;
  for(c = 0 ; c < GetActiveObjectCount(doc) ; c++){
    println(obj[c]->GetName());
  }
}

これで、実行するとエラーが出ます。

[FAIL] Script 'xxxx' Line 10 Pos 47 : Variable or Function expectid

もう、お気付きだと思います。

選択した全てのオブジェクト取得する関数で、未定義の選択されたオブジェクトの数を返す関数が使用されています。

この様な場合は、関数のプロトタイプを宣言すると問題は解決します。

もう、詳しい説明は必要ないと思いますが…

プロトタイプを使用することで、関数を複数使用した場合でも、順番を気にせず記述できるわけです。

冒頭で、main()関数の先とか後とか書きましたが、そんな事が重要ではなく、定義前に使用できるようにする方法なのです。

ま、main()も関数なんだね。一番最初に実行されるだけの…

/*
コンソールに選択オブジェクトを返します。
2009.7.3
*/


//プロトタイプ
GetActiveObjectCount(doc);
GetActiveObjectAll(doc);


//全ての選択オブジェクトの配列変数
GetActiveObjectAll(doc)
{
  if(!GetActiveObject(doc))return;
  var objs = new(array , GetActiveObjectCount(doc));
  var c;
  objs[0] = GetActiveObject(doc);
  for(c = 1 ; c < GetActiveObjectCount(doc) ; c++){
    objs[c] = objs[c - 1]->SearchNext(BIT_AOBJ);
  }
  return objs;
}

//選択されたオブジェクトの数

GetActiveObjectCount(doc)
{
  var obj = GetActiveObject(doc);
  var c = 0;
  while(obj){
    obj = obj->SearchNext(BIT_AOBJ);
    c++;
  }
  return c;
}


//全ての選択オブジェクトの名前をコンソールに表示
main(doc , op)
{
  var c = 0;
  var obj = GetActiveObjectAll(doc);
  if(!obj)return;
  for(c = 0 ; c < GetActiveObjectCount(doc) ; c++){
    println(obj[c]->GetName());
  }
}

関数の順番とプロトタイプの順番が違いますが、問題なく動作します。

プロトタイプの順番も問題ではないのです。

これで複雑なスクリプトも組めることでしょう。

|

« C4D XZ平面のスプラインを基に、XPressoで坂道ポリゴンオブジェクトを整形させてみました。 | トップページ | C4D C.O.F.F.E.E. 列挙? enum »