SimpleDataType
説明
SimpleDataTypeクラスは、すべてのFlexSimオブジェクトの中心となります。どの種類でもオブジェクトデータを持つノードは、最終的にはSimpleDataTypeのインスタンスに関連付けられます。これは、CouplingDataTypeの親クラスでもあります。
SimpleDataTypeオブジェクトは、ツリーの単一のノードとして、複数の変数を保持できます。ただし、FlexSimイベント(停止、リセット、開始など)や、クリックなどのユーザーイベントのいずれにも反応しません。このため、必要なメモリはごくわずかです。このクラスは一般に、より大きなオブジェクトの一部として、ツリーに保存できるデータを保持するため使用されます。
ツリーノードホルダー
SimpleDataTypeで定義されるメンバー変数はholderのみで、このオブジェクトを参照するツリー内ノードへのポインターです。すべての子クラスにより、この目的で使用されます。
直接の子クラス
クラス | 説明 |
---|---|
ObjectDataType | FlexsimObjectの親(すべてのライブラリオブジェクトのコア) |
CouplingDataType | ノードからノードポインターへの機能を提供します。 |
FlexSimEvent | FlexSimが使用できるイベントリストのイベントのベースクラス。 |
実装
仮想メソッド
メソッド | 説明 |
---|---|
void bind() | クラスの変数をバインドして、FlexSim内で可視となり、保存できるようにします(必須)。 |
void bindEvents() | クラスのイベントをバインドします。詳細については、「バインド済みイベント」を参照してください。 |
void bindStatistics() | クラスの統計をバインドします。詳細については、「バインドされた統計」を参照してください。 |
const char* getClassFactory() | クラス名をFlexSimに返し、オブジェクトのインスタンスを正しく作成できるようにします(必須)。 |
char* toString(int verbose) | FlexSim内で表示される文字列を返します(オプション)。 |
bind()
bind()メソッドは、さまざまな時点で呼び出されます。このメソッドの動作は、現在のバインドモードにより異なります。bind()は、FlexSimで必要な動作に応じて、各種のバインドモードで起動されます。正しいbind()メソッドを実装するために必須ではありませんが、bind()メソッド内でgetBindMode()を使用して、バインドモードを明示的に取得できます。次のバインドモードが存在します。
- SDT_BIND_ON_LOAD - ノードの状態がツリーからロードされたとき(モデルのロード、DLLの再接続など)。
- SDT_BIND_ON_SAVE - ノードがツリーに保存されたとき(モデルの保存、DLLの切断など)。
- SDT_BIND_ON_CREATE - SDTの新しいインスタンスがnodeaddsimpledata()で作成されたとき(FlexScriptでは使用できません)。
- SDT_BIND_ON_DISPLAY - ツリーにノードが表示されたとき。
- SDT_BIND_SET_VALUE - アプリケーションコマンドsetsdtvalueの一部として、flexscriptによりクラスメンバーの値を設定できます。
- SDT_BIND_GET_VALUE - アプリケーションコマンドgetsdtvalueの一部として、flexscriptによりクラスメンバーの値を設定できます。
保存/ロード - ノードが保存されるとき、bind()はオブジェクトの各変数についてサブノードを作成し、結果としてでき上がる構造を保存します。ノードがロードされたとき、bind()は保存されている構造から値を取得し、オブジェクトに格納します。ロードプロセスの別の部分で、構造ノードが削除されます。
この動作を、次の図に示します。この動作に関係するDotクラスは、SimpleDataTypeクラスを拡張したものです。Dotクラスには変数x、y、z、widthがあります。変数x、y、zは「継続的な」サブノードとしてバインドされていることに注意してください。これは、「x」という名前のノードはロードフェーズの後もサブノードとして継続することを意味します。また、継続的なサブノードはクラスメンバーの値に「バインド」され、ノードの値を変更すると、クラスメンバーの値も自動的に変更されます。
Dotクラスのコードは、このドキュメントの「例」セクションにあります。Dotのインスタンスがツリー内でどのように表示されるかを、次の図に示します。すべての値が表示され、xはサブノードであることに注意してください。
この図は、同じオブジェクトの保存される構造を示しています。以前はノードでなかった各変数が、sdt::attributetree内のノードになっています。
ノードがロードされるとき、オブジェクトのサブノードから値が取得され、オブジェクトの再作成に使用されます。これによって、オブジェクトの状態をいつでも保存できます。
nodeaddsimpledata() - モジュールのソースコード内で利用可能な関数です。通常は次の形式で呼び出されます。
nodeaddsimpledata(someTreenode, new SimpleDataTypeDerivative, 1)
このコードは、ツリーノードのデータポインターを、SimpleDataTypeDerivativeの新しいインスタンスに設定します。3番目のパラメータは1または0です。1なら、FlexSimはbind()をSDT_BIND_ON_CREATEモードで呼び出します。このモードでは、必要な継続的ノードがサブノード(Dotの例にあるxノードのように)としてアサートされることが確認されます。SDTクラスで継続的サブノードを使用しない場合、作成時にバインドする必要はありません。
表示 - SimpleDataType::toString()のデフォルト実装はbind()メソッドを呼び出し、ツリーに表示する値が文字列として返されます。toString()メソッドの詳細については、後で説明します。
getsdtvalue( theSDTNode, "memberName") / setsdtvalue( theSDTNode, "memberName", value ) - これらのコマンドは、bind()メソッドをそれぞれSDT_BIND_MODE_GET_VALUEとSDT_BIND_MODE_SET_VALUEのバインドモードで呼び出します。その後で、bind()メソッドでバインドする各メンバーは、メンバーの名前が目的の名前と一致しているかどうかを確認し、一致するならそのメンバーの値を取得/設定します。これらの関数は元に戻すに対応しているため、元の戻すのコンテキスト内で呼び出すと、変更は元に戻すレコードの一部となり、ユーザーが元に戻すを選択すると元に戻されることにも注意してください(変更を元に戻せるようにするには、dll内から直接SimpleDataType::setValue()メソッドを使用できます)。
バージョン7のベータ版をまだ使用している場合、これらの関数はアプリケーションコマンドとしてのみ利用可能なため、FlexSimに問い合わせてください。
変数のバインド
SimpleDataTypeを継承するクラスは、bind()関数を使用して自分のメンバー変数をバインドする必要があります。これを行わないと、FlexSimの保存時に変数の値が保存されません。変数をバインドする方法は、次の表に示すようにタイプにより異なります。
バインド関数 | データタイプ | 例 |
---|---|---|
bindDouble(double varName, int asSubNode) | double | bindDouble(x, 1) - double xをクラスのサブノードとしてバインドします。 |
bindNumber(Type varName) | float、int、その他すべての数値プリミティブ | bindNumber(y) - 数値プリミティブyをクラスにバインドします。 |
bindSubNode(treenode varName, int dataType) | treenode | bindSubNode(myTreenode, 0) - データなしでサブノードをバインドします。 |
bindVariant(Variant varName) | Variant | bindVariant(myVariant) - バリアントをバインドします。 |
bindNodePtr(treenode varName) | treenode | bindNodePtr(myTreenode) |
bindNodeRef(NodeRef varName, int asSubNode) | NodeRef | bindNodeRef(myNodeRef) |
bindObjPtr(SimpleDataType* varName) | SimpleDataType* | bindObjPtr(myObjPtr) |
bindObjRef(ObjRef varName, int asSubNode) | ObjRef | bindObjRef(myObjRef) |
bindString(std::string varName) | std::string | bindString(myStr) |
bindByteBlock(ByteBlock varName, int asSubNode) | ByteBlock | bindByteBlock(bb, 1) - ByteBlockをサブノードとしてバインドします。ツリーでは、これはテキストデータを持つノードです。 |
bindStlContainer(std::container varName | vector、stack、deque(std) | bindStlContainer(myVectorOfDoubles) |
bindStlSet(std::set varName) | set、multiset、unordered_set(std) | bindStlSet(mySet) |
bindStlMap(std::map varName) | map、multimap、unordered_map(std) | bindStlMap(myMap) |
bindCallback(funcName, ClassType) | funcNameはバインドする関数の名前です。ClassTypeは、現在のクラスのクラス名です。 | bindCallback(functionName, MyClass) |
注:STLコンテナを処理するbind()関数では、コンテナがプリミティブタイプで構成されている必要があります。
コールバックのバインド
カスタムのSimpleDataTypeで関数を利用可能にすることが必要な場合があります。次に示すようなクラスを作成した場合、FlexScript function_s(talkerNode, "sayHello")
を使用して、そのオブジェクトのsayHello関数を呼び出すことができます。
class Talker : public SimpleDataType { public: void sayHello() { pt("hello"); pr(); } Variant sayHello(FLEXSIMINTERFACE) { sayHello(); } virtual void bind() override { SimpleDataType::bind(); bindCallback(sayHello, Talker); } };
getClassFactory()
このメソッドはSimpleDataTypeの仮想メンバーで、ツリーを保存するとき、そのクラスが何なのかをFlexSimに正しく通知するため、サブクラスに実装する必要があります。これによりFlexSimは、後でツリーをロードするときクラスファクトリーを読み取り、createsdtderivative()への正しい呼び出しを行って、クラスのインスタンスを正しく作成できます。
toString()
toString()メソッドは、FlexSimのツリーウィンドウに表示される文字列を返します。デフォルトではbind()関数呼び出しの結果の文字列が返されますが、この関数を上書きし、好きな形式のデータを返すことができます。
toString()は、2つの場合に対応する必要があります。最初は、ノードが選択されておらず、表示されているときです。デフォルトの実装では、1行の文字列が返されます。もう1つはノードが選択され、ノードに完全な表示エリアが与えられているときです。この場合、デフォルト実装では各変数とその値を別々の行で表示します。
どの文字列を返すべきかどうかを判定するには、「verbose」パラメータを使用します。1なら、完全なビューの文字列を返します。0なら、1行の文字列を返します。
リンク
ホットリンクとコールドリンクは、SimpleDataTypeクラスの変数の取得と設定に使用できます。このためには、いくつかの要件があります。
- リンクパスは、SimpleDataTypeノード(../..>path/to/node/TheSDT)をポイントしている必要があります。
- コールドリンクには、sdtvalueという名前のサブノードが存在し、SDT変数名がテキストデータとして存在している必要があります。
- SDT変数はバインドされた変数の必要があります。すなわち、この変数のバインドにbind()が使用されている必要があります。
上記の条件が満たされていれば、コールドリンクノードは次のようになります。
例
基本的な例として、Dotクラスを使用します。位置とサイズ以外の情報は必要ありません。Dotクラスのヘッダーファイルは次のようになります。
#pragma once #include "FlexsimDefs.h" class Dot : public SimpleDataType { public: double x, y, z; float width; Dot() : x(0), y(0), z(0), width(0) {} Dot(double x, double y, double z, float w) : x(x), y(y), z(z), width(w) {} virtual const char* getClassFactory() override { return "ModuleName::Dot"; } virtual void bind() override { SimpleDataType::bind(); bindDouble(x, 1); bindDouble(y, 1); bindDouble(z, 1); bindNumber(width); } };
下の図は、ツリー内のDotのインスタンスがどのように見えるかを示しています。変数x、y、zが実際にはサブノードであることに注意してください。これは、これらの変数のバインド方法によるものです。widthはテキストのみで一覧表示されます。
この例の作成方法
- このドキュメントを読んで、DLLモジュールを作成します。
- DLLプロジェクトに、Dot.hというヘッダーを追加します。
- 上に示したDotクラスをDot.hにコピーします。
"ModuleName::Dot"
を、モジュール名に合わせて変更します。- モジュールのメイン.cppファイルで、
createsdtderivative(char* classname)
に次の行を追加します。if (strcmp(classname, "Dot") == 0) return new Dot();
- FlexSimが実行中なら、すべてのDLLの接続を解除します。
- モジュールのDLLを構築します。
- FlexSimを開始するか、DLLを再接続します。
- ツリーのどこかに空白のノードを作成します。
- そのノードに名前とサブノードを指定します。
- サブノードに「sdt::attributetree」という名前を付けます。
- サブノードに「[moduleName]::Dot」というテキストデータを与えます。
- ノードをso()として割り当てます。
- スクリプトとして「
nodeadddata(so(), DATATYPE_SIMPLE);
」コマンドを実行します。
これで、ノードがSimpleDataTypeオブジェクトになります。 - 「Ctrl-c」を使用してノードをコピーします。
- 「Ctrl-v」を使用して別の空白ノードに貼り付けます。これで、Dotクラスのインスタンスが作成されます。
- 貼り付けられたノードにサブノードを追加します。
- 再度コピーします。これで、サブノードとしてバインドされたデータが表示されます。