vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
reflected_behavior.h
1#pragma once
2
3#include <memory>
4#include <string_view>
5#include <tuple>
6#include <type_traits>
7
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"
13
14namespace Vkm::Engine {
15
16namespace detail {
17
29template<typename V>
30void visitField(BehaviorFieldVisitor& visitor, const char* name, V& value) {
31 if constexpr (std::is_enum_v<V>) {
32 static_assert(
33 Reflect::HAS_ENUM_NAMES<V>,
34 "ReflectedBehavior: enum field needs a VKM_ENUM_NAMES registration."
35 );
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>) {
43 static_assert(
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."
48 );
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);
54 });
55 visitor.endStruct();
56 }
57 } else {
58 static_assert(
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."
64 );
65 }
66}
67
68} // namespace detail
69
77template<typename Derived>
78class ReflectedBehavior : public Behavior {
79 public:
80 const char* typeName() const override { return reflectedName(); }
81
82 void visitFields(BehaviorFieldVisitor& visitor) override {
83 Reflect::forEachField(
84 static_cast<Derived&>(*this),
85 [&](std::string_view name, auto& value) {
86 // VKM_F's #name is a literal, so data() is null-terminated.
87 detail::visitField(visitor, name.data(), value);
88 }
89 );
90 }
91
92 std::unique_ptr<Behavior> clone() const override {
93 auto copy = std::make_unique<Derived>();
94 const Derived& self = static_cast<const Derived&>(*this);
95 std::apply(
96 [&](auto&&... f) {
97 (((*copy).*(f.ptr) = self.*(f.ptr)), ...);
98 },
100 );
101 return copy;
102 }
103
104 private:
112 static constexpr const char* reflectedName() {
113 static_assert(
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."
118 );
119 if constexpr (Reflect::IS_REFLECTED<Derived>) return Reflect::Traits<Derived>::NAME;
120 else return "";
121 }
122};
123
124} // namespace Vkm::Engine
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