Component+Scene: Restructure scene .json to allow multiple components
This commit is contained in:
+36
-18
@@ -1,50 +1,68 @@
|
||||
{
|
||||
"init": "assets/lua/scene1-init.lua",
|
||||
"camera": {
|
||||
"name": "Camera",
|
||||
"entities": [
|
||||
{
|
||||
"id": { "id": 12312312 },
|
||||
"tag": { "tag": "Camera" },
|
||||
"transform" : {
|
||||
"translate": [0.0, 0.0, 1.0],
|
||||
"rotate": [0.0, 0.0, -1.0],
|
||||
"scale": [ 1.0, 1.0, 1.0 ],
|
||||
"type": "perspective",
|
||||
"script": {
|
||||
"type": "lua",
|
||||
"name": "assets/lua/cameracontroller.lua"
|
||||
}
|
||||
"scale": [1.0, 1.0, 1.0]
|
||||
},
|
||||
"camera": { "type": "perspective" },
|
||||
"lua-scripts": [
|
||||
{ "path": "assets/lua/cameracontroller.lua" }
|
||||
]
|
||||
},
|
||||
"quad": [
|
||||
{
|
||||
"name": "Quad",
|
||||
"id": { "id": 564564564 },
|
||||
"tag": { "tag": "Quad" },
|
||||
"transform" : {
|
||||
"translate": [ 0.0, 0.0, 0.0 ],
|
||||
"rotate": [ 0.0, 0.0, 0.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ]
|
||||
},
|
||||
"sprite": {
|
||||
"color": [ 1.0, 1.0, 1.0, 1.0 ],
|
||||
"texture": "assets/gfx/test.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Quad 2",
|
||||
"id": { "id": 97897897 },
|
||||
"tag": { "tag": "Quad 2" },
|
||||
"transform" : {
|
||||
"translate": [ 1.1, 0.0, 0.0 ],
|
||||
"rotate": [ 0.0, 0.0, 0.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ]
|
||||
},
|
||||
"sprite": {
|
||||
"color": [ 0.5, 0.6, 0.8, 1.0 ],
|
||||
"texture": "assets/gfx/test.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Quad 3",
|
||||
"id": { "id": 3424242 },
|
||||
"tag": { "tag": "Quad 3" },
|
||||
"transform" : {
|
||||
"translate": [ 2.2, 0.0, 0.0 ],
|
||||
"rotate": [ 0.0, 0.0, 0.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ],
|
||||
"scale": [ 1.0, 1.0, 1.0 ]
|
||||
},
|
||||
"sprite": {
|
||||
"color": [ 1.0, 1.0, 1.0, 1.0 ],
|
||||
"texture": "assets/gfx/test-inverted.png"
|
||||
}
|
||||
],
|
||||
"text": [
|
||||
},
|
||||
{
|
||||
"name": "Text",
|
||||
"id": { "id": 675754 },
|
||||
"tag": { "tag": "Text" },
|
||||
"text": {
|
||||
"content": "Hello World!",
|
||||
"font": "assets/fnt/open-sans",
|
||||
"font-size": 24,
|
||||
"line-spacing": 1.0,
|
||||
"width": 150
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ruc/format/print.h"
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/component/cameracomponent.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
void fromJson(const ruc::Json& json, CameraComponent& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||
|
||||
if (json.exists("type")) {
|
||||
value.type = json.at("type").get<std::string>() == "orthographic" ? CameraType::Orthographic : CameraType::Perspective;
|
||||
}
|
||||
if (json.exists("zoom-level")) {
|
||||
json.at("zoom-level").getTo(value.zoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4
|
||||
#include "glm/ext/vector_float3.hpp" // glm::vec3
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
@@ -32,4 +33,6 @@ struct CameraComponent {
|
||||
glm::mat4 projection { 1.0f }; // Identity matrix
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, CameraComponent& value);
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/component/id-component.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
void fromJson(const ruc::Json& json, IDComponent& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||
|
||||
if (json.exists("id")) {
|
||||
json.at("id").getTo(value.id);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/uid.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
struct IDComponent {
|
||||
UID id;
|
||||
|
||||
IDComponent() = default;
|
||||
IDComponent(UID id)
|
||||
: id(id)
|
||||
{
|
||||
}
|
||||
IDComponent(const IDComponent&) = default;
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, IDComponent& value);
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/component/luascriptcomponent.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
void fromJson(const ruc::Json& json, LuaScriptComponent& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||
|
||||
VERIFY(json.exists("path"), "path not found");
|
||||
json.at("path").getTo(value.path);
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string> // std::string
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
class LuaScript;
|
||||
@@ -24,4 +26,7 @@ struct LuaScriptComponent {
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, LuaScriptComponent& value);
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/component/nativescriptcomponent.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
void fromJson(const ruc::Json& json, NativeScriptComponent& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||
|
||||
VERIFY(json.exists("name"), "name not found");
|
||||
json.at("name").getTo(value.name);
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility> // std::move
|
||||
|
||||
#include "inferno/script/nativescript.h"
|
||||
|
||||
@@ -14,17 +15,29 @@ namespace Inferno {
|
||||
|
||||
struct NativeScriptComponent {
|
||||
NativeScript* instance { nullptr };
|
||||
std::string name;
|
||||
|
||||
NativeScript::InitializeFunction initialize { nullptr };
|
||||
NativeScript::DestroyFunction destroy { nullptr };
|
||||
|
||||
// Dont allow manually setting instance during construction
|
||||
NativeScriptComponent() {}
|
||||
NativeScriptComponent(const std::string& binding)
|
||||
NativeScriptComponent(const std::string& name)
|
||||
: name(std::move(name))
|
||||
{
|
||||
initialize = NativeScriptBinding::the().initializeBinding(binding);
|
||||
destroy = NativeScriptBinding::the().destroyBinding(binding);
|
||||
bind();
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
VERIFY(initialize == nullptr && destroy == nullptr, "NativeScript already bound");
|
||||
|
||||
VERIFY(name != "", "name not set");
|
||||
initialize = NativeScriptBinding::the().initializeBinding(name);
|
||||
destroy = NativeScriptBinding::the().destroyBinding(name);
|
||||
}
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, NativeScriptComponent& value);
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/component/tagcomponent.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
void fromJson(const ruc::Json& json, TagComponent& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||
|
||||
if (json.exists("tag")) {
|
||||
json.at("tag").getTo(value.tag);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <string> // std::string
|
||||
#include <utility> // std::move
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
struct TagComponent {
|
||||
@@ -23,4 +25,6 @@ struct TagComponent {
|
||||
operator const std::string&() const { return tag; }
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, TagComponent& value);
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
+63
-53
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint32_t
|
||||
#include <limits> // std::numeric_limits
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
#include "ruc/meta/assert.h"
|
||||
|
||||
#include "inferno/component/cameracomponent.h"
|
||||
#include "inferno/component/id-component.h"
|
||||
#include "inferno/component/luascriptcomponent.h"
|
||||
#include "inferno/component/nativescriptcomponent.h"
|
||||
#include "inferno/component/spritecomponent.h"
|
||||
@@ -26,6 +28,7 @@
|
||||
#include "inferno/system/scriptsystem.h"
|
||||
#include "inferno/system/textareasystem.h"
|
||||
#include "inferno/system/transformsystem.h"
|
||||
#include "inferno/uid.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
@@ -47,54 +50,66 @@ void Scene::initialize()
|
||||
|
||||
auto sceneJson = ruc::Json::parse(ruc::File("assets/scene/scene1.json").data());
|
||||
|
||||
// Camera
|
||||
|
||||
VERIFY(sceneJson.exists("camera"), "scene doesnt contain a camera");
|
||||
auto& cameraJson = sceneJson.at("camera");
|
||||
uint32_t camera = loadEntity(cameraJson);
|
||||
|
||||
auto& cameraComponent = addComponent<CameraComponent>(camera);
|
||||
if (cameraJson.exists("type") && cameraJson.at("type").get<std::string>() == "orthographic") {
|
||||
cameraComponent.type = CameraType::Orthographic;
|
||||
}
|
||||
if (cameraJson.exists("zoom-level") && cameraJson.at("zoom-level").type() == ruc::Json::Type::Number) {
|
||||
cameraComponent.zoomLevel = cameraJson.at("zoom-level").asDouble();
|
||||
if (sceneJson.exists("init")) {
|
||||
// TODO: load either NativeScript or LuaScript?
|
||||
}
|
||||
|
||||
if (cameraJson.exists("script")) {
|
||||
auto& cameraScript = cameraJson.at("script");
|
||||
if (cameraScript.exists("type") && cameraScript.exists("name")) {
|
||||
auto name = cameraScript.at("name").get<std::string>();
|
||||
if (cameraScript.at("type").get<std::string>() == "lua") {
|
||||
addComponent<LuaScriptComponent>(camera, name);
|
||||
}
|
||||
else {
|
||||
addComponent<NativeScriptComponent>(camera, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Entities
|
||||
// -------------------------------------
|
||||
|
||||
// Quads
|
||||
if (sceneJson.exists("entities")) {
|
||||
const auto& entityJson = sceneJson.at("entities");
|
||||
VERIFY(entityJson.type() == ruc::Json::Type::Array);
|
||||
const auto& entities = entityJson.asArray();
|
||||
for (size_t i = 0; i < entities.size(); ++i) {
|
||||
|
||||
if (sceneJson.exists("quad") && sceneJson.at("quad").type() == ruc::Json::Type::Array) {
|
||||
auto& quads = sceneJson.at("quad").asArray().elements();
|
||||
for (const auto& quad : quads) {
|
||||
uint32_t quadEntity = loadEntity(quad);
|
||||
addComponent<SpriteComponent>(quadEntity);
|
||||
auto& spriteComponent = getComponent<SpriteComponent>(quadEntity);
|
||||
quad.getTo(spriteComponent);
|
||||
uint32_t entity = createEntity();
|
||||
|
||||
VERIFY(entities.at(i).type() == ruc::Json::Type::Object);
|
||||
const auto& components = entities.at(i);
|
||||
|
||||
// ID is required
|
||||
VERIFY(components.exists("id"), "id not found");
|
||||
auto& id = getComponent<IDComponent>(entity);
|
||||
components.at("id").getTo(id);
|
||||
|
||||
if (components.exists("tag")) {
|
||||
auto& tag = getComponent<TagComponent>(entity);
|
||||
components.at("tag").getTo(tag);
|
||||
}
|
||||
if (components.exists("transform")) {
|
||||
auto& transform = getComponent<TransformComponent>(entity);
|
||||
components.at("transform").getTo(transform);
|
||||
}
|
||||
if (components.exists("camera")) {
|
||||
auto& camera = addComponent<CameraComponent>(entity);
|
||||
components.at("camera").getTo(camera);
|
||||
}
|
||||
if (components.exists("lua-scripts")) {
|
||||
VERIFY(components.at("lua-scripts").type() == ruc::Json::Type::Array);
|
||||
const auto& scripts = components.at("lua-scripts").asArray();
|
||||
for (size_t j = 0; j < scripts.size(); ++j) {
|
||||
auto& script = addComponent<LuaScriptComponent>(entity);
|
||||
scripts.at(j).getTo(script);
|
||||
}
|
||||
}
|
||||
|
||||
// Text
|
||||
|
||||
if (sceneJson.exists("text") && sceneJson.at("text").type() == ruc::Json::Type::Array) {
|
||||
auto& texts = sceneJson.at("text").asArray().elements();
|
||||
for (const auto& text : texts) {
|
||||
uint32_t textEntity = loadEntity(text);
|
||||
addComponent<TextAreaComponent>(textEntity);
|
||||
auto& textAreaComponent = getComponent<TextAreaComponent>(textEntity);
|
||||
text.getTo(textAreaComponent);
|
||||
if (components.exists("native-scripts")) {
|
||||
VERIFY(components.at("native-scripts").type() == ruc::Json::Type::Array);
|
||||
const auto& scripts = components.at("native-scripts").asArray();
|
||||
for (size_t j = 0; j < scripts.size(); ++j) {
|
||||
auto& script = addComponent<NativeScriptComponent>(entity);
|
||||
scripts.at(j).getTo(script);
|
||||
script.bind();
|
||||
}
|
||||
}
|
||||
if (components.exists("sprite")) {
|
||||
auto& sprite = addComponent<SpriteComponent>(entity);
|
||||
components.at("sprite").getTo(sprite);
|
||||
}
|
||||
if (components.exists("text")) {
|
||||
auto& text = addComponent<TextAreaComponent>(entity);
|
||||
components.at("text").getTo(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,20 +140,15 @@ void Scene::destroy()
|
||||
|
||||
uint32_t Scene::createEntity(const std::string& name)
|
||||
{
|
||||
uint32_t entity = static_cast<uint32_t>(m_registry->create());
|
||||
addComponent<TagComponent>(entity, name.empty() ? "Unnamed Entity" : name);
|
||||
addComponent<TransformComponent>(entity);
|
||||
|
||||
return entity;
|
||||
return createEntityWithUID(UID(), name);
|
||||
}
|
||||
|
||||
uint32_t Scene::loadEntity(ruc::Json json)
|
||||
uint32_t Scene::createEntityWithUID(UID id, const std::string& name)
|
||||
{
|
||||
uint32_t entity = createEntity((json.exists("name"))
|
||||
? json.at("name").get<std::string>()
|
||||
: "");
|
||||
auto& transform = getComponent<TransformComponent>(entity);
|
||||
json.getTo(transform);
|
||||
uint32_t entity = static_cast<uint32_t>(m_registry->create());
|
||||
addComponent<IDComponent>(entity, id);
|
||||
addComponent<TagComponent>(entity, name.empty() ? "Unnamed Entity" : name);
|
||||
addComponent<TransformComponent>(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint32_t
|
||||
#include <memory> // std::shared_ptr
|
||||
|
||||
@@ -14,6 +15,8 @@
|
||||
#include "ruc/format/format.h"
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/uid.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
class Camera;
|
||||
@@ -27,7 +30,7 @@ public:
|
||||
void destroy();
|
||||
|
||||
uint32_t createEntity(const std::string& name = "");
|
||||
uint32_t loadEntity(ruc::Json json);
|
||||
uint32_t createEntityWithUID(UID id, const std::string& name = "");
|
||||
uint32_t findEntity(std::string_view name);
|
||||
void destroyEntity(uint32_t entity);
|
||||
|
||||
@@ -49,7 +52,8 @@ public:
|
||||
return m_registry->any<T...>(entt::entity { entity });
|
||||
}
|
||||
|
||||
// @Todo Should replace be allowed? could trigger memory leaks with nativescript
|
||||
// TODO: Should replace be allowed? could trigger memory leaks with nativescript
|
||||
// TODO: Replace will make it so an entity cant have multiple scripts
|
||||
template<typename T, typename... P>
|
||||
T& addComponent(uint32_t entity, P&&... parameters) const
|
||||
{
|
||||
@@ -64,7 +68,7 @@ public:
|
||||
return m_registry->remove_if_exists<T>(entt::entity { entity });
|
||||
}
|
||||
|
||||
// @Todo Should replace be allowed? could trigger memory leaks with nativescript
|
||||
// TODO: Should replace be allowed? could trigger memory leaks with nativescript
|
||||
template<typename T, typename... P>
|
||||
T& getComponent(uint32_t entity, P&&... parameters) const
|
||||
{
|
||||
|
||||
@@ -55,8 +55,8 @@ public:
|
||||
m_detroyBindings.emplace(binding, destroy);
|
||||
}
|
||||
|
||||
NativeScript::InitializeFunction initializeBinding(const std::string& binding) { return m_initializeBindings[binding]; }
|
||||
NativeScript::DestroyFunction destroyBinding(const std::string& binding) { return m_detroyBindings[binding]; }
|
||||
NativeScript::InitializeFunction initializeBinding(const std::string& name) { return m_initializeBindings[name]; }
|
||||
NativeScript::DestroyFunction destroyBinding(const std::string& name) { return m_detroyBindings[name]; }
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, NativeScript::InitializeFunction> m_initializeBindings;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
#include "ruc/format/log.h"
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
#include "inferno/uid.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
static std::random_device s_seed;
|
||||
static std::mt19937_64 s_engine(s_seed());
|
||||
static std::uniform_int_distribution<uint64_t> s_distribution;
|
||||
|
||||
UID::UID()
|
||||
: m_uid(s_distribution(s_engine))
|
||||
{
|
||||
}
|
||||
|
||||
UID::UID(uint64_t uid)
|
||||
: m_uid(uid)
|
||||
{
|
||||
}
|
||||
|
||||
void fromJson(const ruc::Json& json, UID& value)
|
||||
{
|
||||
VERIFY(json.type() == ruc::Json::Type::Number);
|
||||
|
||||
value = UID((int64_t)json.asDouble());
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
|
||||
#include "ruc/json/json.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
class UID {
|
||||
public:
|
||||
UID();
|
||||
UID(uint64_t uid);
|
||||
|
||||
// Comparison operator for std::map
|
||||
bool operator<(const UID& other) const
|
||||
{
|
||||
return m_uid < other.m_uid;
|
||||
}
|
||||
|
||||
operator uint64_t() const { return m_uid; }
|
||||
|
||||
private:
|
||||
uint64_t m_uid;
|
||||
};
|
||||
|
||||
void fromJson(const ruc::Json& json, UID& value);
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
namespace std {
|
||||
|
||||
// Hash function for std::unordered_map
|
||||
template<>
|
||||
struct hash<Inferno::UID> {
|
||||
size_t operator()(const Inferno::UID& uid) const
|
||||
{
|
||||
return hash<uint64_t>()(static_cast<uint64_t>(uid));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
Reference in New Issue
Block a user