オブジェクトクラス

一般的な定義

Objectは、ほとんどすべての基本クラスです。Godotのほとんどのクラスは、直接的または間接的に継承されます。オブジェクトはリフレクションと編集可能なプロパティを提供し、それらを宣言することは、このような単一のマクロを使用する必要があります。

class CustomObject : public Object {

    GDCLASS(CustomObject, Object); // this is required to inherit
};

これにより、オブジェクトは、例えば、多くの機能を得ることができます

obj = memnew(CustomObject);
print_line("Object class: ", obj->get_class()); // print object class

obj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.

参照:

オブジェクトの登録

ClassDB は、Objectから継承する登録済みクラスのリスト全体と、すべてのメソッドプロパティと整数定数への動的バインディングを保持する静的クラスです。

クラスは呼び出しによって登録されます:

ClassDB::register_class<MyCustomClass>()

登録すると、クラスをスクリプト、コードでインスタンス化したり、デシリアライズ時に再度作成したりできます。

仮想として登録することは同じですが、インスタンス化することはできません。

ClassDB::register_virtual_class<MyCustomClass>()

オブジェクトから派生したクラスは、静的な関数である static void _bind_methods() を上書きすることができます。1つのクラスが登録されると、この静的関数が呼び出され、すべてのオブジェクトのメソッド、プロパティ、定数などが登録されます。この関数は1回だけ呼び出されます。オブジェクト派生クラスがインスタンス化されていても登録されていない場合は、仮想として自動的に登録されます。

_bind_methods の内部には、実行できる事がいくつかあります。関数の登録は次の 1 つです:

ClassDB::register_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomMethod);

引数の既定値は、逆の順序で渡すことができます:

ClassDB::register_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomType::method, DEFVAL(-1)); // default value for arg2name

D_METHOD は、効率を高めるために「メソッド名」をStringNameに変換するマクロです。引数名はイントロスペクションに使用されますが、リリース時にコンパイルするとマクロはそれらを無視するので、文字列は使用されず、最適化されます。

その他の例については、コントロールまたはオブジェクトの _bind_methods を確認してください。

十分に文書化されていないモジュールや機能を追加するだけなら、 D_METHOD() マクロは無視しても問題なく、簡潔にするために名前を渡す文字列を渡すことができます。

参照:

定数

クラスには、多くの場合、次のような列挙型があります:

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

メソッドにバインドするときにこれらを動作させるには、enumをintに変換できるように宣言する必要があります。これにはマクロが用意されています:

VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.

定数は、次の方法を使用して _bind_methods 内でバインドすることもできます:

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

プロパティ (設定/取得)

オブジェクトはプロパティをエクスポートし、プロパティは次の場合に役立ちます:

  • オブジェクトのシリアル化と逆シリアル化。
  • オブジェクト派生クラスの編集可能な値のリストを作成します。

プロパティは通常、PropertyInfo()クラスによって定義されます。通常は次のように構築されます:

PropertyInfo(type, name, hint, hint_string, usage_flags)

例:

PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)

これは「amount」という名前の整数プロパティであり、ヒントは範囲です。範囲は0から49まで1のステップ(整数)です。 エディタ(値を視覚的に編集)でのみ使用できますが、シリアル化されません。

別の例:

PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")

これは文字列プロパティであり、任意の文字列を受け取ることができますが、エディタは定義されたヒントのみを許可します。使用状況フラグが指定されていないため、既定のフラグは PROPERTY_USAGE_STORAGE および PROPERTY_USAGE_EDITOR です。

「object.h」には多くのヒントと使用フラグがあります。

プロパティはC#プロパティのように動作し、インデックス作成を使用してスクリプトからアクセスすることもできますが、読みやすさには関数の使用が推奨されるため、一般的にこの使用方法はお勧めできません。また、多くのプロパティは、演算子[]を使用しない限りインデックス作成を不可能にする「アニメーション/フレーム」などのカテゴリにバインドされています。

_bind_methods() から、set/get 関数が存在する限り、プロパティを作成してバインドできます。例:

ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")

これにより、セッターとゲッターを使用してプロパティが作成されます。

_set/_get/_get_property_list を使用してプロパティをバインドします

より柔軟な必要がある場合(つまり、コンテキスト上のプロパティの追加または削除)に、プロパティを作成する追加の方法が存在します。

次の関数はObject派生クラスでオーバーライドできます。これらの関数は仮想ではありません。仮想にしないでください。オーバーライドのたびに呼び出され、前の関数は無効になりません(多重レベル呼出し)。

void _get_property_info(List<PropertyInfo> *r_props); // return list of properties
bool _get(const StringName &p_property, Variant &r_value) const; // return true if property was found
bool _set(const StringName &p_property, const Variant &p_value); // return true if property was found

また、 p_property を必要な名前と順番に比較しなければならないため、これは少し効率が悪くなります。

動的キャスト

Godotは、オブジェクト派生クラス間の動的キャストを提供します。例:

void somefunc(Object *some_obj) {

     Button *button = Object::cast_to<Button>(some_obj);
}

If cast fails, NULL is returned. This system uses RTTI, but it also works fine (although a bit slower) when RTTI is disabled. This is useful on platforms where a small binary size is ideal, such as HTML5 or consoles (with low memory footprint).

シグナル

オブジェクトは、一連のシグナルを定義できます(他の言語のデリゲートと同様)。それらに接続する方がかなり簡単です:

obj->connect(<signal>, target_instance, target_method)
// for example:
obj->connect("enter_tree", this, "_node_entered_tree")

メソッド _node_entered_tree は、 ClassDB::register_method を使用してクラスに登録する必要があります(前に説明しました)。

クラスへのシグナルの追加は _bind_methods で行われ、ADD_SIGNAL マクロを使用します。例:

ADD_SIGNAL(MethodInfo("been_killed"))

参照

Referenceはオブジェクトから継承され、参照カウントを保持します。参照カウントオブジェクトタイプのベースです。これらの宣言は、Ref<> template を使用して行う必要があります。例:

class MyReference: public Reference {
    GDCLASS(MyReference, Reference);
};

Ref<MyReference> myref(memnew(MyReference));

myref は参照カウントされます。Ref<>templates が参照を指定しなくなったときに解放されます。

参照:

リソース:

ResourceはReferenceを継承するため、すべてのリソースが参照カウントされます。 リソースには、オプションでディスク上のファイルを参照するパスを含めることができます。 これは resource.set_path(path) で設定できます。 これは通常、リソースローダーによって行われます。 2つの異なるリソースが同じパスを持つことはできません。そうしようとするとエラーになります。

パスのないリソースも問題ありません。

参照:

リソースの読み込み

リソースは、次のようにResourceLoader APIを使用して読み込むことができます:

Ref<Resource> res = ResourceLoader::load("res://someresource.res")

そのリソースへの参照が以前に読み込まれ、メモリ内にある場合、リソースローダーはその参照を返します。つまり、ディスク上で参照されているファイルから同時に読み込まれるリソースは 1 つだけです。

  • リソースインタラクティブローダー (TODO)

リソースの保存

リソースの保存は、リソースセーバー API を使用して行うことができます:

ResourceSaver::save("res://someresource.res", instance)

インスタンスが保存されます。ファイルへのパスを持つサブリソースは、そのリソースへの参照として保存されます。パスのないサブリソースは、保存されたリソースにバンドルされ、割り当てられたサブID(「res://someresource.res::1」 など)が割り当てられます。これは、読み込み時にキャッシュするのにも役立ちます。