mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-26 01:18:01 -05:00
70 lines
2 KiB
C++
70 lines
2 KiB
C++
#pragma once
|
|
|
|
#include "../DefaultInclude.hpp"
|
|
#include "../ui/EnterLayerEvent.hpp"
|
|
|
|
namespace cocos2d {
|
|
class CCNode;
|
|
}
|
|
|
|
namespace geode {
|
|
template<class T>
|
|
concept IDProvidable = std::is_base_of_v<cocos2d::CCNode, T> && requires {
|
|
{ T::CLASS_NAME } -> std::convertible_to<const char*>;
|
|
};
|
|
|
|
class GEODE_DLL NodeIDs final {
|
|
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();
|
|
|
|
template<IDProvidable T>
|
|
void registerProvider(void(GEODE_CALL* fun)(T*)) {
|
|
m_providers.insert({
|
|
T::CLASS_NAME,
|
|
reinterpret_cast<Provider<cocos2d::CCNode>>(fun)
|
|
});
|
|
}
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
template<IDProvidable For>
|
|
void GEODE_CALL geodeInternalProvideIDsFor(For* cls) {
|
|
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_) \
|
|
struct GEODE_CONCAT(ProvideIDsFor, Layer_) : public Layer_ {\
|
|
void provide();\
|
|
};\
|
|
$execute {\
|
|
NodeIDs::get()->registerProvider(\
|
|
&geodeInternalProvideIDsFor<GEODE_CONCAT(ProvideIDsFor, Layer_)>\
|
|
);\
|
|
};\
|
|
void GEODE_CONCAT(ProvideIDsFor, Layer_)::provide()
|