Merge pull request #513 from MihailRis/enums-refactor

reduce boilerplate code of enums
This commit is contained in:
MihailRis 2025-04-13 14:45:26 +03:00 committed by GitHub
commit bba647db5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 200 additions and 297 deletions

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "GLSLExtension.hpp"
#include <sstream>
@ -95,22 +96,6 @@ inline void source_line(std::stringstream& ss, uint linenum) {
ss << "#line " << linenum << "\n";
}
static std::optional<Type> param_type_from(
const std::string& name
) {
static const std::unordered_map<std::string, Type> typeNames {
{"float", Type::FLOAT},
{"vec2", Type::VEC2},
{"vec3", Type::VEC3},
{"vec4", Type::VEC4},
};
const auto& found = typeNames.find(name);
if (found == typeNames.end()) {
return std::nullopt;
}
return found->second;
}
static Value default_value_for(Type type) {
switch (type) {
case Type::FLOAT:
@ -212,11 +197,13 @@ public:
}
bool processParamDirective() {
using Param = PostEffect::Param;
skipWhitespace(false);
// Parse type name
auto typeName = parseName();
auto type = param_type_from(typeName);
if (!type.has_value()) {
Param::Type type;
if (!Param::TypeMeta.getItem(typeName, type)) {
throw error("unsupported param type " + util::quote(typeName));
}
skipWhitespace(false);
@ -228,17 +215,17 @@ public:
skipWhitespace(false);
ss << "uniform " << typeName << " " << paramName << ";\n";
auto defValue = default_value_for(type.value());
auto defValue = default_value_for(type);
// Parse default value
if (peekNoJump() == '=') {
skip(1);
skipWhitespace(false);
defValue = parseDefaultValue(type.value(), typeName);
defValue = parseDefaultValue(type, typeName);
}
skipLine();
params[paramName] = PostEffect::Param(type.value(), std::move(defValue));
params[paramName] = PostEffect::Param(type, std::move(defValue));
return false;
}

View File

@ -1,7 +1,6 @@
#pragma once
#include <memory>
#include <optional>
#include <set>
#include <stdexcept>
#include <string>
@ -25,23 +24,6 @@ namespace rigging {
class SkeletonConfig;
}
constexpr const char* ContentType_name(ContentType type) {
switch (type) {
case ContentType::NONE:
return "none";
case ContentType::BLOCK:
return "block";
case ContentType::ITEM:
return "item";
case ContentType::ENTITY:
return "entity";
case ContentType::GENERATOR:
return "generator";
default:
return "unknown";
}
}
class namereuse_error : public std::runtime_error {
ContentType type;
public:
@ -185,26 +167,6 @@ public:
}
};
constexpr const char* to_string(ResourceType type) {
switch (type) {
case ResourceType::CAMERA:
return "camera";
case ResourceType::POST_EFFECT_SLOT:
return "post-effect-slot";
default:
return "unknown";
}
}
inline std::optional<ResourceType> ResourceType_from(std::string_view str) {
if (str == "camera") {
return ResourceType::CAMERA;
} else if (str == "post-effect-slot") {
return ResourceType::POST_EFFECT_SLOT;
}
return std::nullopt;
}
using ResourceIndicesSet = ResourceIndices[RESOURCE_TYPES_COUNT];
/// @brief Content is a definitions repository

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "ContentLoader.hpp"
#include <algorithm>
@ -259,28 +260,25 @@ void ContentLoader::loadBlock(
}
// block model
std::string modelTypeName = to_string(def.model);
std::string modelTypeName = BlockModelMeta.getNameString(def.model);
root.at("model").get(modelTypeName);
root.at("model-name").get(def.modelName);
if (auto model = BlockModel_from(modelTypeName)) {
if (*model == BlockModel::custom && def.customModelRaw == nullptr) {
if (BlockModelMeta.getItem(modelTypeName, def.model)) {
if (def.model == BlockModel::custom && def.customModelRaw == nullptr) {
if (root.has("model-primitives")) {
def.customModelRaw = root["model-primitives"];
} else if (def.modelName.empty()) {
throw std::runtime_error(name + ": no 'model-primitives' or 'model-name' found");
}
}
def.model = *model;
} else if (!modelTypeName.empty()) {
logger.error() << "unknown model: " << modelTypeName;
def.model = BlockModel::none;
}
std::string cullingModeName = to_string(def.culling);
std::string cullingModeName = CullingModeMeta.getNameString(def.culling);
root.at("culling").get(cullingModeName);
if (auto mode = CullingMode_from(cullingModeName)) {
def.culling = *mode;
} else {
if (!CullingModeMeta.getItem(cullingModeName, def.culling)) {
logger.error() << "unknown culling mode: " << cullingModeName;
}
@ -518,9 +516,7 @@ void ContentLoader::loadEntity(
std::string bodyTypeName;
root.at("body-type").get(bodyTypeName);
if (auto bodyType = BodyType_from(bodyTypeName)) {
def.bodyType = *bodyType;
}
BodyTypeMeta.getItem(bodyTypeName, def.bodyType);
root.at("skeleton-name").get(def.skeletonName);
root.at("blocking").get(def.blocking);
@ -799,8 +795,9 @@ void ContentLoader::load() {
if (io::exists(resourcesFile)) {
auto resRoot = io::read_json(resourcesFile);
for (const auto& [key, arr] : resRoot.asObject()) {
if (auto resType = ResourceType_from(key)) {
loadResources(*resType, arr);
ResourceType type;
if (ResourceTypeMeta.getItem(key, type)) {
loadResources(type, arr);
} else {
// Ignore unknown resources
logger.warning() << "unknown resource type: " << key;
@ -813,8 +810,9 @@ void ContentLoader::load() {
if (io::exists(aliasesFile)) {
auto resRoot = io::read_json(aliasesFile);
for (const auto& [key, arr] : resRoot.asObject()) {
if (auto resType = ResourceType_from(key)) {
loadResourceAliases(*resType, arr);
ResourceType type;
if (ResourceTypeMeta.getItem(key, type)) {
loadResourceAliases(type, arr);
} else {
// Ignore unknown resources
logger.warning() << "unknown resource type: " << key;

View File

@ -1,12 +1,21 @@
#pragma once
#include "typedefs.hpp"
#include "util/EnumMetadata.hpp"
class Content;
class ContentPackRuntime;
enum class ContentType { NONE, BLOCK, ITEM, ENTITY, GENERATOR };
VC_ENUM_METADATA(ContentType)
{"none", ContentType::NONE},
{"block", ContentType::BLOCK},
{"item", ContentType::ITEM},
{"entity", ContentType::ENTITY},
{"generator", ContentType::GENERATOR},
VC_ENUM_END
enum class ResourceType : size_t {
CAMERA,
POST_EFFECT_SLOT,
@ -15,3 +24,8 @@ enum class ResourceType : size_t {
inline constexpr auto RESOURCE_TYPES_COUNT =
static_cast<size_t>(ResourceType::LAST) + 1;
VC_ENUM_METADATA(ResourceType)
{"camera", ResourceType::CAMERA},
{"post-effect-slot", ResourceType::POST_EFFECT_SLOT},
VC_ENUM_END

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "../ContentLoader.hpp"
#include <algorithm>
@ -210,13 +211,9 @@ void ContentLoader::loadGenerator(
map.at("heights-bpd").get(def.heightsBPD);
std::string interpName;
map.at("heights-interpolation").get(interpName);
if (auto interp = InterpolationType_from(interpName)) {
def.heightsInterpolation = *interp;
}
InterpolationTypeMeta.getItem(interpName, def.heightsInterpolation);
map.at("biomes-interpolation").get(interpName);
if (auto interp = InterpolationType_from(interpName)) {
def.biomesInterpolation = *interp;
}
InterpolationTypeMeta.getItem(interpName, def.biomesInterpolation);
map.at("sea-level").get(def.seaLevel);
map.at("wide-structs-chunks-radius").get(def.wideStructsChunksRadius);

View File

@ -4,7 +4,6 @@
#include <string>
#include <stdexcept>
#include <unordered_map>
#include <optional>
#include "typedefs.hpp"
#include "interfaces/Serializable.hpp"

View File

@ -7,6 +7,7 @@
#include <glm/glm.hpp>
#include "data/dv_fwd.hpp"
#include "util/EnumMetadata.hpp"
class Shader;
@ -14,6 +15,14 @@ class PostEffect {
public:
struct Param {
enum class Type { FLOAT, VEC2, VEC3, VEC4 };
VC_ENUM_METADATA(Type)
{"float", Type::FLOAT},
{"vec2", Type::VEC2},
{"vec3", Type::VEC3},
{"vec4", Type::VEC4},
VC_ENUM_END
using Value = std::variant<float, glm::vec2, glm::vec3, glm::vec4>;
Type type;

View File

@ -1,39 +0,0 @@
#include "commons.hpp"
#include <map>
std::optional<CursorShape> CursorShape_from(std::string_view name) {
static std::map<std::string_view, CursorShape> shapes = {
{"arrow", CursorShape::ARROW},
{"text", CursorShape::TEXT},
{"crosshair", CursorShape::CROSSHAIR},
{"pointer", CursorShape::POINTER},
{"ew-resize", CursorShape::EW_RESIZE},
{"ns-resize", CursorShape::NS_RESIZE},
{"nwse-resize", CursorShape::NWSE_RESIZE},
{"nesw-resize", CursorShape::NESW_RESIZE},
{"all-resize", CursorShape::ALL_RESIZE},
{"not-allowed", CursorShape::NOT_ALLOWED}
};
const auto& found = shapes.find(name);
if (found == shapes.end()) {
return std::nullopt;
}
return found->second;
}
std::string to_string(CursorShape shape) {
static std::string names[] = {
"arrow",
"text",
"crosshair",
"pointer",
"ew-resize",
"ns-resize",
"nwse-resize",
"nesw-resize",
"all-resize",
"not-allowed"
};
return names[static_cast<int>(shape)];
}

View File

@ -3,6 +3,8 @@
#include <string>
#include <optional>
#include "util/EnumMetadata.hpp"
enum class DrawPrimitive {
point = 0,
line,
@ -48,8 +50,18 @@ enum class CursorShape {
LAST=NOT_ALLOWED
};
std::optional<CursorShape> CursorShape_from(std::string_view name);
std::string to_string(CursorShape shape);
VC_ENUM_METADATA(CursorShape)
{"arrow", CursorShape::ARROW},
{"text", CursorShape::TEXT},
{"crosshair", CursorShape::CROSSHAIR},
{"pointer", CursorShape::POINTER},
{"ew-resize", CursorShape::EW_RESIZE},
{"ns-resize", CursorShape::NS_RESIZE},
{"nwse-resize", CursorShape::NWSE_RESIZE},
{"nesw-resize", CursorShape::NESW_RESIZE},
{"all-resize", CursorShape::ALL_RESIZE},
{"not-allowed", CursorShape::NOT_ALLOWED},
VC_ENUM_END
class Flushable {
public:

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "gui_xml.hpp"
#include <stdexcept>
@ -168,8 +169,9 @@ static void read_uinode(
node.setTooltipDelay(element.attr("tooltip-delay").asFloat());
}
if (element.has("cursor")) {
if (auto cursor = CursorShape_from(element.attr("cursor").getText())) {
node.setCursor(*cursor);
CursorShape cursor;
if (CursorShapeMeta.getItem(element.attr("cursor").getText(), cursor)) {
node.setCursor(cursor);
}
}

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "EngineController.hpp"
#include <algorithm>
@ -164,7 +165,7 @@ static dv::value create_missing_content_report(
auto root = dv::object();
auto& contentEntries = root.list("content");
for (auto& entry : report->getMissingContent()) {
std::string contentName = ContentType_name(entry.type);
std::string contentName = ContentTypeMeta.getNameString(entry.type);
auto& contentEntry = contentEntries.object();
contentEntry["type"] = contentName;
contentEntry["name"] = entry.name;

View File

@ -1,3 +1,5 @@
#define VC_ENABLE_REFLECTION
#include "util/stringutil.hpp"
#include "libentity.hpp"
@ -96,8 +98,8 @@ static int l_set_crouching(lua::State* L) {
static int l_get_body_type(lua::State* L) {
if (auto entity = get_entity(L, 1)) {
return lua::pushstring(
L, to_string(entity->getRigidbody().hitbox.type)
return lua::pushlstring(
L, BodyTypeMeta.getName(entity->getRigidbody().hitbox.type)
);
}
return 0;
@ -105,9 +107,9 @@ static int l_get_body_type(lua::State* L) {
static int l_set_body_type(lua::State* L) {
if (auto entity = get_entity(L, 1)) {
if (auto type = BodyType_from(lua::tostring(L, 2))) {
entity->getRigidbody().hitbox.type = *type;
} else {
if (!BodyTypeMeta.getItem(
lua::tostring(L, 2), entity->getRigidbody().hitbox.type
)) {
throw std::runtime_error(
"unknown body type " + util::quote(lua::tostring(L, 2))
);

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "content/Content.hpp"
#include "content/ContentLoader.hpp"
#include "content/ContentControl.hpp"
@ -311,7 +312,7 @@ static int l_get_textures(lua::State* L) {
static int l_get_model(lua::State* L) {
if (auto def = require_block(L)) {
return lua::pushstring(L, to_string(def->model));
return lua::pushlstring(L, BlockModelMeta.getName(def->model));
}
return 0;
}

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "libgui.hpp"
#include "assets/Assets.hpp"
#include "engine/Engine.hpp"
@ -422,7 +423,7 @@ static int p_get_line_pos(UINode*, lua::State* L) {
}
static int p_get_cursor(UINode* node, lua::State* L) {
return lua::pushstring(L, to_string(node->getCursor()));
return lua::pushlstring(L, CursorShapeMeta.getName(node->getCursor()));
}
static int p_get_scroll(UINode* node, lua::State* L) {
@ -660,9 +661,9 @@ static void p_set_focused(
}
static void p_set_cursor(UINode* node, lua::State* L, int idx) {
if (auto cursor = CursorShape_from(lua::require_string(L, idx))) {
node->setCursor(*cursor);
}
auto cursor = CursorShape::ARROW; // reset to default
CursorShapeMeta.getItem(lua::require_string(L, idx), cursor);
node->setCursor(cursor);
}
static int p_set_scroll(UINode* node, lua::State* L, int idx) {

View File

@ -5,17 +5,6 @@
#include <stdexcept>
#include <glm/glm.hpp>
std::optional<InterpolationType> InterpolationType_from(std::string_view str) {
if (str == "nearest") {
return InterpolationType::NEAREST;
} else if (str == "linear") {
return InterpolationType::LINEAR;
} else if (str == "cubic") {
return InterpolationType::CUBIC;
}
return std::nullopt;
}
static inline float sample_at(
const float* buffer,
uint width,

View File

@ -6,6 +6,7 @@
#include "typedefs.hpp"
#include "maths/Heightmap.hpp"
#include "util/EnumMetadata.hpp"
enum class InterpolationType {
NEAREST,
@ -13,7 +14,11 @@ enum class InterpolationType {
CUBIC,
};
std::optional<InterpolationType> InterpolationType_from(std::string_view str);
VC_ENUM_METADATA(InterpolationType)
{"nearest", InterpolationType::NEAREST},
{"linear", InterpolationType::LINEAR},
{"cubic", InterpolationType::CUBIC},
VC_ENUM_END
class Heightmap {
uint width, height;

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "Entities.hpp"
#include <glm/ext/matrix_transform.hpp>
@ -216,9 +217,7 @@ void Entities::loadEntity(const dv::value& map, Entity entity) {
dv::get_vec(bodymap, "vel", body.hitbox.velocity);
std::string bodyTypeName;
map.at("type").get(bodyTypeName);
if (auto bodyType = BodyType_from(bodyTypeName)) {
body.hitbox.type = *bodyType;
}
BodyTypeMeta.getItem(bodyTypeName, body.hitbox.type);
bodymap["crouch"].asBoolean(body.hitbox.crouching);
bodymap["damping"].asNumber(body.hitbox.linearDamping);
}
@ -329,7 +328,7 @@ dv::value Entities::serialize(const Entity& entity) {
if (def.save.body.settings) {
bodymap["damping"] = rigidbody.hitbox.linearDamping;
if (hitbox.type != def.bodyType) {
bodymap["type"] = to_string(hitbox.type);
bodymap["type"] = BodyTypeMeta.getNameString(hitbox.type);
}
if (hitbox.crouching) {
bodymap["crouch"] = hitbox.crouching;

View File

@ -2,7 +2,6 @@
#include <glm/glm.hpp>
#include <memory>
#include <optional>
#include "interfaces/Serializable.hpp"
#include "settings.hpp"

View File

@ -2,26 +2,6 @@
#include <stdexcept>
std::optional<BodyType> BodyType_from(std::string_view str) {
if (str == "kinematic") {
return BodyType::KINEMATIC;
} else if (str == "dynamic") {
return BodyType::DYNAMIC;
} else if (str == "static") {
return BodyType::STATIC;
}
return std::nullopt;
}
std::string to_string(BodyType type) {
switch (type) {
case BodyType::KINEMATIC: return "kinematic";
case BodyType::DYNAMIC: return "dynamic";
case BodyType::STATIC: return "static";
default: return "unknown";
}
}
Hitbox::Hitbox(BodyType type, glm::vec3 position, glm::vec3 halfsize)
: type(type),
position(position),

View File

@ -2,10 +2,10 @@
#include "maths/aabb.hpp"
#include "typedefs.hpp"
#include "util/EnumMetadata.hpp"
#include <set>
#include <string>
#include <optional>
#include <functional>
#include <glm/glm.hpp>
@ -41,8 +41,11 @@ enum class BodyType {
STATIC, KINEMATIC, DYNAMIC
};
std::optional<BodyType> BodyType_from(std::string_view str);
std::string to_string(BodyType type);
VC_ENUM_METADATA(BodyType)
{"static", BodyType::STATIC},
{"kinematic", BodyType::KINEMATIC},
{"dynamic", BodyType::DYNAMIC},
VC_ENUM_END
struct Hitbox {
BodyType type;

View File

@ -1,37 +1,13 @@
#define VC_ENABLE_REFLECTION
#include "NotePreset.hpp"
#include <map>
#include <vector>
#include "data/dv_util.hpp"
std::string to_string(NoteDisplayMode mode) {
static std::vector<std::string> names = {
"static_billboard",
"y_free_billboard",
"xy_free_billboard",
"projected"
};
return names.at(static_cast<int>(mode));
}
std::optional<NoteDisplayMode> NoteDisplayMode_from(std::string_view s) {
static std::map<std::string_view, NoteDisplayMode, std::less<>> map {
{"static_billboard", NoteDisplayMode::STATIC_BILLBOARD},
{"y_free_billboard", NoteDisplayMode::Y_FREE_BILLBOARD},
{"xy_free_billboard", NoteDisplayMode::XY_FREE_BILLBOARD},
{"projected", NoteDisplayMode::PROJECTED}
};
const auto& found = map.find(s);
if (found == map.end()) {
return std::nullopt;
}
return found->second;
}
#include <vector>
dv::value NotePreset::serialize() const {
return dv::object({
{"display", to_string(displayMode)},
{"display", NoteDisplayModeMeta.getNameString(displayMode)},
{"color", dv::to_value(color)},
{"scale", scale},
{"render_distance", renderDistance},
@ -42,7 +18,7 @@ dv::value NotePreset::serialize() const {
void NotePreset::deserialize(const dv::value& src) {
if (src.has("display")) {
displayMode = NoteDisplayMode_from(src["display"].asString()).value();
NoteDisplayModeMeta.getItem(src["display"].asString(), displayMode);
}
if (src.has("color")) {
dv::get_vec(src["color"], color);

View File

@ -2,10 +2,10 @@
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <optional>
#include <string>
#include "interfaces/Serializable.hpp"
#include "util/EnumMetadata.hpp"
enum class NoteDisplayMode {
STATIC_BILLBOARD,
@ -14,8 +14,12 @@ enum class NoteDisplayMode {
PROJECTED
};
std::string to_string(NoteDisplayMode mode);
std::optional<NoteDisplayMode> NoteDisplayMode_from(std::string_view s);
VC_ENUM_METADATA(NoteDisplayMode)
{"static_billboard", NoteDisplayMode::STATIC_BILLBOARD},
{"y_free_billboard", NoteDisplayMode::Y_FREE_BILLBOARD},
{"xy_free_billboard", NoteDisplayMode::XY_FREE_BILLBOARD},
{"projected", NoteDisplayMode::PROJECTED},
VC_ENUM_END
struct NotePreset : public Serializable {
NoteDisplayMode displayMode = NoteDisplayMode::STATIC_BILLBOARD;

View File

@ -1,26 +1,8 @@
#define VC_ENABLE_REFLECTION
#include "ParticlesPreset.hpp"
#include "data/dv_util.hpp"
std::string to_string(ParticleSpawnShape shape) {
static std::string names[] = {
"ball",
"sphere",
"box"
};
return names[static_cast<int>(shape)];
}
ParticleSpawnShape ParticleSpawnShape_from(std::string_view s) {
if (s == "ball") {
return ParticleSpawnShape::BALL;
} else if (s == "sphere") {
return ParticleSpawnShape::SPHERE;
} else {
return ParticleSpawnShape::BOX;
}
}
dv::value ParticlesPreset::serialize() const {
auto root = dv::object();
if (frames.empty()) {
@ -47,7 +29,7 @@ dv::value ParticlesPreset::serialize() const {
root["min_angular_vel"] = minAngularVelocity;
root["max_angular_vel"] = maxAngularVelocity;
root["spawn_spread"] = dv::to_value(size);
root["spawn_shape"] = to_string(spawnShape);
root["spawn_shape"] = ParticleSpawnShapeMeta.getName(spawnShape);
root["random_sub_uv"] = randomSubUV;
return root;
}
@ -82,7 +64,7 @@ void ParticlesPreset::deserialize(const dv::value& src) {
dv::get_vec(src["explosion"], explosion);
}
if (src.has("spawn_shape")) {
spawnShape = ParticleSpawnShape_from(src["spawn_shape"].asString());
ParticleSpawnShapeMeta.getItem(src["spawn_shape"].asString(), spawnShape);
}
if (src.has("frames")) {
for (const auto& frame : src["frames"]) {

View File

@ -5,8 +5,9 @@
#include <vector>
#include "interfaces/Serializable.hpp"
#include "util/EnumMetadata.hpp"
enum ParticleSpawnShape {
enum class ParticleSpawnShape {
/// @brief Coordinates are regulary distributed within
/// the volume of a ball.
BALL = 0,
@ -18,8 +19,11 @@ enum ParticleSpawnShape {
BOX
};
std::string to_string(ParticleSpawnShape shape);
ParticleSpawnShape ParticleSpawnShape_from(std::string_view s);
VC_ENUM_METADATA(ParticleSpawnShape)
{"ball", ParticleSpawnShape::BALL},
{"sphere", ParticleSpawnShape::SPHERE},
{"box", ParticleSpawnShape::BOX},
VC_ENUM_END
struct ParticlesPreset : public Serializable {
/// @brief Collision detection
@ -53,7 +57,7 @@ struct ParticlesPreset : public Serializable {
/// @brief Maximum angular velocity
float maxAngularVelocity = 0.0f;
/// @brief Spawn spread shape
ParticleSpawnShape spawnShape = BALL;
ParticleSpawnShape spawnShape = ParticleSpawnShape::BALL;
/// @brief Spawn spread
glm::vec3 spawnSpread {};
/// @brief Texture name

61
src/util/EnumMetadata.hpp Normal file
View File

@ -0,0 +1,61 @@
#pragma once
#ifdef VC_ENABLE_REFLECTION
#define VC_ENUM_METADATA(NAME) static inline util::EnumMetadata<NAME> NAME##Meta {
#define VC_ENUM_END };
#include <map>
#include <string>
#include <utility>
namespace util {
template<typename EnumT>
class EnumMetadata {
public:
EnumMetadata(
std::initializer_list<std::pair<const std::string_view, EnumT>> items
)
: items(items) {
for (const auto& [name, item] : items) {
names[item] = name;
}
}
std::string_view getName(EnumT item) const {
const auto& found = names.find(item);
if (found == names.end()) {
return "";
}
return found->second;
}
std::string getNameString(EnumT item) const {
return std::string(getName(item));
}
bool getItem(std::string_view name, EnumT& dst) const {
const auto& found = items.find(name);
if (found == items.end()) {
return false;
}
dst = found->second;
return true;
}
size_t size() const {
return items.size();
}
private:
std::map<std::string_view, EnumT> items;
std::map<EnumT, std::string_view> names;
};
}
#else
#include <initializer_list>
#define VC_ENUM_METADATA(NAME) \
struct NAME##__PAIR {const char* n; NAME i;}; \
[[maybe_unused]] static inline std::initializer_list<NAME##__PAIR> NAME##_PAIRS {
#define VC_ENUM_END };
#endif // VC_ENABLE_REFLECTION

View File

@ -18,62 +18,6 @@ dv::value BlockMaterial::serialize() const {
});
}
std::string to_string(BlockModel model) {
switch (model) {
case BlockModel::none:
return "none";
case BlockModel::block:
return "block";
case BlockModel::xsprite:
return "X";
case BlockModel::aabb:
return "aabb";
case BlockModel::custom:
return "custom";
default:
return "unknown";
}
}
std::optional<BlockModel> BlockModel_from(std::string_view str) {
if (str == "none") {
return BlockModel::none;
} else if (str == "block") {
return BlockModel::block;
} else if (str == "X") {
return BlockModel::xsprite;
} else if (str == "aabb") {
return BlockModel::aabb;
} else if (str == "custom") {
return BlockModel::custom;
}
return std::nullopt;
}
std::string to_string(CullingMode mode) {
switch (mode) {
case CullingMode::DEFAULT:
return "default";
case CullingMode::OPTIONAL:
return "optional";
case CullingMode::DISABLED:
return "disabled";
default:
return "unknown";
}
}
std::optional<CullingMode> CullingMode_from(std::string_view str) {
if (str == "default") {
return CullingMode::DEFAULT;
} else if (str == "optional") {
return CullingMode::OPTIONAL;
} else if (str == "disabled") {
return CullingMode::DISABLED;
}
return std::nullopt;
}
CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ)
: axes({axisX, axisY, axisZ}) {
fix = glm::ivec3(0);

View File

@ -1,7 +1,6 @@
#pragma once
#include <glm/glm.hpp>
#include <optional>
#include <string>
#include <vector>
#include <array>
@ -10,6 +9,7 @@
#include "maths/UVRegion.hpp"
#include "maths/aabb.hpp"
#include "typedefs.hpp"
#include "util/EnumMetadata.hpp"
struct ParticlesPreset;
@ -93,8 +93,13 @@ enum class BlockModel {
custom
};
std::string to_string(BlockModel model);
std::optional<BlockModel> BlockModel_from(std::string_view str);
VC_ENUM_METADATA(BlockModel)
{"none", BlockModel::none},
{"block", BlockModel::block},
{"X", BlockModel::xsprite},
{"aabb", BlockModel::aabb},
{"custom", BlockModel::custom},
VC_ENUM_END
enum class CullingMode {
DEFAULT,
@ -102,8 +107,11 @@ enum class CullingMode {
DISABLED,
};
std::string to_string(CullingMode mode);
std::optional<CullingMode> CullingMode_from(std::string_view str);
VC_ENUM_METADATA(CullingMode)
{"default", CullingMode::DEFAULT},
{"optional", CullingMode::OPTIONAL},
{"disabled", CullingMode::DISABLED},
VC_ENUM_END
using BoxModel = AABB;

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "World.hpp"
#include <glm/glm.hpp>
@ -49,7 +50,7 @@ void World::updateTimers(float delta) {
void World::writeResources(const Content& content) {
auto root = dv::object();
for (size_t typeIndex = 0; typeIndex < RESOURCE_TYPES_COUNT; typeIndex++) {
auto typeName = to_string(static_cast<ResourceType>(typeIndex));
auto typeName = ResourceTypeMeta.getNameString(static_cast<ResourceType>(typeIndex));
auto& list = root.list(typeName);
auto& indices = content.resourceIndices[typeIndex];
for (size_t i = 0; i < indices.size(); i++) {

View File

@ -1,3 +1,4 @@
#define VC_ENABLE_REFLECTION
#include "WorldFiles.hpp"
#include <cassert>
@ -182,8 +183,9 @@ bool WorldFiles::readResourcesData(const Content& content) {
}
auto root = io::read_json(file);
for (const auto& [key, arr] : root.asObject()) {
if (auto resType = ResourceType_from(key)) {
read_resources_data(content, arr, *resType);
ResourceType type;
if (ResourceTypeMeta.getItem(key, type)) {
read_resources_data(content, arr, type);
} else {
logger.warning() << "unknown resource type: " << key;
}