added basic structures
This commit is contained in:
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/clang++",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20",
|
||||
"intelliSenseMode": "clang-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
967
TSE_Base/include/uuid.h
Normal file
967
TSE_Base/include/uuid.h
Normal file
@@ -0,0 +1,967 @@
|
||||
#ifndef STDUUID_H
|
||||
#define STDUUID_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
#include <random>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <numeric>
|
||||
#include <atomic>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
# define LIBUUID_CPP20_OR_GREATER
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LIBUUID_CPP20_OR_GREATER
|
||||
#include <span>
|
||||
#else
|
||||
#include <gsl/span>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <objbase.h>
|
||||
#endif
|
||||
|
||||
#ifdef UUID_TIME_GENERATOR
|
||||
#include <iphlpapi.h>
|
||||
#pragma comment(lib, "IPHLPAPI.lib")
|
||||
#endif
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <CoreFoundation/CFUUID.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace uuids
|
||||
{
|
||||
#ifdef __cpp_lib_span
|
||||
template <class ElementType, std::size_t Extent>
|
||||
using span = std::span<ElementType, Extent>;
|
||||
#else
|
||||
template <class ElementType, std::ptrdiff_t Extent>
|
||||
using span = gsl::span<ElementType, Extent>;
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept
|
||||
{
|
||||
if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
|
||||
return static_cast<unsigned char>(ch - static_cast<TChar>('0'));
|
||||
if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
|
||||
return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a'));
|
||||
if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
|
||||
return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A'));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept
|
||||
{
|
||||
return
|
||||
(ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
|
||||
(ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
|
||||
(ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr std::basic_string_view<TChar> to_string_view(TChar const * str) noexcept
|
||||
{
|
||||
if (str) return str;
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]]
|
||||
constexpr std::basic_string_view<
|
||||
typename StringType::value_type,
|
||||
typename StringType::traits_type>
|
||||
to_string_view(StringType const & str) noexcept
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
class sha1
|
||||
{
|
||||
public:
|
||||
using digest32_t = uint32_t[5];
|
||||
using digest8_t = uint8_t[20];
|
||||
|
||||
static constexpr unsigned int block_bytes = 64;
|
||||
|
||||
[[nodiscard]] inline static uint32_t left_rotate(uint32_t value, size_t const count) noexcept
|
||||
{
|
||||
return (value << count) ^ (value >> (32 - count));
|
||||
}
|
||||
|
||||
sha1() { reset(); }
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
m_digest[0] = 0x67452301;
|
||||
m_digest[1] = 0xEFCDAB89;
|
||||
m_digest[2] = 0x98BADCFE;
|
||||
m_digest[3] = 0x10325476;
|
||||
m_digest[4] = 0xC3D2E1F0;
|
||||
m_blockByteIndex = 0;
|
||||
m_byteCount = 0;
|
||||
}
|
||||
|
||||
void process_byte(uint8_t octet)
|
||||
{
|
||||
this->m_block[this->m_blockByteIndex++] = octet;
|
||||
++this->m_byteCount;
|
||||
if (m_blockByteIndex == block_bytes)
|
||||
{
|
||||
this->m_blockByteIndex = 0;
|
||||
process_block();
|
||||
}
|
||||
}
|
||||
|
||||
void process_block(void const * const start, void const * const end)
|
||||
{
|
||||
const uint8_t* begin = static_cast<const uint8_t*>(start);
|
||||
const uint8_t* finish = static_cast<const uint8_t*>(end);
|
||||
while (begin != finish)
|
||||
{
|
||||
process_byte(*begin);
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
void process_bytes(void const * const data, size_t const len)
|
||||
{
|
||||
const uint8_t* block = static_cast<const uint8_t*>(data);
|
||||
process_block(block, block + len);
|
||||
}
|
||||
|
||||
uint32_t const * get_digest(digest32_t digest)
|
||||
{
|
||||
size_t const bitCount = this->m_byteCount * 8;
|
||||
process_byte(0x80);
|
||||
if (this->m_blockByteIndex > 56) {
|
||||
while (m_blockByteIndex != 0) {
|
||||
process_byte(0);
|
||||
}
|
||||
while (m_blockByteIndex < 56) {
|
||||
process_byte(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (m_blockByteIndex < 56) {
|
||||
process_byte(0);
|
||||
}
|
||||
}
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount) & 0xFF));
|
||||
|
||||
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
||||
return digest;
|
||||
}
|
||||
|
||||
uint8_t const * get_digest_bytes(digest8_t digest)
|
||||
{
|
||||
digest32_t d32;
|
||||
get_digest(d32);
|
||||
size_t di = 0;
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 0);
|
||||
|
||||
return digest;
|
||||
}
|
||||
|
||||
private:
|
||||
void process_block()
|
||||
{
|
||||
uint32_t w[80];
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]);
|
||||
}
|
||||
for (size_t i = 16; i < 80; i++) {
|
||||
w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
|
||||
}
|
||||
|
||||
uint32_t a = m_digest[0];
|
||||
uint32_t b = m_digest[1];
|
||||
uint32_t c = m_digest[2];
|
||||
uint32_t d = m_digest[3];
|
||||
uint32_t e = m_digest[4];
|
||||
|
||||
for (std::size_t i = 0; i < 80; ++i)
|
||||
{
|
||||
uint32_t f = 0;
|
||||
uint32_t k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
f = (b & c) | (~b & d);
|
||||
k = 0x5A827999;
|
||||
}
|
||||
else if (i < 40) {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
}
|
||||
else if (i < 60) {
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
}
|
||||
else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
uint32_t temp = left_rotate(a, 5) + f + e + k + w[i];
|
||||
e = d;
|
||||
d = c;
|
||||
c = left_rotate(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
m_digest[0] += a;
|
||||
m_digest[1] += b;
|
||||
m_digest[2] += c;
|
||||
m_digest[3] += d;
|
||||
m_digest[4] += e;
|
||||
}
|
||||
|
||||
private:
|
||||
digest32_t m_digest;
|
||||
uint8_t m_block[64];
|
||||
size_t m_blockByteIndex;
|
||||
size_t m_byteCount;
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
template <>
|
||||
inline constexpr wchar_t empty_guid<wchar_t>[37] = L"00000000-0000-0000-0000-000000000000";
|
||||
|
||||
template <typename CharT>
|
||||
inline constexpr CharT guid_encoder[17] = "0123456789abcdef";
|
||||
|
||||
template <>
|
||||
inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef";
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// UUID format https://tools.ietf.org/html/rfc4122
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// Field NDR Data Type Octet # Note
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// time_low unsigned long 0 - 3 The low field of the timestamp.
|
||||
// time_mid unsigned short 4 - 5 The middle field of the timestamp.
|
||||
// time_hi_and_version unsigned short 6 - 7 The high field of the timestamp multiplexed with the version number.
|
||||
// clock_seq_hi_and_reserved unsigned small 8 The high field of the clock sequence multiplexed with the variant.
|
||||
// clock_seq_low unsigned small 9 The low field of the clock sequence.
|
||||
// node character 10 - 15 The spatially unique node identifier.
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | time_low |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | time_mid | time_hi_and_version |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |clk_seq_hi_res | clk_seq_low | node (0-1) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | node (2-5) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// enumerations
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// indicated by a bit pattern in octet 8, marked with N in xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx
|
||||
enum class uuid_variant
|
||||
{
|
||||
// NCS backward compatibility (with the obsolete Apollo Network Computing System 1.5 UUID format)
|
||||
// N bit pattern: 0xxx
|
||||
// > the first 6 octets of the UUID are a 48-bit timestamp (the number of 4 microsecond units of time since 1 Jan 1980 UTC);
|
||||
// > the next 2 octets are reserved;
|
||||
// > the next octet is the "address family";
|
||||
// > the final 7 octets are a 56-bit host ID in the form specified by the address family
|
||||
ncs,
|
||||
|
||||
// RFC 4122/DCE 1.1
|
||||
// N bit pattern: 10xx
|
||||
// > big-endian byte order
|
||||
rfc,
|
||||
|
||||
// Microsoft Corporation backward compatibility
|
||||
// N bit pattern: 110x
|
||||
// > little endian byte order
|
||||
// > formely used in the Component Object Model (COM) library
|
||||
microsoft,
|
||||
|
||||
// reserved for possible future definition
|
||||
// N bit pattern: 111x
|
||||
reserved
|
||||
};
|
||||
|
||||
// indicated by a bit pattern in octet 6, marked with M in xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
|
||||
enum class uuid_version
|
||||
{
|
||||
none = 0, // only possible for nil or invalid uuids
|
||||
time_based = 1, // The time-based version specified in RFC 4122
|
||||
dce_security = 2, // DCE Security version, with embedded POSIX UIDs.
|
||||
name_based_md5 = 3, // The name-based version specified in RFS 4122 with MD5 hashing
|
||||
random_number_based = 4, // The randomly or pseudo-randomly generated version specified in RFS 4122
|
||||
name_based_sha1 = 5 // The name-based version specified in RFS 4122 with SHA1 hashing
|
||||
};
|
||||
|
||||
// Forward declare uuid & to_string so that we can declare to_string as a friend later.
|
||||
class uuid;
|
||||
template <class CharT = char,
|
||||
class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>>
|
||||
std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id);
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// uuid class
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
class uuid
|
||||
{
|
||||
public:
|
||||
using value_type = uint8_t;
|
||||
|
||||
constexpr uuid() noexcept = default;
|
||||
|
||||
uuid(value_type(&arr)[16]) noexcept
|
||||
{
|
||||
std::copy(std::cbegin(arr), std::cend(arr), std::begin(data));
|
||||
}
|
||||
|
||||
constexpr uuid(std::array<value_type, 16> const & arr) noexcept : data{arr} {}
|
||||
|
||||
explicit uuid(span<value_type, 16> bytes)
|
||||
{
|
||||
std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data));
|
||||
}
|
||||
|
||||
template<typename ForwardIterator>
|
||||
explicit uuid(ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
if (std::distance(first, last) == 16)
|
||||
std::copy(first, last, std::begin(data));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr uuid_variant variant() const noexcept
|
||||
{
|
||||
if ((data[8] & 0x80) == 0x00)
|
||||
return uuid_variant::ncs;
|
||||
else if ((data[8] & 0xC0) == 0x80)
|
||||
return uuid_variant::rfc;
|
||||
else if ((data[8] & 0xE0) == 0xC0)
|
||||
return uuid_variant::microsoft;
|
||||
else
|
||||
return uuid_variant::reserved;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr uuid_version version() const noexcept
|
||||
{
|
||||
if ((data[6] & 0xF0) == 0x10)
|
||||
return uuid_version::time_based;
|
||||
else if ((data[6] & 0xF0) == 0x20)
|
||||
return uuid_version::dce_security;
|
||||
else if ((data[6] & 0xF0) == 0x30)
|
||||
return uuid_version::name_based_md5;
|
||||
else if ((data[6] & 0xF0) == 0x40)
|
||||
return uuid_version::random_number_based;
|
||||
else if ((data[6] & 0xF0) == 0x50)
|
||||
return uuid_version::name_based_sha1;
|
||||
else
|
||||
return uuid_version::none;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_nil() const noexcept
|
||||
{
|
||||
for (size_t i = 0; i < data.size(); ++i) if (data[i] != 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void swap(uuid & other) noexcept
|
||||
{
|
||||
data.swap(other.data);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline span<std::byte const, 16> as_bytes() const
|
||||
{
|
||||
return span<std::byte const, 16>(reinterpret_cast<std::byte const*>(data.data()), 16);
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] constexpr static bool is_valid_uuid(StringType const & in_str) noexcept
|
||||
{
|
||||
auto str = detail::to_string_view(in_str);
|
||||
bool firstDigit = true;
|
||||
size_t hasBraces = 0;
|
||||
size_t index = 0;
|
||||
|
||||
if (str.empty())
|
||||
return false;
|
||||
|
||||
if (str.front() == '{')
|
||||
hasBraces = 1;
|
||||
if (hasBraces && str.back() != '}')
|
||||
return false;
|
||||
|
||||
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
|
||||
{
|
||||
if (str[i] == '-') continue;
|
||||
|
||||
if (index >= 16 || !detail::is_hex(str[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (firstDigit)
|
||||
{
|
||||
firstDigit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
index++;
|
||||
firstDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 16)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] constexpr static std::optional<uuid> from_string(StringType const & in_str) noexcept
|
||||
{
|
||||
auto str = detail::to_string_view(in_str);
|
||||
bool firstDigit = true;
|
||||
size_t hasBraces = 0;
|
||||
size_t index = 0;
|
||||
|
||||
std::array<uint8_t, 16> data{ { 0 } };
|
||||
|
||||
if (str.empty()) return {};
|
||||
|
||||
if (str.front() == '{')
|
||||
hasBraces = 1;
|
||||
if (hasBraces && str.back() != '}')
|
||||
return {};
|
||||
|
||||
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
|
||||
{
|
||||
if (str[i] == '-') continue;
|
||||
|
||||
if (index >= 16 || !detail::is_hex(str[i]))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (firstDigit)
|
||||
{
|
||||
data[index] = static_cast<uint8_t>(detail::hex2char(str[i]) << 4);
|
||||
firstDigit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
data[index] = static_cast<uint8_t>(data[index] | detail::hex2char(str[i]));
|
||||
index++;
|
||||
firstDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 16)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return uuid{ data };
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<value_type, 16> data{ { 0 } };
|
||||
|
||||
friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept;
|
||||
friend bool operator<(uuid const & lhs, uuid const & rhs) noexcept;
|
||||
|
||||
template <class Elem, class Traits>
|
||||
friend std::basic_ostream<Elem, Traits> & operator<<(std::basic_ostream<Elem, Traits> &s, uuid const & id);
|
||||
|
||||
template<class CharT, class Traits, class Allocator>
|
||||
friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id);
|
||||
|
||||
friend std::hash<uuid>;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// operators and non-member functions
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
[[nodiscard]] inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept
|
||||
{
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator!= (uuid const& lhs, uuid const& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator< (uuid const& lhs, uuid const& rhs) noexcept
|
||||
{
|
||||
return lhs.data < rhs.data;
|
||||
}
|
||||
|
||||
template <class CharT,
|
||||
class Traits,
|
||||
class Allocator>
|
||||
[[nodiscard]] inline std::basic_string<CharT, Traits, Allocator> to_string(uuid const & id)
|
||||
{
|
||||
std::basic_string<CharT, Traits, Allocator> uustr{detail::empty_guid<CharT>};
|
||||
|
||||
for (size_t i = 0, index = 0; i < 36; ++i)
|
||||
{
|
||||
if (i == 8 || i == 13 || i == 18 || i == 23)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uustr[i] = detail::guid_encoder<CharT>[id.data[index] >> 4 & 0x0f];
|
||||
uustr[++i] = detail::guid_encoder<CharT>[id.data[index] & 0x0f];
|
||||
index++;
|
||||
}
|
||||
|
||||
return uustr;
|
||||
}
|
||||
|
||||
template <class Elem, class Traits>
|
||||
std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& s, uuid const& id)
|
||||
{
|
||||
s << to_string(id);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline void swap(uuids::uuid & lhs, uuids::uuid & rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// namespace IDs that could be used for generating name-based uuids
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Name string is a fully-qualified domain name
|
||||
static uuid uuid_namespace_dns{ {0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
|
||||
|
||||
// Name string is a URL
|
||||
static uuid uuid_namespace_url{ {0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
|
||||
|
||||
// Name string is an ISO OID (See https://oidref.com/, https://en.wikipedia.org/wiki/Object_identifier)
|
||||
static uuid uuid_namespace_oid{ {0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
|
||||
|
||||
// Name string is an X.500 DN, in DER or a text output format (See https://en.wikipedia.org/wiki/X.500, https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
|
||||
static uuid uuid_namespace_x500{ {0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} };
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// uuid generators
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
class uuid_system_generator
|
||||
{
|
||||
public:
|
||||
using result_type = uuid;
|
||||
|
||||
uuid operator()()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
GUID newId;
|
||||
HRESULT hr = ::CoCreateGuid(&newId);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
throw std::system_error(hr, std::system_category(), "CoCreateGuid failed");
|
||||
}
|
||||
|
||||
std::array<uint8_t, 16> bytes =
|
||||
{ {
|
||||
static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1) & 0xFF),
|
||||
|
||||
(unsigned char)((newId.Data2 >> 8) & 0xFF),
|
||||
(unsigned char)((newId.Data2) & 0xFF),
|
||||
|
||||
(unsigned char)((newId.Data3 >> 8) & 0xFF),
|
||||
(unsigned char)((newId.Data3) & 0xFF),
|
||||
|
||||
newId.Data4[0],
|
||||
newId.Data4[1],
|
||||
newId.Data4[2],
|
||||
newId.Data4[3],
|
||||
newId.Data4[4],
|
||||
newId.Data4[5],
|
||||
newId.Data4[6],
|
||||
newId.Data4[7]
|
||||
} };
|
||||
|
||||
return uuid{ std::begin(bytes), std::end(bytes) };
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
|
||||
uuid_t id;
|
||||
uuid_generate(id);
|
||||
|
||||
std::array<uint8_t, 16> bytes =
|
||||
{ {
|
||||
id[0],
|
||||
id[1],
|
||||
id[2],
|
||||
id[3],
|
||||
id[4],
|
||||
id[5],
|
||||
id[6],
|
||||
id[7],
|
||||
id[8],
|
||||
id[9],
|
||||
id[10],
|
||||
id[11],
|
||||
id[12],
|
||||
id[13],
|
||||
id[14],
|
||||
id[15]
|
||||
} };
|
||||
|
||||
return uuid{ std::begin(bytes), std::end(bytes) };
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
auto newId = CFUUIDCreate(NULL);
|
||||
auto bytes = CFUUIDGetUUIDBytes(newId);
|
||||
CFRelease(newId);
|
||||
|
||||
std::array<uint8_t, 16> arrbytes =
|
||||
{ {
|
||||
bytes.byte0,
|
||||
bytes.byte1,
|
||||
bytes.byte2,
|
||||
bytes.byte3,
|
||||
bytes.byte4,
|
||||
bytes.byte5,
|
||||
bytes.byte6,
|
||||
bytes.byte7,
|
||||
bytes.byte8,
|
||||
bytes.byte9,
|
||||
bytes.byte10,
|
||||
bytes.byte11,
|
||||
bytes.byte12,
|
||||
bytes.byte13,
|
||||
bytes.byte14,
|
||||
bytes.byte15
|
||||
} };
|
||||
return uuid{ std::begin(arrbytes), std::end(arrbytes) };
|
||||
#else
|
||||
return uuid{};
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename UniformRandomNumberGenerator>
|
||||
class basic_uuid_random_generator
|
||||
{
|
||||
public:
|
||||
using engine_type = UniformRandomNumberGenerator;
|
||||
|
||||
explicit basic_uuid_random_generator(engine_type& gen) :
|
||||
generator(&gen, [](auto) {}) {}
|
||||
explicit basic_uuid_random_generator(engine_type* gen) :
|
||||
generator(gen, [](auto) {}) {}
|
||||
|
||||
[[nodiscard]] uuid operator()()
|
||||
{
|
||||
alignas(uint32_t) uint8_t bytes[16];
|
||||
for (int i = 0; i < 16; i += 4)
|
||||
*reinterpret_cast<uint32_t*>(bytes + i) = distribution(*generator);
|
||||
|
||||
// variant must be 10xxxxxx
|
||||
bytes[8] &= 0xBF;
|
||||
bytes[8] |= 0x80;
|
||||
|
||||
// version must be 0100xxxx
|
||||
bytes[6] &= 0x4F;
|
||||
bytes[6] |= 0x40;
|
||||
|
||||
return uuid{std::begin(bytes), std::end(bytes)};
|
||||
}
|
||||
|
||||
private:
|
||||
std::uniform_int_distribution<uint32_t> distribution;
|
||||
std::shared_ptr<UniformRandomNumberGenerator> generator;
|
||||
};
|
||||
|
||||
using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
|
||||
|
||||
class uuid_name_generator
|
||||
{
|
||||
public:
|
||||
explicit uuid_name_generator(uuid const& namespace_uuid) noexcept
|
||||
: nsuuid(namespace_uuid)
|
||||
{}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] uuid operator()(StringType const & name)
|
||||
{
|
||||
reset();
|
||||
process_characters(detail::to_string_view(name));
|
||||
return make_uuid();
|
||||
}
|
||||
|
||||
private:
|
||||
void reset()
|
||||
{
|
||||
hasher.reset();
|
||||
std::byte bytes[16];
|
||||
auto nsbytes = nsuuid.as_bytes();
|
||||
std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes);
|
||||
hasher.process_bytes(bytes, 16);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
void process_characters(std::basic_string_view<CharT, Traits> const str)
|
||||
{
|
||||
for (uint32_t c : str)
|
||||
{
|
||||
hasher.process_byte(static_cast<uint8_t>(c & 0xFF));
|
||||
if constexpr (!std::is_same_v<CharT, char>)
|
||||
{
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 8) & 0xFF));
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 16) & 0xFF));
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 24) & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] uuid make_uuid()
|
||||
{
|
||||
detail::sha1::digest8_t digest;
|
||||
hasher.get_digest_bytes(digest);
|
||||
|
||||
// variant must be 0b10xxxxxx
|
||||
digest[8] &= 0xBF;
|
||||
digest[8] |= 0x80;
|
||||
|
||||
// version must be 0b0101xxxx
|
||||
digest[6] &= 0x5F;
|
||||
digest[6] |= 0x50;
|
||||
|
||||
return uuid{ digest, digest + 16 };
|
||||
}
|
||||
|
||||
private:
|
||||
uuid nsuuid;
|
||||
detail::sha1 hasher;
|
||||
};
|
||||
|
||||
#ifdef UUID_TIME_GENERATOR
|
||||
// !!! DO NOT USE THIS IN PRODUCTION
|
||||
// this implementation is unreliable for good uuids
|
||||
class uuid_time_generator
|
||||
{
|
||||
using mac_address = std::array<unsigned char, 6>;
|
||||
|
||||
std::optional<mac_address> device_address;
|
||||
|
||||
[[nodiscard]] bool get_mac_address()
|
||||
{
|
||||
if (device_address.has_value())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD len = 0;
|
||||
auto ret = GetAdaptersInfo(nullptr, &len);
|
||||
if (ret != ERROR_BUFFER_OVERFLOW) return false;
|
||||
std::vector<unsigned char> buf(len);
|
||||
auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front());
|
||||
ret = GetAdaptersInfo(pips, &len);
|
||||
if (ret != ERROR_SUCCESS) return false;
|
||||
mac_address addr;
|
||||
std::copy(pips->Address, pips->Address + 6, std::begin(addr));
|
||||
device_address = addr;
|
||||
#endif
|
||||
|
||||
return device_address.has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] long long get_time_intervals()
|
||||
{
|
||||
auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800));
|
||||
auto diff = std::chrono::system_clock::now() - start;
|
||||
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count();
|
||||
return ns / 100;
|
||||
}
|
||||
|
||||
[[nodiscard]] static unsigned short get_clock_sequence()
|
||||
{
|
||||
static std::mt19937 clock_gen(std::random_device{}());
|
||||
static std::uniform_int_distribution<unsigned short> clock_dis;
|
||||
static std::atomic_ushort clock_sequence = clock_dis(clock_gen);
|
||||
return clock_sequence++;
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] uuid operator()()
|
||||
{
|
||||
if (get_mac_address())
|
||||
{
|
||||
std::array<uuids::uuid::value_type, 16> data;
|
||||
|
||||
auto tm = get_time_intervals();
|
||||
|
||||
auto clock_seq = get_clock_sequence();
|
||||
|
||||
auto ptm = reinterpret_cast<uuids::uuid::value_type*>(&tm);
|
||||
|
||||
memcpy(&data[0], ptm + 4, 4);
|
||||
memcpy(&data[4], ptm + 2, 2);
|
||||
memcpy(&data[6], ptm, 2);
|
||||
|
||||
memcpy(&data[8], &clock_seq, 2);
|
||||
|
||||
// variant must be 0b10xxxxxx
|
||||
data[8] &= 0xBF;
|
||||
data[8] |= 0x80;
|
||||
|
||||
// version must be 0b0001xxxx
|
||||
data[6] &= 0x1F;
|
||||
data[6] |= 0x10;
|
||||
|
||||
memcpy(&data[10], &device_address.value()[0], 6);
|
||||
|
||||
return uuids::uuid{std::cbegin(data), std::cend(data)};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<uuids::uuid>
|
||||
{
|
||||
using argument_type = uuids::uuid;
|
||||
using result_type = std::size_t;
|
||||
|
||||
[[nodiscard]] result_type operator()(argument_type const &uuid) const
|
||||
{
|
||||
#ifdef UUID_HASH_STRING_BASED
|
||||
std::hash<std::string> hasher;
|
||||
return static_cast<result_type>(hasher(uuids::to_string(uuid)));
|
||||
#else
|
||||
uint64_t l =
|
||||
static_cast<uint64_t>(uuid.data[0]) << 56 |
|
||||
static_cast<uint64_t>(uuid.data[1]) << 48 |
|
||||
static_cast<uint64_t>(uuid.data[2]) << 40 |
|
||||
static_cast<uint64_t>(uuid.data[3]) << 32 |
|
||||
static_cast<uint64_t>(uuid.data[4]) << 24 |
|
||||
static_cast<uint64_t>(uuid.data[5]) << 16 |
|
||||
static_cast<uint64_t>(uuid.data[6]) << 8 |
|
||||
static_cast<uint64_t>(uuid.data[7]);
|
||||
uint64_t h =
|
||||
static_cast<uint64_t>(uuid.data[8]) << 56 |
|
||||
static_cast<uint64_t>(uuid.data[9]) << 48 |
|
||||
static_cast<uint64_t>(uuid.data[10]) << 40 |
|
||||
static_cast<uint64_t>(uuid.data[11]) << 32 |
|
||||
static_cast<uint64_t>(uuid.data[12]) << 24 |
|
||||
static_cast<uint64_t>(uuid.data[13]) << 16 |
|
||||
static_cast<uint64_t>(uuid.data[14]) << 8 |
|
||||
static_cast<uint64_t>(uuid.data[15]);
|
||||
|
||||
if constexpr (sizeof(result_type) > 4)
|
||||
{
|
||||
return result_type(l ^ h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t hash64 = l ^ h;
|
||||
return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* STDUUID_H */
|
||||
9
TSE_Base/src/IdGenerator.cpp
Normal file
9
TSE_Base/src/IdGenerator.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "IdGenerator.hpp"
|
||||
|
||||
std::mt19937 rnd = std::mt19937();
|
||||
auto gen = uuids::uuid_random_generator(rnd);
|
||||
|
||||
uuids::uuid TSE::GenerateRandomUUID()
|
||||
{
|
||||
return gen();
|
||||
}
|
||||
8
TSE_Base/src/IdGenerator.hpp
Normal file
8
TSE_Base/src/IdGenerator.hpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "uuid.h"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
uuids::uuid GenerateRandomUUID();
|
||||
} // namespace TSE
|
||||
16
TSE_Core/src/BehaviourScripts/MeshContainer.cpp
Normal file
16
TSE_Core/src/BehaviourScripts/MeshContainer.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "MeshContainer.hpp"
|
||||
|
||||
TSE::MeshContainer::MeshContainer() = default;
|
||||
|
||||
TSE::MeshContainer::MeshContainer(Mesh *m)
|
||||
: mesh(m) {}
|
||||
|
||||
void TSE::MeshContainer::SetMesh(Mesh *m)
|
||||
{
|
||||
mesh = m;
|
||||
}
|
||||
|
||||
TSE::Mesh *TSE::MeshContainer::GetMesh() const
|
||||
{
|
||||
return mesh;
|
||||
}
|
||||
28
TSE_Core/src/BehaviourScripts/MeshContainer.hpp
Normal file
28
TSE_Core/src/BehaviourScripts/MeshContainer.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#define MESH_CONTAINER typeid(TSE::MeshContainer).name()
|
||||
|
||||
#include "Types.hpp"
|
||||
#include "Mesh.hpp"
|
||||
#include "elements/BehaviourScript.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class MeshContainer : public BehaviourScript
|
||||
{
|
||||
private:
|
||||
Mesh* mesh = nullptr;
|
||||
|
||||
public:
|
||||
MeshContainer();
|
||||
explicit MeshContainer(Mesh* mesh);
|
||||
|
||||
void SetMesh(Mesh* mesh);
|
||||
Mesh* GetMesh() const;
|
||||
|
||||
inline const char* GetName() override
|
||||
{
|
||||
return "Mesh Container";
|
||||
};
|
||||
};
|
||||
} // namespace TSE
|
||||
92
TSE_Core/src/BehaviourScripts/RectBase.cpp
Normal file
92
TSE_Core/src/BehaviourScripts/RectBase.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "RectBase.hpp"
|
||||
|
||||
#include "elements/Transformable.hpp"
|
||||
|
||||
TSE::RectBase::RectBase()
|
||||
{
|
||||
meshCach = Mesh::GetQuadMesh();
|
||||
}
|
||||
|
||||
TSE::Mesh *TSE::RectBase::GetMesh()
|
||||
{
|
||||
return &meshCach;
|
||||
}
|
||||
|
||||
void TSE::RectBase::SetCustomUVs(const std::vector<Vector2> &uvs)
|
||||
{
|
||||
meshCach.uvs = uvs;
|
||||
}
|
||||
|
||||
void TSE::RectBase::OnParentChanged(RectBase *parent)
|
||||
{
|
||||
if(anchors != Rect(0.5f,0.5f, 0.5f, 0.5f))
|
||||
RecalculateMesh(parent);
|
||||
}
|
||||
|
||||
bool IsTransformableRect(TSE::Transformable* trans)
|
||||
{
|
||||
if(trans == nullptr || !trans->HasBehaviourScript(RECT_BASE)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TSE::RectBase::RecalculateMesh(RectBase *parent)
|
||||
{
|
||||
// Determin parent size, or fallback to 1x1
|
||||
Vector2 psize (1,1);
|
||||
if(parent != nullptr)
|
||||
psize = parent->tmpSize;
|
||||
Vector2 phsize = psize * 0.5f;
|
||||
|
||||
|
||||
Vector2 pposoffset (0,0);
|
||||
if(parent != nullptr)
|
||||
{
|
||||
pposoffset = ((parent->pivit * 2) - Vector2::one) * phsize;
|
||||
}
|
||||
|
||||
Vector2 mappedAnchor = (Vector2::Midpoint(anchors.p1,anchors.p2) * 2 - Vector2::one) * phsize;
|
||||
pposoffset = pposoffset + mappedAnchor;
|
||||
|
||||
Vector2 strechscaler = anchors.p2 - anchors.p1;
|
||||
|
||||
tmpSize = psize * strechscaler + size;
|
||||
|
||||
Vector2 hs = tmpSize * 0.5f;
|
||||
|
||||
Vector2 mappedPivit = pivit * 2 - Vector2::one;
|
||||
Vector2 pivitOffset = hs * mappedPivit;
|
||||
|
||||
meshCach.vertecies.clear();
|
||||
meshCach.vertecies.push_back(Vector2(-hs.x, -hs.y) + pivitOffset);
|
||||
meshCach.vertecies.push_back(Vector2( hs.x, -hs.y) + pivitOffset);
|
||||
meshCach.vertecies.push_back(Vector2( hs.x, hs.y) + pivitOffset);
|
||||
meshCach.vertecies.push_back(Vector2(-hs.x, hs.y) + pivitOffset);
|
||||
|
||||
|
||||
baseObject->position = pposoffset;
|
||||
|
||||
lastSize = size;
|
||||
lastAnchors = anchors;
|
||||
lastPivit = pivit;
|
||||
|
||||
// Notify children of change
|
||||
auto children = baseObject->GetChildren();
|
||||
for(auto child : children)
|
||||
{
|
||||
if(IsTransformableRect(child))
|
||||
{
|
||||
((RectBase*)child->GetBehaviourScript(RECT_BASE))->OnParentChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSE::RectBase::OnUpdate()
|
||||
{
|
||||
if(lastSize != size || lastAnchors != anchors || pivit != lastPivit){
|
||||
//local change
|
||||
RectBase* parent = nullptr;
|
||||
if(baseObject->GetParent() != nullptr)
|
||||
parent = (RectBase*)baseObject->GetParent()->GetBehaviourScript(RECT_BASE);
|
||||
RecalculateMesh(parent);
|
||||
}
|
||||
}
|
||||
42
TSE_Core/src/BehaviourScripts/RectBase.hpp
Normal file
42
TSE_Core/src/BehaviourScripts/RectBase.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#define RECT_BASE typeid(TSE::RectBase).name()
|
||||
|
||||
#include "elements/BehaviourScript.hpp"
|
||||
#include "Rect.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include "Mesh.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class RectBase : public BehaviourScript
|
||||
{
|
||||
private:
|
||||
Rect lastAnchors = Rect(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
Vector2 lastSize = Vector2(0,0);
|
||||
Vector2 lastPivit = Vector2(0.5f,0.5f);
|
||||
Mesh meshCach;
|
||||
|
||||
Vector2 tmpSize;
|
||||
|
||||
public:
|
||||
Rect anchors = Rect(0.5f,0.5f, 0.5f, 0.5f); //streching in parent
|
||||
Vector2 size = Vector2(1,1); //size
|
||||
Vector2 pivit = Vector2(0.5f,0.5f); //positioning in parent
|
||||
|
||||
RectBase();
|
||||
Mesh* GetMesh();
|
||||
void SetCustomUVs(const std::vector<Vector2>& uvs);
|
||||
|
||||
private:
|
||||
void OnParentChanged(RectBase* parent);
|
||||
void RecalculateMesh(RectBase *parent);
|
||||
|
||||
public:
|
||||
void OnUpdate() override;
|
||||
inline const char* GetName() override
|
||||
{
|
||||
return "Rect Base";
|
||||
}
|
||||
};
|
||||
} // namespace TSE
|
||||
42
TSE_Core/src/BehaviourScripts/Renderable.cpp
Normal file
42
TSE_Core/src/BehaviourScripts/Renderable.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "Renderable.hpp"
|
||||
|
||||
#include <typeinfo>
|
||||
#include "MeshContainer.hpp"
|
||||
#include "elements/Transformable.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
Renderable::Renderable() = default;
|
||||
|
||||
Renderable::Renderable(Material* mat)
|
||||
{
|
||||
SetMaterial(mat);
|
||||
}
|
||||
|
||||
void Renderable::SetMaterial(Material* mat) {
|
||||
material = mat;
|
||||
}
|
||||
|
||||
Material* Renderable::GetMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
Mesh* Renderable::GetMeshContainer() const {
|
||||
if(baseObject->HasBehaviourScript(MESH_CONTAINER))
|
||||
return dynamic_cast<MeshContainer*>(baseObject->GetBehaviourScript(MESH_CONTAINER))->GetMesh();
|
||||
// if(baseObject->HasBehaviourScript(RECT_BASE))
|
||||
// return dynamic_cast<RectBase*>(baseObject->GetBehaviourScript(RECT_BASE))->GetMesh();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Vector3* Renderable::GetVertices() const {
|
||||
auto* container = GetMeshContainer();
|
||||
return container ? container->vertecies.data() : nullptr;
|
||||
}
|
||||
|
||||
const Vector2* Renderable::GetUVs() const {
|
||||
auto* container = GetMeshContainer();
|
||||
return container ? container->uvs.data() : nullptr;
|
||||
}
|
||||
} // namespace TSE
|
||||
|
||||
35
TSE_Core/src/BehaviourScripts/Renderable.hpp
Normal file
35
TSE_Core/src/BehaviourScripts/Renderable.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#define RENDERABLE typeid(TSE::Renderable).name()
|
||||
|
||||
#include "elements/Material.hpp"
|
||||
#include "interfaces/IRenderable.hpp"
|
||||
#include "elements/BehaviourScript.hpp"
|
||||
#include "Mesh.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class Renderable : public BehaviourScript, public IRenderable
|
||||
{
|
||||
private:
|
||||
Material* material = nullptr;
|
||||
|
||||
public:
|
||||
Renderable();
|
||||
explicit Renderable(Material* material);
|
||||
|
||||
const Vector3* GetVertices() const override;
|
||||
const Vector2* GetUVs() const override;
|
||||
const std::vector<ushort> GetIndices() const override;
|
||||
size_t GetVertexCount() const override;
|
||||
inline const char* GetName() override
|
||||
{
|
||||
return "Renderable";
|
||||
}
|
||||
void SetMaterial(Material* material);
|
||||
Material* GetMaterial();
|
||||
|
||||
private:
|
||||
Mesh* GetMeshContainer() const;
|
||||
};
|
||||
} // namespace TSE
|
||||
23
TSE_Core/src/elements/BehaviourScript.cpp
Normal file
23
TSE_Core/src/elements/BehaviourScript.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "BehaviourScript.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
BehaviourScript::BehaviourScript()
|
||||
: baseObject(nullptr), enabled(true) {}
|
||||
|
||||
void BehaviourScript::SetEnabled(bool value) {
|
||||
enabled = value;
|
||||
}
|
||||
|
||||
bool BehaviourScript::IsEnabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void BehaviourScript::SetBaseObject(Transformable* obj) {
|
||||
baseObject = obj;
|
||||
}
|
||||
|
||||
Transformable* BehaviourScript::GetTransform() const {
|
||||
return baseObject;
|
||||
}
|
||||
} // namespace TSE
|
||||
29
TSE_Core/src/elements/BehaviourScript.hpp
Normal file
29
TSE_Core/src/elements/BehaviourScript.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class Transformable;
|
||||
|
||||
class BehaviourScript
|
||||
{
|
||||
public:
|
||||
BehaviourScript();
|
||||
virtual ~BehaviourScript() = default;
|
||||
|
||||
inline virtual void OnUpdate() { };
|
||||
inline virtual void OnEnable() { };
|
||||
inline virtual void OnDisable() { };
|
||||
inline virtual void Start() { };
|
||||
virtual const char* GetName() = 0;
|
||||
inline virtual void CustomDraw(const bool& debug) { };
|
||||
void SetEnabled(bool v);
|
||||
bool IsEnabled() const;
|
||||
|
||||
void SetBaseObject(Transformable* obj);
|
||||
Transformable* GetTransform() const;
|
||||
|
||||
Transformable* baseObject;
|
||||
protected:
|
||||
bool enabled = true;
|
||||
};
|
||||
} // namespace TSE
|
||||
96
TSE_Core/src/elements/Layer.cpp
Normal file
96
TSE_Core/src/elements/Layer.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "Layer.hpp"
|
||||
#include "BehaviourScripts/Renderable.hpp"
|
||||
#include "elements/BehaviourScript.hpp"
|
||||
|
||||
void HandleObject(TSE::Transformable* trans, TSE::TransformationStack& stack, TSE::IRenderer& rnd)
|
||||
{
|
||||
using namespace TSE;
|
||||
if(!trans->IsEnabled()) return;
|
||||
//OPTIMIZE this if statement
|
||||
if(trans->HasBehaviourScript(RENDERABLE) && trans->GetBehaviourScript(RENDERABLE)->IsEnabled() && ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial() != nullptr && ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial()->GetShader() != nullptr)
|
||||
{
|
||||
rnd.Submit(*trans, ((Renderable*)trans->GetBehaviourScript(RENDERABLE))->GetMaterial()->GetShader(), stack);
|
||||
}
|
||||
if(trans->GetChildren().size() > 0)
|
||||
{
|
||||
stack.Push(trans->GetLocalMatrix());
|
||||
for(auto child : trans->GetChildren())
|
||||
{
|
||||
HandleObject(child, stack, rnd);
|
||||
}
|
||||
stack.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
TSE::Layer::Layer(string &n)
|
||||
{
|
||||
name = n;
|
||||
}
|
||||
|
||||
void TSE::Layer::Render(IRenderer &rnd) const
|
||||
{
|
||||
TransformationStack stack;
|
||||
for(auto obj : objectsToRender)
|
||||
{
|
||||
HandleObject(obj, stack, rnd);
|
||||
}
|
||||
}
|
||||
|
||||
void TSE::Layer::AddTransformable(Transformable *t)
|
||||
{
|
||||
objectsToRender.push_back(t);
|
||||
}
|
||||
|
||||
bool TSE::Layer::HasTransformable(const Transformable *t) const
|
||||
{
|
||||
for(auto trans2 : objectsToRender)
|
||||
{
|
||||
if(t->id == trans2->id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TSE::Layer::RemoveTransformable(const Transformable *t)
|
||||
{
|
||||
RemoveTransformable(t->id);
|
||||
}
|
||||
|
||||
void TSE::Layer::RemoveTransformable(const uuids::uuid id)
|
||||
{
|
||||
auto it = objectsToRender.begin();
|
||||
for(auto trans : objectsToRender)
|
||||
{
|
||||
if(trans->id == id)
|
||||
{
|
||||
objectsToRender.erase(it);
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
TSE::string TSE::Layer::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void TSE::Layer::SetName(const string &n)
|
||||
{
|
||||
name = n;
|
||||
}
|
||||
|
||||
std::vector<TSE::Transformable *> &TSE::Layer::GetAllObjects()
|
||||
{
|
||||
return objectsToRender;
|
||||
}
|
||||
|
||||
void TSE::Layer::Update()
|
||||
{
|
||||
for(auto trans : objectsToRender)
|
||||
{
|
||||
trans->Update();
|
||||
}
|
||||
}
|
||||
31
TSE_Core/src/elements/Layer.hpp
Normal file
31
TSE_Core/src/elements/Layer.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "Transformable.hpp"
|
||||
#include "Types.hpp"
|
||||
#include "interfaces/IRenderer.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class Layer
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
std::vector<Transformable*> objectsToRender;
|
||||
|
||||
public:
|
||||
Layer(string& name);
|
||||
|
||||
void Render(IRenderer& rnd) const;
|
||||
void AddTransformable(Transformable* t);
|
||||
bool HasTransformable(const Transformable* t) const;
|
||||
|
||||
void RemoveTransformable(const Transformable* t);
|
||||
void RemoveTransformable(const uuids::uuid id);
|
||||
|
||||
string GetName() const;
|
||||
void SetName(const string& name);
|
||||
std::vector<Transformable*>& GetAllObjects();
|
||||
void Update();
|
||||
};
|
||||
} // namespace TSE
|
||||
81
TSE_Core/src/elements/Material.cpp
Normal file
81
TSE_Core/src/elements/Material.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "Material.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include "IdGenerator.hpp"
|
||||
#include "interfaces/ITexture.hpp"
|
||||
#include "Types.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector4.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "Matrix4x4.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
Material::Material()
|
||||
: name(""), shader(nullptr)
|
||||
{
|
||||
id = GenerateRandomUUID();
|
||||
}
|
||||
Material::Material(const string& name, IShader* shader, uuids::uuid id)
|
||||
: name(name), shader(shader), id(id) {}
|
||||
|
||||
Material::Material(const string &name, IShader *shader)
|
||||
: name(name), shader(shader)
|
||||
{
|
||||
id = GenerateRandomUUID();
|
||||
}
|
||||
bool Material::HasValue(const string &key) const
|
||||
{
|
||||
return values.find(key) != values.end();
|
||||
}
|
||||
int Material::GetValueCount() const
|
||||
{
|
||||
return values.size();
|
||||
}
|
||||
std::tuple<std::any, string, string> &Material::GetValueAt(int j)
|
||||
{
|
||||
auto it = values.begin();
|
||||
for (int i = 0; i < j; i++)
|
||||
{
|
||||
it++;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
string &Material::GetName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
IShader *Material::GetShader() const
|
||||
{
|
||||
return shader;
|
||||
}
|
||||
void Material::SetShader(IShader *shader)
|
||||
{
|
||||
this->shader = shader;
|
||||
}
|
||||
uuids::uuid Material::GetID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
template void Material::SetValue<int>(const string&, const int&);
|
||||
template void Material::SetValue<float>(const string&, const float&);
|
||||
template void Material::SetValue<Vector2>(const string&, const Vector2&);
|
||||
template void Material::SetValue<Vector3>(const string&, const Vector3&);
|
||||
template void Material::SetValue<Vector4>(const string&, const Vector4&);
|
||||
template void Material::SetValue<Matrix4x4>(const string&, const Matrix4x4&);
|
||||
template void Material::SetValue<Color>(const string&, const Color&);
|
||||
template void Material::SetValue<string>(const string&, const string&);
|
||||
template void Material::SetValue<ITexture>(const string&, const ITexture*);
|
||||
|
||||
template int Material::GetValue<int>(const string&) const;
|
||||
template float Material::GetValue<float>(const string&) const;
|
||||
template Vector2 Material::GetValue<Vector2>(const string&) const;
|
||||
template Vector3 Material::GetValue<Vector3>(const string&) const;
|
||||
template Vector4 Material::GetValue<Vector4>(const string&) const;
|
||||
template Matrix4x4 Material::GetValue<Matrix4x4>(const string&) const;
|
||||
template Color Material::GetValue<Color>(const string&) const;
|
||||
template string Material::GetValue<string>(const string&) const;
|
||||
template ITexture* Material::GetValue<ITexture*>(const string&) const;
|
||||
} // namespace TSE
|
||||
65
TSE_Core/src/elements/Material.hpp
Normal file
65
TSE_Core/src/elements/Material.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "uuid.h"
|
||||
#include "interfaces/IShader.hpp"
|
||||
#include <unordered_map>
|
||||
#include <any>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
struct Material
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
uuids::uuid id;
|
||||
IShader* shader;
|
||||
|
||||
std::unordered_map<string, std::tuple<std::any, string, string>> values;
|
||||
|
||||
public:
|
||||
Material();
|
||||
Material(const string& name, IShader* shader);
|
||||
Material(const string& name, IShader* shader, uuids::uuid id);
|
||||
|
||||
template<typename T>
|
||||
void SetValue(const string& key, const T& value);
|
||||
|
||||
template<typename T>
|
||||
T GetValue(const string& key) const;
|
||||
|
||||
template<typename T>
|
||||
void SetValue(const string& key, const T* value);
|
||||
|
||||
bool HasValue(const string& key) const;
|
||||
int GetValueCount() const;
|
||||
|
||||
std::tuple<std::any, string, string>& GetValueAt(int i);
|
||||
string& GetName();
|
||||
IShader* GetShader() const;
|
||||
void SetShader(IShader* shader);
|
||||
uuids::uuid GetID() const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void Material::SetValue(const string& key, const T& value) {
|
||||
values[key] = std::make_tuple(value, typeid(T).name(), key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Material::GetValue(const string& key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
throw std::runtime_error("Material::GetValue - key '" + key + "' not found");
|
||||
}
|
||||
auto [a,b,c] = it->second;
|
||||
return std::any_cast<T>(a);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Material::SetValue(const string& key, const T* value) {
|
||||
values[key] = std::make_tuple(value, typeid(T).name(), key);
|
||||
}
|
||||
|
||||
} // namespace TSE
|
||||
469
TSE_Core/src/elements/Transformable.cpp
Normal file
469
TSE_Core/src/elements/Transformable.cpp
Normal file
@@ -0,0 +1,469 @@
|
||||
#include "Transformable.hpp"
|
||||
|
||||
#include "IdGenerator.hpp"
|
||||
#include "MathF.hpp"
|
||||
#include "BehaviourScript.hpp"
|
||||
#include "Layer.hpp"
|
||||
#include "Debug.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
Transformable::Transformable()
|
||||
: position(0, 0, 0), scale(1, 1, 1), rotation(), name("")
|
||||
{
|
||||
id = GenerateRandomUUID();
|
||||
objectEntries[id] = this;
|
||||
}
|
||||
|
||||
Transformable::Transformable(uuids::uuid id)
|
||||
: id(id), position(0, 0, 0), scale(1, 1, 1), rotation(), name("")
|
||||
{
|
||||
objectEntries[id] = this;
|
||||
}
|
||||
|
||||
Transformable::Transformable(const string &name)
|
||||
: position(0, 0, 0), scale(1, 1, 1), rotation(), name(name)
|
||||
{
|
||||
id = GenerateRandomUUID();
|
||||
objectEntries[id] = this;
|
||||
}
|
||||
|
||||
Transformable::Transformable(const string &name, uuids::uuid id)
|
||||
: id(id), position(0, 0, 0), scale(1, 1, 1), rotation(), name(name)
|
||||
{
|
||||
objectEntries[id] = this;
|
||||
}
|
||||
|
||||
Vector3 Transformable::forward() const
|
||||
{
|
||||
return Vector3::Normalize(GetGlobalMatrix() * Vector3::forward - GetGlobalMatrix() * Vector3::zero);
|
||||
}
|
||||
|
||||
Vector3 Transformable::right() const
|
||||
{
|
||||
return Vector3::Normalize(GetGlobalMatrix() * Vector3::right - GetGlobalMatrix() * Vector3::zero);
|
||||
}
|
||||
|
||||
Vector3 Transformable::up() const
|
||||
{
|
||||
return Vector3::Normalize(GetGlobalMatrix() * Vector3::up - GetGlobalMatrix() * Vector3::zero);
|
||||
}
|
||||
|
||||
Vector3 Transformable::GetPosition() const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
void Transformable::SetPosition(const Vector3 &pos)
|
||||
{
|
||||
position = pos;
|
||||
}
|
||||
|
||||
Quaternion Transformable::GetRotation() const
|
||||
{
|
||||
return rotation;
|
||||
}
|
||||
|
||||
void Transformable::SetRotation(const Quaternion &rot)
|
||||
{
|
||||
rotation = rot;
|
||||
}
|
||||
|
||||
Vector3 Transformable::GetScale() const
|
||||
{
|
||||
return scale;
|
||||
}
|
||||
|
||||
void Transformable::SetScale(const Vector3 &s)
|
||||
{
|
||||
scale = s;
|
||||
}
|
||||
|
||||
string Transformable::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
uuids::uuid Transformable::GetId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
Vector3 Transformable::GetEuler()
|
||||
{
|
||||
return rotation.ToEulerAngles();
|
||||
}
|
||||
|
||||
void Transformable::SetEuler(const Vector3 &euler)
|
||||
{
|
||||
rotation = Quaternion::FromEulerAngles(euler);
|
||||
}
|
||||
|
||||
int Transformable::GetComponentCount()
|
||||
{
|
||||
return components.size();
|
||||
}
|
||||
|
||||
Matrix4x4 Transformable::GetLocalMatrix() const
|
||||
{
|
||||
return Matrix4x4::ToTranslationMatrix(position) * Matrix4x4::ToRotationMatrix(rotation) * Matrix4x4::ToScaleMatrix(scale);;
|
||||
}
|
||||
|
||||
Matrix4x4 Transformable::GetGlobalMatrix() const
|
||||
{
|
||||
if (parent != nullptr)
|
||||
return parent->GetGlobalMatrix() * GetLocalMatrix();
|
||||
return GetLocalMatrix();
|
||||
}
|
||||
|
||||
Vector3 Transformable::GetGlobalPosition() const
|
||||
{
|
||||
return LocalToGlobalPosition(Vector3::zero);
|
||||
}
|
||||
|
||||
Vector3 Transformable::GlobalToLocalPosition(const Vector3& global) const
|
||||
{
|
||||
Matrix4x4 globalMatrix = GetGlobalMatrix();
|
||||
if(globalMatrix.IsAffine())
|
||||
{
|
||||
globalMatrix.InvertAffine();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalMatrix.Invert();
|
||||
}
|
||||
return globalMatrix * global;
|
||||
}
|
||||
|
||||
Vector3 Transformable::LocalToGlobalPosition(const Vector3& local) const
|
||||
{
|
||||
return GetGlobalMatrix() * local;
|
||||
}
|
||||
|
||||
void Transformable::LookAt_2D(const Vector3& globalTarget)
|
||||
{
|
||||
Vector3 to = globalTarget - GetGlobalPosition();
|
||||
Vector3 toXY = {to.x, to.y, 0.0f};
|
||||
if(Vector3::Dot(toXY, toXY) < TSE_EPSILON) return;
|
||||
toXY.Normalize();
|
||||
|
||||
Vector3 fwdWorld = rotation.Rotate(Vector3::up);
|
||||
Vector3 fwdXY = Vector3(fwdWorld.x, fwdWorld.y, 0);
|
||||
fwdXY.Normalize();
|
||||
|
||||
float cosA = std::clamp(Vector3::Dot(fwdXY, toXY), -1.0f, 1.0f);
|
||||
float sinA = fwdXY.x * toXY.y - fwdXY.y * toXY.x;
|
||||
float angle = atan2(sinA, cosA);
|
||||
|
||||
Quaternion twist = Quaternion::FromAngleAxis(angle, Vector3::forward);
|
||||
rotation = twist * rotation;
|
||||
}
|
||||
|
||||
void Transformable::SetParent(Transformable *p)
|
||||
{
|
||||
Transformable* t(this);
|
||||
if (parent != nullptr && parent != p) {
|
||||
|
||||
auto it = parent->children.begin();
|
||||
for (int i = 0; i < parent->children.size(); i++)
|
||||
{
|
||||
if(**it == *t)
|
||||
{
|
||||
parent->children.erase(it);
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (p != nullptr && p != parent) {
|
||||
p->children.push_back(t);
|
||||
}
|
||||
parent = p;
|
||||
}
|
||||
|
||||
Transformable *Transformable::GetParent() const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
const std::vector<Transformable *> &Transformable::GetChildren() const
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
bool Transformable::IsMyChild(Transformable *other)
|
||||
{
|
||||
for (auto child : children)
|
||||
{
|
||||
if(child->id == other->id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(child->IsMyChild(other))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Transformable::MoveUp(Layer *l)
|
||||
{
|
||||
if(l != nullptr)
|
||||
{
|
||||
auto it = l->GetAllObjects().begin();
|
||||
for(int i = 0; i < l->GetAllObjects().size(); i++)
|
||||
{
|
||||
if((*it)->id == id)
|
||||
{
|
||||
if(i == 0) return;
|
||||
std::swap(l->GetAllObjects()[i - 1], l->GetAllObjects()[i]);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto it = parent->children.begin();
|
||||
for(int i = 0; i < parent->children.size(); i++)
|
||||
{
|
||||
if((*it)->id == id)
|
||||
{
|
||||
if(i == 0) return;
|
||||
std::swap(parent->children[i - 1], parent->children[i]);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void Transformable::MoveDown(Layer *l)
|
||||
{
|
||||
if(l != nullptr)
|
||||
{
|
||||
auto it = l->GetAllObjects().begin();
|
||||
for(int i = 0; i < l->GetAllObjects().size(); i++)
|
||||
{
|
||||
if((*it)->id == id)
|
||||
{
|
||||
if(i == l->GetAllObjects().size() - 1) return;
|
||||
std::swap(l->GetAllObjects()[i + 1], l->GetAllObjects()[i]);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto it = parent->children.begin();
|
||||
for(int i = 0; i < parent->children.size(); i++)
|
||||
{
|
||||
if((*it)->id == id)
|
||||
{
|
||||
if(i == parent->children.size() - 1) return;
|
||||
std::swap(parent->children[i + 1], parent->children[i]);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
bool Transformable::IsEnabled() const
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
void Transformable::SetEnabled(bool v)
|
||||
{
|
||||
if (_enabled != v) {
|
||||
_enabled = v;
|
||||
if (_enabled) OnEnable();
|
||||
else OnDisable();
|
||||
}
|
||||
}
|
||||
|
||||
BehaviourScript *Transformable::AddBehaviourScript(BehaviourScript *script)
|
||||
{
|
||||
if (!script) return nullptr;
|
||||
const std::string key = typeid(*script).name();
|
||||
components.emplace(key, script);
|
||||
script->SetBaseObject(this);
|
||||
script->Start();
|
||||
return script;
|
||||
}
|
||||
|
||||
BehaviourScript *Transformable::GetBehaviourScript(const string &name) const
|
||||
{
|
||||
auto it = components.find(name);
|
||||
return (it != components.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
BehaviourScript *Transformable::GetBehaviourScriptAt(const int i) const
|
||||
{
|
||||
auto it = components.begin();
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
it++;
|
||||
|
||||
}
|
||||
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
std::vector<BehaviourScript *> Transformable::GetAllBehaviourScripts(const string &name) const
|
||||
{
|
||||
std::vector<BehaviourScript *> res;
|
||||
|
||||
auto it = components.begin();
|
||||
while(it != components.end())
|
||||
{
|
||||
if((*it).first == name)
|
||||
{
|
||||
res.push_back((*it).second);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Transformable::RemoveBehaviourScript(BehaviourScript *script)
|
||||
{
|
||||
for (auto it = components.begin(); it != components.end(); ++it) {
|
||||
if (it->second == script) {
|
||||
components.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Transformable::HasBehaviourScript(const string &name) const
|
||||
{
|
||||
auto it = components.find(name);
|
||||
return it != components.end();
|
||||
}
|
||||
|
||||
void Transformable::Update()
|
||||
{
|
||||
for (auto& [name, script] : components) {
|
||||
if (script && script->IsEnabled()) script->OnUpdate();
|
||||
}
|
||||
for (auto child : children)
|
||||
{
|
||||
child->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void Transformable::Delete(Transformable *t)
|
||||
{
|
||||
objectEntries.erase(t->id);
|
||||
delete t;
|
||||
}
|
||||
|
||||
void Transformable::Delete(const uuids::uuid id)
|
||||
{
|
||||
if(!Exists(id)) return;
|
||||
Transformable* t = objectEntries.at(id);
|
||||
objectEntries.erase(id);
|
||||
delete t;
|
||||
}
|
||||
|
||||
void Transformable::HardDelete(Transformable *t, bool onlyThis)
|
||||
{
|
||||
//deleting children
|
||||
if(!onlyThis)
|
||||
for(auto child : t->children)
|
||||
{
|
||||
HardDelete(child);
|
||||
}
|
||||
|
||||
//deleting atteched scripts
|
||||
for (auto& [_, script] : t->components)
|
||||
delete script;
|
||||
|
||||
//deleting self
|
||||
Delete(t);
|
||||
}
|
||||
|
||||
void Transformable::HardDelete(const uuids::uuid id, bool onlyThis)
|
||||
{
|
||||
if(!Exists(id)) return;
|
||||
Transformable* t = objectEntries.at(id);
|
||||
//deleting children
|
||||
if(!onlyThis)
|
||||
for(auto child : t->children)
|
||||
{
|
||||
HardDelete(child);
|
||||
}
|
||||
|
||||
//deleting atteched scripts
|
||||
for (auto& [_, script] : t->components)
|
||||
delete script;
|
||||
|
||||
//deleting self
|
||||
Delete(t);
|
||||
}
|
||||
|
||||
void Transformable::DeleteAll()
|
||||
{
|
||||
auto it = objectEntries.begin();
|
||||
for(int i = 0; i < objectEntries.size(); i++)
|
||||
{
|
||||
delete it->second;
|
||||
it++;
|
||||
}
|
||||
objectEntries.clear();
|
||||
}
|
||||
|
||||
bool Transformable::Exists(const uuids::uuid id)
|
||||
{
|
||||
auto it = objectEntries.find(id);
|
||||
return it != objectEntries.end();
|
||||
}
|
||||
|
||||
bool Transformable::operator==(const Transformable &other) const
|
||||
{
|
||||
return other.id == id;
|
||||
}
|
||||
|
||||
bool Transformable::operator!=(const Transformable &other) const
|
||||
{
|
||||
return other.id != id;
|
||||
}
|
||||
|
||||
void Transformable::OnEnable()
|
||||
{
|
||||
for (auto& [_, script] : components)
|
||||
if (script && script->IsEnabled()) script->OnEnable();
|
||||
}
|
||||
|
||||
void Transformable::OnDisable()
|
||||
{
|
||||
for (auto& [_, script] : components)
|
||||
if (script && script->IsEnabled()) script->OnDisable();
|
||||
}
|
||||
|
||||
int Transformable::GetTansformableCount()
|
||||
{
|
||||
return objectEntries.size();
|
||||
}
|
||||
|
||||
Transformable *Transformable::Find(string name)
|
||||
{
|
||||
for(auto obj : objectEntries)
|
||||
{
|
||||
if(obj.second->name == name)
|
||||
{
|
||||
return obj.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Transformable *Transformable::Find(uuids::uuid id)
|
||||
{
|
||||
for(auto obj : objectEntries)
|
||||
{
|
||||
if(obj.second->id == id)
|
||||
{
|
||||
return obj.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace TSE
|
||||
106
TSE_Core/src/elements/Transformable.hpp
Normal file
106
TSE_Core/src/elements/Transformable.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include "Quaternion.hpp"
|
||||
#include "Matrix4x4.hpp"
|
||||
#include "uuid.h"
|
||||
#include "Types.hpp"
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class BehaviourScript;
|
||||
class Layer;
|
||||
|
||||
class Transformable
|
||||
{
|
||||
public:
|
||||
Vector3 position;
|
||||
Vector3 scale;
|
||||
Quaternion rotation;
|
||||
string name;
|
||||
bool _enabled = true;
|
||||
uuids::uuid id;
|
||||
|
||||
private:
|
||||
std::unordered_multimap<string, BehaviourScript*> components;
|
||||
std::vector<Transformable*> children;
|
||||
Transformable* parent = nullptr;
|
||||
|
||||
static std::unordered_map<uuids::uuid, Transformable*> objectEntries;
|
||||
|
||||
public:
|
||||
Transformable();
|
||||
Transformable(uuids::uuid id);
|
||||
Transformable(const string& name);
|
||||
Transformable(const string& name, uuids::uuid id);
|
||||
~Transformable() = default;
|
||||
|
||||
Vector3 forward() const;
|
||||
Vector3 right() const;
|
||||
Vector3 up() const;
|
||||
|
||||
Vector3 GetPosition() const;
|
||||
void SetPosition(const Vector3& pos);
|
||||
Quaternion GetRotation() const;
|
||||
void SetRotation(const Quaternion& rot);
|
||||
Vector3 GetScale() const;
|
||||
void SetScale(const Vector3& scale);
|
||||
string GetName() const;
|
||||
uuids::uuid GetId() const;
|
||||
Vector3 GetEuler();
|
||||
void SetEuler(const Vector3& euler);
|
||||
int GetComponentCount();
|
||||
Matrix4x4 GetLocalMatrix() const;
|
||||
Matrix4x4 GetGlobalMatrix() const;
|
||||
Vector3 GetGlobalPosition() const;
|
||||
|
||||
Vector3 GlobalToLocalPosition(const Vector3& global) const;
|
||||
Vector3 LocalToGlobalPosition(const Vector3& local) const;
|
||||
|
||||
void LookAt_2D(const Vector3& globalTarget);
|
||||
|
||||
void SetParent(Transformable* parent);
|
||||
Transformable* GetParent() const;
|
||||
const std::vector<Transformable*>& GetChildren() const;
|
||||
bool IsMyChild(Transformable* other);
|
||||
|
||||
void MoveUp(Layer* l = nullptr);
|
||||
void MoveDown(Layer* l = nullptr);
|
||||
|
||||
bool IsEnabled() const;
|
||||
void SetEnabled(bool v);
|
||||
|
||||
BehaviourScript* AddBehaviourScript(BehaviourScript* script);
|
||||
BehaviourScript* GetBehaviourScript(const string& name) const;
|
||||
BehaviourScript* GetBehaviourScriptAt(const int i) const;
|
||||
std::vector<BehaviourScript*> GetAllBehaviourScripts(const string& name) const;
|
||||
void RemoveBehaviourScript(BehaviourScript* script);
|
||||
bool HasBehaviourScript(const string& name) const;
|
||||
|
||||
void Update();
|
||||
|
||||
static void Delete(Transformable* t);
|
||||
static void Delete(const uuids::uuid id);
|
||||
static void HardDelete(Transformable* t, bool onlyThis = false);
|
||||
static void HardDelete(const uuids::uuid id, bool onlyThis = false);
|
||||
static void DeleteAll();
|
||||
|
||||
static bool Exists(const uuids::uuid id);
|
||||
|
||||
bool operator==(const Transformable& other) const;
|
||||
bool operator!=(const Transformable& other) const;
|
||||
|
||||
private:
|
||||
void OnEnable();
|
||||
void OnDisable();
|
||||
|
||||
public:
|
||||
|
||||
static int GetTansformableCount();
|
||||
static Transformable* Find(string name);
|
||||
static Transformable* Find(uuids::uuid id);
|
||||
};
|
||||
}
|
||||
18
TSE_Core/src/interfaces/IRenderable.hpp
Normal file
18
TSE_Core/src/interfaces/IRenderable.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class IRenderable
|
||||
{
|
||||
public:
|
||||
virtual const Vector3* GetVertices() const = 0;
|
||||
virtual const Vector2* GetUVs() const = 0;
|
||||
virtual const std::vector<ushort> GetIndices() const = 0;
|
||||
virtual size_t GetVertexCount() const = 0;
|
||||
virtual ~IRenderable() = default;
|
||||
};
|
||||
} // namespace TSE
|
||||
3
TSE_Core/src/interfaces/IRenderer.cpp
Normal file
3
TSE_Core/src/interfaces/IRenderer.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "IRenderer.hpp"
|
||||
|
||||
std::vector<TSE::Camera*> TSE::IRenderer::camerasToRenderWith = std::vector<TSE::Camera*>();
|
||||
26
TSE_Core/src/interfaces/IRenderer.hpp
Normal file
26
TSE_Core/src/interfaces/IRenderer.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "IShader.hpp"
|
||||
#include "TransformationStack.hpp"
|
||||
#include "elements/Transformable.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class Camera;
|
||||
|
||||
class IRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
static std::vector<Camera*> camerasToRenderWith;
|
||||
|
||||
virtual void End() = 0;
|
||||
virtual void Flush() = 0;
|
||||
virtual void Begin() = 0;
|
||||
|
||||
virtual void Submit(const Transformable& trans, TransformationStack& stack) = 0;
|
||||
virtual void Submit(const Transformable& trans, IShader* shader, TransformationStack& stack) = 0;
|
||||
|
||||
virtual ~IRenderer() = default;
|
||||
};
|
||||
} // namespace TSE
|
||||
29
TSE_Core/src/interfaces/IShader.hpp
Normal file
29
TSE_Core/src/interfaces/IShader.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "Types.hpp"
|
||||
#include "Matrix4x4.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
#include "Vector4.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class IShader
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void Bind() const = 0;
|
||||
virtual void Unbind() const = 0;
|
||||
|
||||
virtual void SetUniform(const char* name, int value) = 0;
|
||||
virtual void SetUniform(const char* name, const int* value, int count) = 0;
|
||||
virtual void SetUniform(const char* name, const Matrix4x4* value) = 0;
|
||||
virtual void SetUniform(const char* name, float value) = 0;
|
||||
virtual void SetUniform(const char* name, const float* value, int count) = 0;
|
||||
virtual void SetUniform(const char* name, const Vector2* value) = 0;
|
||||
virtual void SetUniform(const char* name, const Vector3* value) = 0;
|
||||
virtual void SetUniform(const char* name, const Vector4* value) = 0;
|
||||
|
||||
virtual ~IShader() = default;
|
||||
};
|
||||
} // namespace TSE
|
||||
16
TSE_Core/src/interfaces/ITexture.hpp
Normal file
16
TSE_Core/src/interfaces/ITexture.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vector2.hpp"
|
||||
|
||||
namespace TSE
|
||||
{
|
||||
class ITexture
|
||||
{
|
||||
public:
|
||||
virtual ~ITexture() = default;
|
||||
virtual Vector2 size() const = 0;
|
||||
virtual float width() const = 0;
|
||||
virtual float height() const = 0;
|
||||
virtual uint GetTextureId() const = 0;
|
||||
};
|
||||
} // namespace TSE
|
||||
Reference in New Issue
Block a user