8#include "core/reflect.h"
9#include "resource/asset_ref.h"
10#include "resource/asset_type.h"
11#include "system/script/behavior.h"
12#include "system/script/behavior_field_visitor.h"
14namespace Vkm::Engine {
30void visitField(BehaviorFieldVisitor& visitor,
const char* name, V& value) {
31 if constexpr (std::is_enum_v<V>) {
33 Reflect::HAS_ENUM_NAMES<V>,
34 "ReflectedBehavior: enum field needs a VKM_ENUM_NAMES registration."
36 using Names = Reflect::EnumNames<V>;
37 int index =
static_cast<int>(
value);
38 visitor.enumField(name, index, Names::values, Names::count);
39 value =
static_cast<V
>(index);
40 }
else if constexpr (VISITOR_SUPPORTS_FIELD<V>) {
41 visitor.field(name, value);
42 }
else if constexpr (IS_ASSET_REF<V>) {
44 ASSET_TYPE<typename V::asset_t> != AssetType::Count,
45 "ReflectedBehavior: AssetRef names an asset kind the library does not "
46 "hold. Only kinds with an ASSET_TYPE (resource/asset_type.h) can be "
47 "authored, because the assets block has no section for the others."
49 visitor.assetField(name,
value.name, ASSET_TYPE<typename V::asset_t>);
50 }
else if constexpr (Reflect::IS_REFLECTED<V>) {
51 if (visitor.beginStruct(name)) {
52 Reflect::forEachField(value, [&](std::string_view subName,
auto& sub) {
53 visitField(visitor, subName.data(), sub);
59 Reflect::DEPENDENT_FALSE<V>,
60 "ReflectedBehavior: a reflected field must be float, int, bool, std::string, "
61 "glm::vec2, glm::vec3, glm::vec4, glm::quat, an enum registered with "
62 "VKM_ENUM_NAMES, an AssetRef<Asset>, or a struct with its own reflect block. "
63 "Keep anything else as runtime state: leave it out of VKM_REFLECT."
77template<
typename Derived>
80 const char*
typeName()
const override {
return reflectedName(); }
83 Reflect::forEachField(
84 static_cast<Derived&
>(*
this),
85 [&](std::string_view name,
auto& value) {
87 detail::visitField(visitor, name.data(), value);
92 std::unique_ptr<Behavior>
clone()
const override {
93 auto copy = std::make_unique<Derived>();
94 const Derived& self =
static_cast<const Derived&
>(*this);
97 (((*copy).*(f.ptr) = self.*(f.ptr)), ...);
112 static constexpr const char* reflectedName() {
114 Reflect::IS_REFLECTED<Derived>,
115 "This behavior has no reflect block. Below the class, at global scope, write "
116 "VKM_REFLECT_BEGIN(::YourNamespace::YourBehavior), one VKM_F(field) per authored "
117 "field, then VKM_REFLECT_END() - with no fields between them if it has none."
Type-erased visitor over a behavior's reflected authoring fields.
Definition behavior_field_visitor.h:23
CRTP base that derives typeName(), visitFields() and clone() from the reflect block.
Definition reflected_behavior.h:78
void visitFields(BehaviorFieldVisitor &visitor) override
Visit the behavior's reflected authoring fields; ReflectedBehavior generates it.
Definition reflected_behavior.h:82
const char * typeName() const override
Stable type name, identical to this type's BehaviorRegistry key; serialization uses it.
Definition reflected_behavior.h:80
std::unique_ptr< Behavior > clone() const override
Deep copy for entity duplication; authored fields only, the context is rebound.
Definition reflected_behavior.h:92
float value()
Uniform float in [0, 1), from the per-thread generator.
Definition random.h:126
The reflection trait, specialised per type by VKM_REFLECT_BEGIN / VKM_F / VKM_REFLECT_END.
Definition reflect.h:41