最後に,ユーザー用ボタンの"Sample Func 0"をクリックすることによって,このボタンに割り当てられた関数が実行されます.
ボタンを押すことによって,コンソールに"User Status"情報およびピックされたオブジェクトの情報が出力されたことを確認してください.
<ソース解説>
まずUSERクラスのコンストラクタを見てみましょう.
//コンストラクト
USER::USER()
{
// ここでUserFunc関数ポインタの指す関数を指定する
for(int i=0;i<USERFUNCNUMMAX;i++){
if(i==0)
UserFunc[i] = &USER::ExecSampleFunc0; // サンプル
else if(i==1)
UserFunc[i] = &USER::ExecSampleFunc1; // サンプル
else if(i==2)
UserFunc[i] = &USER::ExecSampleFunc2; // サンプル
else if(i==3)
UserFunc[i] = &USER::ExecSampleFunc3; // サンプル
else if(i==4)
UserFunc[i] = &USER::MasterUserFunc; // 未使用のUserFunc[i]にはMasterUserFunc()を登録しておく
else if(i==5)
UserFunc[i] = &USER::MasterUserFunc; // 未使用のUserFunc[i]にはMasterUserFunc()を登録しておく
else if(i==6)
UserFunc[i] = &USER::MasterUserFunc; // 未使用のUserFunc[i]にはMasterUserFunc()を登録しておく
else if(i==7)
UserFunc[i] = &USER::MasterUserFunc; // 未使用のUserFunc[i]にはMasterUserFunc()を登録しておく
else
UserFunc[i] = &USER::MasterUserFunc; // 未使用のUserFunc[i]にはMasterUserFunc()を登録しておく
}
// Userステータスの初期化
UserStat.Mode = 0;
for(int i=0;i<USERPROPNUM;i++)
UserStat.Prop[i] = 0;
}
ここでUserFunc()という関数ポインタにユーザーが作成した関数を登録します.7行目を見てみると,ExecSampleFunc0()という名の関数を
UserFunc()に代入しています. これは,メイン画面ユーザーボタンの"Sample Func 0"に当たる部分に対応します.このように,関数ポインタを介してKodatuno GUI部とUser部がやりとりします.
ExecSampleFunc0()はユーザーが自作する関数であり,説明は後ほど記述します.(プロトタイプ宣言も当然必要です.UserFunc.h内に記述されています.)
また,UserFunc()自体は引数が決まっていますので、それに代入するExecSampleFunc0()の引数もUserFunc()に合わせる必要があります.引数は,
- BODYList *BodyList
Kodatunoは読み込んだBodyの幾何情報を読み込んだ数だけ、読み込んだ順にリスト構造として保持します。Bodyの幾何情報は"BODY.h"で定義されており,
BODYクラスによって統括されています.*BodyListはリスト化されたBodyへのポインタです.
- OBJECTList *ObjList
あるBodyに対して、ある面やエッジ(オブジェクト)をピックした場合、そのピックされたオブジェクトを識別するための情報が必要です。
*ObjListはそのセレクション情報を提供する引数です。
- int PickCount
全部で幾つの面あるいはエッジを選択したかを示します。
の3つです.BODYListとOBJECTListはピックしたオブジェクトの実体を取り出すための重要な要素ですが,ここでは概略をおさえるだけにとどめ,2.8 BODYListとOBJECTListでまとめて解説します.
また,USERクラス内にUserStat構造体が定義されており,この中に"User Status"ダイアログでの設定情報が格納されています.
//Userステータス値格納用構造体
typedef struct{
int Mode;
double Prop[USERPROPNUM];
}UserStat_;
では,ExecSampleFunc0()を見てみましょう.
// Userボタン登録関数0の実体を記述
// *BodyList:BODYの実体が登録順にリストされている
// *ObjList:セレクションされたエンティティ情報
// PickCount:セレクションされたエンティティの数
int USER::ExecSampleFunc0(BODYList *BodyList,OBJECTList *ObjList,int PickCount)
{
char mes[256];
// ユーザーステータスでの選択されたモード番号をコンソール出力
sprintf(mes,"Selected Mode : %d",UserStat.Mode);
GuiIF.SetMessage(mes);
// ユーザーステータスでのプロパティ値(最初の2つ)をコンソール出力
sprintf(mes,"User Property 1: %lf",UserStat.Prop[0]);
GuiIF.SetMessage(mes);
sprintf(mes,"User Property 2: %lf",UserStat.Prop[1]);
GuiIF.SetMessage(mes);
GuiIF.SetMessage("....");
// セレクション数をコンソール出力
sprintf(mes,"All Pick Count : %d",PickCount);
GuiIF.SetMessage(mes);
for(int i=0;i<PickCount;i++){
OBJECT *obj = (OBJECT *)ObjList->getData(i); // i番目にセレクションされたエンティティの情報を得る
sprintf(mes,"#%d",i+1);
GuiIF.SetMessage(mes);
sprintf(mes,"Body No. : %d",obj->Body);
GuiIF.SetMessage(mes);
sprintf(mes,"Selected Object Type : %d",obj->Type);
GuiIF.SetMessage(mes);
sprintf(mes,"Selected Object No. : %d",obj->Num);
GuiIF.SetMessage(mes);
}
return KOD_TRUE;
}
先ほども述べたとおり,引数は必ず固定しなければなりません.
コンソールへの文字列出力はSetMessage()関数を使います.10〜19行目では"User Status"ダイアログでの設定情報を取り出し,出力しています.
22行目ではExecSampleFunc0()の引数PickCountを出力しています.25行目以降では,ピックした数分のオブジェクトの情報を出力しています.
i番目にピックされたオブジェクトの情報を取得するには26行目のように記述します.この記述の意味は解説しませんので,26行目はおまじないとして覚えてしまってください.
なお,OBJECT構造体は"BODY.h"に記述されています.
// ピックされたオブジェクトを示す構造体
typedef struct{
int Body; // BODYオブジェクトの番号
int Type; // エンティティタイプのシンボル(NURBS曲線:126 , NURBS曲面:128 , トリム面:144)
int Num; // Typeにおける要素番号(NURBS曲線が4本あったら、その4本に割り当てられた0〜3の番号)
int CCount; // 何番目にピックされた曲線かを表す
int SCount; // 何番目にピックされた曲面かを表す
}OBJECT;
以上でExecSampleFunc0()の解説は終わりです.ユーザーが定義した関数の登録方法,ピックした曲面/曲線の幾何情報の取り出し方が理解できたでしょうか.
つづいて,サンプルアプリケーションの解説に入っていきます.
そうそう,ユーザーボタン名を変更する方法を説明するのを忘れていました.ボタン名は"UserFunc.cpp"の2行目,SetMenuLabelName()関数内で記述します.
// Userメニュー名を登録(Userボタンの表示名)
void USER::SetMenuLabelName()
{
// 独自のメニュー名をここに記述してください
strcpy(MenuLabel1,"Sample Func 0");
strcpy(MenuLabel2,"Sample Func 1");
strcpy(MenuLabel3,"Sample Func 2");
strcpy(MenuLabel4,"Sample Func 3");
strcpy(MenuLabel5,"User Func 5");
strcpy(MenuLabel6,"User Func 6");
strcpy(MenuLabel7,"User Func 7");
strcpy(MenuLabel8,"User Func 8");
}
適当に名前を変更し,変更が反映されることを確認してみましょう.