Skip to content

Commit

Permalink
replace adjustables with new config system
Browse files Browse the repository at this point in the history
any type can now be marked as "config" through its metadata
  • Loading branch information
phisko committed Mar 8, 2023
1 parent da70556 commit afd1290
Show file tree
Hide file tree
Showing 51 changed files with 433 additions and 535 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ function(add_kengine_library path)
# Headers for which we'll generate reflection headers and/or type registration code
file(GLOB system_headers
${path}/data/*.hpp
${path}/functions/*.hpp)
${path}/functions/*.hpp
${path}/systems/*.hpp)

if(EXISTS ${path}/CMakeLists.txt)
# Helpers for the system CMakeLists
Expand Down
4 changes: 2 additions & 2 deletions kengine/config/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# kengine_config

Expose global values that the user may adjust.
Expose global values that the user may adjust. To expose a component to the user, simply add the `config` metadata to its reflectible API.

* [data](data/)
* [values](data/values.md): component that exposes values to adjust
* [configurable](data/configurable.md): marks an entity as containing configurable components.

Sub-libaries:
* [kengine_config_imgui](imgui/)
Expand Down
144 changes: 2 additions & 142 deletions kengine/config/data/configurable.hpp
Original file line number Diff line number Diff line change
@@ -1,148 +1,8 @@
#pragma once

#ifndef KENGINE_CONFIG_NAME_MAX_LENGTH
#define KENGINE_CONFIG_NAME_MAX_LENGTH 64
#endif

// stl
#include <vector>

// magic_enum
#include <magic_enum.hpp>

// putils
#include "putils/string.hpp"
#include "putils/color.hpp"
#include "putils/lengthof.hpp"

namespace kengine::config {
//! putils reflect all
//! used_types: [refltype::string, refltype::value]
//! class_name: config_values
struct values {
static constexpr char string_name[] = "config_string";
using string = putils::string<KENGINE_CONFIG_NAME_MAX_LENGTH, string_name>;
struct value;

string section;
std::vector<value> entries;

enum class value_type {
Bool,
Float,
Int,
Color,
Invalid
};

/*!
* putils reflect all
* class_name: config_values_value
* used_types: [
* refltype::storage_for_bool,
* refltype::storage_for_float,
* refltype::storage_for_int,
* refltype::storage_for_color,
* putils::normalized_color
* ]
*/
struct value {
template<typename T, const char * Name>
struct storage {
storage() noexcept = default;
explicit storage(T * ptr) noexcept : ptr(ptr), value(*ptr) {}
explicit storage(T value) noexcept : value(value) {}
T * ptr = nullptr;
T value;
};

static constexpr char _bool_storage_name[] = "config_storage_bool";
using storage_for_bool = storage<bool, _bool_storage_name>;

static constexpr char _float_storage_name[] = "config_storage_float";
using storage_for_float = storage<float, _float_storage_name>;

static constexpr char _int_storage_name[] = "config_storage_int";
using storage_for_int = storage<int, _int_storage_name>;

static constexpr char _color_storage_name[] = "config_storage_color";
using storage_for_color = storage<putils::normalized_color, _color_storage_name>;

value() noexcept {}
value(const value &) noexcept = default;
value & operator=(const value &) noexcept = default;
value(value &&) noexcept = default;
value & operator=(value &&) noexcept = default;

value(const char * name, bool * b) noexcept : name(name), bool_storage(b), type(value_type::Bool) {}
value(const char * name, bool b) noexcept : name(name), bool_storage(b), type(value_type::Bool) {}

value(const char * name, float * f) noexcept : name(name), float_storage(f), type(value_type::Float) {}
value(const char * name, float f) noexcept : name(name), float_storage(f), type(value_type::Float) {}

value(const char * name, int * i) noexcept : name(name), int_storage(i), type(value_type::Int) {}
value(const char * name, int i) noexcept : name(name), int_storage(i), type(value_type::Int) {}

value(const char * name, putils::normalized_color * color) noexcept : name(name), color_storage(color), type(value_type::Color) {}
value(const char * name, putils::normalized_color color) noexcept : name(name), color_storage(color), type(value_type::Color) {}
value(const char * name, putils::color color) noexcept : name(name), color_storage(putils::to_normalized_color(color)), type(value_type::Color) {}

template<typename E>
static const char ** get_enum_names_impl() noexcept {
static putils::string<64> names[magic_enum::enum_count<E>()];
static const char * ret[putils::lengthof(names)];
static bool first = true;
if (first) {
for (size_t i = 0; i < putils::lengthof(names); ++i) {
names[i] = magic_enum::enum_names<E>()[i];
ret[i] = names[i].c_str();
}
first = false;
}
return ret;
}

template<typename E>
value(const char * name, E * enum_type) noexcept : name(name), int_storage((int *)enum_type), type(value_type::Int) {
static_assert(std::is_enum_v<E> && std::is_same_v<std::underlying_type_t<E>, int>);
get_enum_names = get_enum_names_impl<E>;
enum_count = magic_enum::enum_count<E>();
}

template<typename E>
value(const char * name, E enum_type) noexcept : name(name), int_storage((int)enum_type), type(value_type::Int) {
static_assert(std::is_enum_v<E> && std::is_same_v<std::underlying_type_t<E>, int>);
get_enum_names = get_enum_names_impl<E>();
enum_count = magic_enum::enum_count<E>();
}

string name;

union {
storage_for_bool bool_storage;
storage_for_float float_storage;
storage_for_int int_storage;
storage_for_color color_storage;
};

value_type type = value_type::Invalid;

using enum_name_func = const char **();
//! putils reflect off
enum_name_func * get_enum_names = nullptr;
size_t enum_count = 0;
};
};
struct configurable {};
}

#include "values.rpp"

template<typename T, const char * Name>
#define refltype kengine::config::values::value::storage<T, Name>
putils_reflection_info_template {
static constexpr auto class_name = Name;
putils_reflection_attributes(
putils_reflection_attribute(value)
);
};
#undef refltype
#include "configurable.rpp"
28 changes: 2 additions & 26 deletions kengine/config/data/configurable.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
# [values](values.hpp)
# [configurable](configurable.hpp)

Utility component exposing values that may be adjusted at runtime, e.g. by the [imgui_config](../imgui/systems/system.md) system.

Currently supported types are `bool`, `int`, `float`, [putils::normalized_color](https://github.com/phisko/putils/blob/master/putils/color.md) and `enum` types.

The maximum length of the config's name (stored as a [putils::string](https://github.com/phisko/putils/blob/master/putils/string.md)) defaults to 64, and can be adjusted by defining the `KENGINE_CONFIG_NAME_MAX_LENGTH` macro.

## Usage

```c++
static bool global_bool = false;
static int global_int = 42;

const auto e = registry.create();
registry.emplace<kengine::config::values>(e) = {
"Globals", // Category for these config values
{ // vector of config values
{ "Bool name", &global_bool },
{ "Int name", &global_int }
}
};

// ... Later on, once config system has been processed

std::cout << global_bool << std::endl; // May be true, if user modified it
```
Tag component that marks an entity as configurable. Its components will be exposed to users and serialized.
34 changes: 2 additions & 32 deletions kengine/config/data/configurable.rpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,8 @@

#include "putils/reflection.hpp"

#define refltype kengine::config::values
#define refltype kengine::config::configurable
putils_reflection_info {
putils_reflection_custom_class_name(config_values);
putils_reflection_attributes(
putils_reflection_attribute(section),
putils_reflection_attribute(entries)
);
putils_reflection_used_types(
putils_reflection_type(refltype::string),
putils_reflection_type(refltype::value)
);
};
#undef refltype

#define refltype kengine::config::values::value
putils_reflection_info {
putils_reflection_custom_class_name(config_values_value);
putils_reflection_attributes(
putils_reflection_attribute(name),
putils_reflection_attribute(bool_storage),
putils_reflection_attribute(float_storage),
putils_reflection_attribute(int_storage),
putils_reflection_attribute(color_storage),
putils_reflection_attribute(type),
putils_reflection_attribute(enum_count)
);
putils_reflection_used_types(
putils_reflection_type(refltype::storage_for_bool),
putils_reflection_type(refltype::storage_for_float),
putils_reflection_type(refltype::storage_for_int),
putils_reflection_type(refltype::storage_for_color),
putils_reflection_type(putils::normalized_color)
);
putils_reflection_class_name;
};
#undef refltype
4 changes: 3 additions & 1 deletion kengine/config/imgui/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
project(kengine)

kengine_library_link_private_libraries(kengine_imgui)
kengine_library_link_private_libraries(kengine_imgui)
kengine_library_link_private_libraries(kengine_meta_imgui)
kengine_library_link_private_libraries(kengine_meta_json)
Loading

0 comments on commit afd1290

Please sign in to comment.