#pragma once #include #include // Duplicate VTable template T *extend_dup_vtable(T *vtable) { // Get Size const unsigned char *const real_vtable = ((const unsigned char *) vtable) - sizeof(void *); constexpr size_t real_vtable_size = sizeof(T) + sizeof(void *); // Allocate unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size); T *ret = (T *) (new_vtable + sizeof(void *)); new (ret) T; // Copy memcpy(new_vtable, real_vtable, real_vtable_size); // Return return ret; } // Customize VTable template T *extend_get_vtable() { static T *vtable = nullptr; if (!vtable) { vtable = extend_dup_vtable(T::base); setup_vtable(vtable); } return vtable; } #define CUSTOM_VTABLE(name, parent) \ static void setup_##name##_vtable(parent##_vtable *); \ static parent##_vtable *get_##name##_vtable() { \ return extend_get_vtable(); \ } \ static void setup_##name##_vtable(parent##_vtable *vtable) // Extend MCPI Classes template Data *extend_get_data(Self *self) { return (Data *) (self + 1); } template auto extend_struct(auto&&... args) -> decltype(Self::allocate()) { constexpr size_t size = sizeof(Self) + sizeof(Data); Self *out = (Self *) ::operator new(size); Data *data = extend_get_data(out); new (data) Data(std::forward(args)...); return out; } // Helpers #define CREATE_HELPER(name) \ struct Custom##name { \ explicit Custom##name(auto&&... args): self(((name *) this) - 1) { \ self->constructor(std::forward(args)...); \ self->vtable = get_vtable(); \ } \ name *const self; \ static name##_vtable *get_vtable(); \ private: \ static void setup_vtable(name##_vtable *vtable); \ protected: \ virtual ~Custom##name() = default; \ public: #include "Screen.h" #include "DynamicTexture.h" #undef CREATE_HELPER