UUID & start on IDs

This commit is contained in:
Curle 2023-03-11 07:14:36 +00:00
parent 1297af3db1
commit 387bc84985
5 changed files with 199 additions and 0 deletions

View File

@ -7,12 +7,14 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
FILE(GLOB_RECURSE SOURCES
core/src/*.cpp
shadow-entity/src/*.cpp
shadow-renderer/src/*.cpp
shadow-reflection/src/*.cpp
shadow-utility/src/*.cpp
)
FILE(GLOB_RECURSE HEADERS
core/inc/*.h
shadow-entity/inc/*.h
shadow-renderer/inc/*.h
shadow-reflection/inc/*.h
shadow-utility/inc/*.h
@ -24,6 +26,7 @@ target_include_directories(shadow-engine
PRIVATE ${SDL2_INCLUDE_DIRS}
PUBLIC
core/inc
shadow-entity/inc
shadow-renderer/inc
shadow-reflection/inc
shadow-utility/inc

View File

@ -0,0 +1,64 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <string>
// ShadowEntity temporary namespace
namespace SE {
/**
* Universally Unique ID.
* 128 Bits.
*
* Unique per runtime only - the suitability for serialization is undetermined.
*/
class UUID {
/**
* Data storage; 128 bits.
* 2 x 64 bit
* 4 x 32 bit
* 16 x 8 bit
*/
union Data {
uint64_t u64[2];
uint32_t u32[4];
uint8_t u8[16];
};
public:
// Create a new, unused, UUID.
static UUID Generate();
// Check whether the UUID is correctly formed.
static bool IsValidStr(char const* str);
// Create an empty UUID.
inline UUID() { std::memset(&data.u8, 0, 16); }
// Create a UUID based on the given values.
inline UUID(uint64_t i0, uint64_t i1) { data.u64[0] = i0; data.u64[1] = i1; }
inline UUID(uint32_t i0, uint32_t i1, uint32_t i2, uint32_t i3) { data.u32[0] = i0; data.u32[1] = i1; data.u32[2] = i2; data.u32[3] = i3; }
inline explicit UUID(std::string const& str) : UUID(str.c_str()) {}
// Create a UUID from the given format.
explicit UUID(char const* str);
// Check whether the UUID is nonzero.
inline bool IsValid() const { return data.u64[0] != 0 && data.u64[1] != 0; }
// Set the UUID to zero.
inline void Clear() { std::memset(&data.u8, 0, 16); }
// Get a section of the UUID's data as the given bit width.
inline uint8_t GetU8(size_t idx) const { return data.u8[idx]; }
inline uint32_t GetU32(size_t idx) const { return data.u32[idx]; }
inline uint64_t GetU64(size_t idx) const { return data.u64[idx]; }
// Check whether this and a given UUID are in/equal.
__inline bool operator==(UUID const& other) const { return data.u64[0] == other.data.u64[0] && data.u64[1] == other.data.u64[1]; }
__inline bool operator!=(UUID const& other) const { return !(*this == other); }
private:
Data data {};
};
}

View File

@ -0,0 +1,56 @@
#include <id/UUID.h>
namespace SE {
static_assert(sizeof(UUID) == 16, "UUID has incorrect size");
/**
* Verify that a string has the correct format;
* XXXXXXXX-XXXX-XXX-XXXXX-XXXXXXXXXXXX
*
* The length must be 36.
* There must be dashes at index 8, 13, 18 and 23.
* @param str the input string
* @return whether the UUID string is correctly formed
*/
bool UUID::IsValidStr(const char *str) {
size_t const len = strlen(str);
if (len != 36) return false;
for (size_t i = 0; i < len; i++) {
char c = str[i];
if (c == '-') {
if (i != 8 && i != 13 && i != 18 && i != 23) return false;
} else if (! std::isxdigit(c)) {
return false;
}
}
return true;
}
UUID::UUID(char const* str ) {
// A single byte is two hex characters.
// Store them here so that we can use them later.
char c0 = '\0', c1;
size_t const len = strlen( str );
uint32_t byteIdx = 0;
for (size_t i = 0; i < len; i++ ) {
char const c = str[i];
if ( c == '-' )
continue;
// Scan for pairs of characters.
// Only assign a byte if two have been parsed.
if (c0 == '\0') {
c0 = c;
} else {
c1 = c;
data.u8[byteIdx++] = std::stoi(std::string(c0, c1));
// Reset the first char so that we can return to scanning a pair.
c0 = '\0';
}
}
}
}

View File

@ -0,0 +1,60 @@
#pragma once
#include <id/UUID.h> // Shadow-Engine/core/inc/id
namespace SE {
// An ID for a section of the scene (which may be unloaded separately of the level; for ie. open world Cells.)
using EntitySectionID = UUID;
// An ID for a scene (which contains all sections and entities).
using EntitySceneID = UUID;
/**
* Contains the common data and functions for the Entity System's identifiers.
*/
struct IDContainer {
public:
IDContainer() = default;
explicit IDContainer(uint64_t v) : id(v) {}
// Check if the ID is valid (non-zero)
__inline bool Valid() const { return id != 0; }
// Set this ID to be invalid (zero).
__inline void Invalidate() { id = 0; }
// Check for in/equality against another ID.
__inline bool operator==(IDContainer const& other) const { return id == other.id; }
__inline bool operator!=(IDContainer const& other) const { return id != other.id; }
uint64_t id;
};
/**
* An ID used for an Entity.
* Is only guaranteed to be unique in the current scene (ie. a level change may also change the IDs of the entities within).
*/
struct EntityID : public IDContainer {
/**
* @return a new, unused Entity ID.
*/
static EntityID Generate();
EntityID() = default;
explicit EntityID(uint64_t v) : IDContainer(v) {}
};
/**
* An ID used for a Component (a segment of data attached to an Entity).
* Is only guaranteed to be unique in the current scene (ie. a level change may also change the IDs of the components within).
*/
struct ComponentID : public IDContainer {
/**
* @return a new, unused Component ID.
*/
static ComponentID Generate();
ComponentID() = default;
explicit ComponentID(uint64_t v) : IDContainer(v) {}
};
}

View File

@ -0,0 +1,16 @@
#include <id/ID.h>
#include <atomic>
namespace SE {
static std::atomic<uint64_t> entityID = 1;
EntityID EntityID::Generate() {
EntityID id(entityID++);
return id;
}
static std::atomic<uint64_t> componentID = 1;
ComponentID ComponentID::Generate() {
ComponentID id(componentID++);
return id;
}
}