Свои компоненты¶
Перед тем, как начать проверьте, не включены ли у вас в коде следующие флаги:
- FS_NO_COMPONENTS
- FS_NO_REG_TYPES
Если они включены, то лучше уберите их.
Минимальный компонент¶
#include <firesteel/component.hpp>
using namespace Firesteel;
class MyComponent : public Component {
public:
MyComponent(Entity* tEntity)
: Component(tEntity) {
}
//Runs when component is added.
void onStart() override {}
//Runs every frame.
void onUpdate() override {}
//Runs before rendering.
void onDraw() override {}
//Runs when component gets removed.
void onRemove() override {}
void properties() override { }
const char* name() const override { return "fs.my_component"; }
};
Регистрация компонентов¶
#include <firesteel/firesteel.hpp>
using namespace Firesteel;
#include "my_component.hpp"
class CustomComponentsApp : public Firesteel::App {
void onInitialize() override {
ComponentRegistry::sInstance()->append("fs.my_component", DefaultComponentFactory<MyComponent>);
}
};
ComponentRegistry - как раз таки реестр компонентов
- ComponentRegistry::sInstance()->append() - метод регистрации через статичный реестр. Т.е. вам не нужно создавать свою копию реестра для этого -
это уже сделано за вас
- DefaultComponentFactory<MyComponent> - базовая фабрика для компонента, если ваш компонент не требует дополнительных действий при добавлении на
сущность
Альтернативная регистрация¶
Вообще второй аргумент в ComponentRegistry::sInstance()->append() это лямбда-функция. То есть вы вполне можете просто:
ComponentRegistry::sInstance()->append("fs.my_component", [](Entity* e, const nlohmann::json& j) {
return Component::create<MyComponent>(e,j);
});
Сериализация и десериализация¶
Если вы используете систему сцен, что уже есть в Firesteel, то всё уже готово. Регистрация в реестре уже даёт возможность
компоненту сериализовываться (т.е. сохраняться и загружаться). Если ваш компонент имеет имя другого, уже существующего
компонента, то вылетит ошибка.
Хотите добавить сохраняемые свойства для компонента? Да проще простого. Добавьте в свой компонент следующее:
void properties() override {
PROPERTY(value);
}
std::string value;
MyComponent(Entity* tEntity, const std::string& tVal="Hello World!")
: value(tVal), Component(tEntity) { }
std::string ещё могут быть и другие типы данных.Вот их список на данный момент:
- bool
- uint (т.е. unsigned int)
- int
- float
- double
- std::string
- glm::vec2
- glm::vec3
- glm::vec4
Свой сериализатор для типа данных¶
Если вам недостаточно изначальных типов сериализуемых данных, то можете сделать свой сериализатор:
#include <firesteel/type.hpp>
using namespace Firesteel;
struct MyType {
bool boolVal;
};
struct MyTypeTypeHandler : public ITypeHandler {
std::string toString(const void* tVal) const override {
return (static_cast<const MyType*>(tVal)->boolVal)?"true":"false";
}
void fromString(void* tVal, const std::string& tStr) const override {
static_cast<MyType*>(tVal)->boolVal=(tStr=="true");
}
#ifndef FS_NO_JSON
nlohmann::json toJson(void* tVal) const override {
return static_cast<const MyType*>(tVal)->boolVal;
}
void fromJson(void* tVal, const nlohmann::json& tJson) const override {
static_cast<MyType*>(tVal)->boolVal=tJson.get<bool>();
}
#endif // !FS_NO_JSON
};
class WindowApp : public Firesteel::App {
void onInitialize() override {
TypeRegistry::sInstance()->registerType<MyType>(std::make_unique<MyTypeTypeHandler>());
}
}
class MyComponent : public Component {
public:
MyComponent(Entity* tEntity, const MyType& tVal=MyType{})
: value(tVal), Component(tEntity) { }
void properties() override {
PROPERTY(value);
}
const char* name() const override { return "fs.my_component"; }
MyType value;
};