geode/loader/include/Geode/modify/IDManager.hpp

71 lines
2 KiB
C++
Raw Normal View History

2022-10-17 05:25:56 -04:00
#pragma once
#include "../DefaultInclude.hpp"
#include "../ui/EnterLayerEvent.hpp"
2022-10-17 05:25:56 -04:00
namespace cocos2d {
class CCNode;
}
namespace geode {
template<class T>
2022-10-23 06:46:06 -04:00
concept IDProvidable = std::is_base_of_v<cocos2d::CCNode, T> && requires {
{ T::CLASS_NAME } -> std::convertible_to<const char*>;
};
2024-06-20 16:00:04 -04:00
class GEODE_DLL NodeIDs final {
2022-10-17 05:25:56 -04:00
public:
template<class T>
using Provider = void(GEODE_CALL*)(T*);
protected:
std::unordered_map<std::string, Provider<cocos2d::CCNode>> m_providers;
public:
static NodeIDs* get();
2022-10-17 05:25:56 -04:00
template<IDProvidable T>
void registerProvider(void(GEODE_CALL* fun)(T*)) {
m_providers.insert({
T::CLASS_NAME,
reinterpret_cast<Provider<cocos2d::CCNode>>(fun)
});
2022-10-17 05:25:56 -04:00
}
template<IDProvidable T>
bool provide(T* layer) const {
if (m_providers.count(T::CLASS_NAME)) {
m_providers.at(T::CLASS_NAME)(layer);
return true;
}
return false;
}
// @note Because NodeIDs::provideFor(this) looks really neat
template<IDProvidable T>
static bool provideFor(T* layer) {
return NodeIDs::get()->provide(layer);
}
2022-10-17 05:25:56 -04:00
};
template<IDProvidable For>
void GEODE_CALL geodeInternalProvideIDsFor(For* cls) {
2024-01-01 12:54:40 -05:00
if (cls->CCNode::getID() != For::CLASS_NAME) {
cls->CCNode::setID(For::CLASS_NAME);
cls->provide();
EnterLayerEvent(For::CLASS_NAME, cls).post();
}
}
}
#define $register_ids(Layer_) \
2022-10-23 06:46:06 -04:00
struct GEODE_CONCAT(ProvideIDsFor, Layer_) : public Layer_ {\
void provide();\
};\
2022-10-17 05:25:56 -04:00
$execute {\
NodeIDs::get()->registerProvider(\
&geodeInternalProvideIDsFor<GEODE_CONCAT(ProvideIDsFor, Layer_)>\
);\
2022-10-17 05:25:56 -04:00
};\
void GEODE_CONCAT(ProvideIDsFor, Layer_)::provide()