mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 18:05:35 -05:00
add proxy ID API
This commit is contained in:
parent
19f18ca927
commit
06ecaa9837
2 changed files with 91 additions and 3 deletions
53
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
53
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
|
@ -916,13 +916,24 @@ public:
|
|||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL CCNode* getChildByID(std::string_view id);
|
||||
/**
|
||||
* Get a child by its string ID
|
||||
* @param id ID of the child
|
||||
* @param considerProxies If true, proxy IDs will be checked first
|
||||
* @returns The child, or nullptr if none was found
|
||||
* @note Geode addition
|
||||
* @todo in v5: merge this with getChildByID and add default value considerProxies = true
|
||||
*/
|
||||
GEODE_DLL CCNode* getChildByID(std::string_view id, bool considerProxies);
|
||||
|
||||
/**
|
||||
* Get a child by its string ID. Recursively searches all the children
|
||||
* @param id ID of the child
|
||||
* @returns The child, or nullptr if none was found
|
||||
* @note Geode addition
|
||||
* @todo in v5: remove
|
||||
*/
|
||||
[[deprecated("Use CCNode::querySelector instead")]]
|
||||
GEODE_DLL CCNode* getChildByIDRecursive(std::string_view id);
|
||||
|
||||
/**
|
||||
|
@ -945,9 +956,51 @@ public:
|
|||
* Removes a child from the container by its ID.
|
||||
* @param id The ID of the node
|
||||
* @note Geode addition
|
||||
* @note Will not follow proxies but just delete the proxy; if you want to
|
||||
* actually remove the node the proxy points to itself, use
|
||||
* `getChildByID(id)->removeFromParent()`
|
||||
*/
|
||||
GEODE_DLL void removeChildByID(std::string_view id);
|
||||
|
||||
/**
|
||||
* Add a Proxy ID to this node. A Proxy ID is an ID of a node that is
|
||||
* logically the child of this node, but might not actually be. In other
|
||||
* words, when using `CCNode::getChildByID` or other related functions, it
|
||||
* will first check if there is a proxy ID on that node, and follow those
|
||||
* if one does exist.
|
||||
*
|
||||
* For example, if a mod moves a button to another CCMenu, it should leave
|
||||
* behind a proxy ID into the old CCMenu so any other mod trying to find the
|
||||
* button in the old menu will still get it.
|
||||
*
|
||||
* Another example: if a mod makes a CCMenu paged, it will probably add lots
|
||||
* of wrapper nodes into the node tree, but any buttons of the CCMenu still
|
||||
* logically stay children of the CCMenu. That mod would then use proxy IDs
|
||||
* so the menu will appear like nothing has changed for other mods which try
|
||||
* to work with it.
|
||||
*
|
||||
* @param id The ID of the proxy node
|
||||
* @param getter When the ID is queried, returns the actual node it points
|
||||
* to. Needs not be a child of this node. May return nullptr if the node no
|
||||
* longer exists
|
||||
* @returns True if the ID was added, or false if it this ID has already
|
||||
* been added
|
||||
*/
|
||||
GEODE_DLL bool addProxyID(std::string_view id, std::function<CCNode*(CCNode*)> getter);
|
||||
/**
|
||||
* Remove a Proxy ID from this node
|
||||
* @param id The ID of the Proxy. If the ID does not point to a proxy,
|
||||
* nothing happens
|
||||
*/
|
||||
GEODE_DLL void removeProxyID(std::string_view id);
|
||||
/**
|
||||
* Check if the given ID is of a proxy node or of an actual child
|
||||
* @returns True if the ID is of a proxy
|
||||
* @note Technically there may also be children with the same ID, but this
|
||||
* function will return true if there is a proxy
|
||||
*/
|
||||
GEODE_DLL bool isProxyID(std::string_view id);
|
||||
|
||||
/**
|
||||
* Add a child before a specified existing child
|
||||
* @param child The node to add. The node may not be a child of another
|
||||
|
|
|
@ -24,6 +24,7 @@ private:
|
|||
std::unordered_map<std::string, Ref<CCObject>> m_userObjects;
|
||||
std::unordered_set<std::unique_ptr<EventListenerProtocol>> m_eventListeners;
|
||||
std::unordered_map<std::string, std::unique_ptr<EventListenerProtocol>> m_idEventListeners;
|
||||
std::unordered_map<std::string, std::function<CCNode*(CCNode*)>> m_proxies;
|
||||
|
||||
friend class ProxyCCNode;
|
||||
friend class cocos2d::CCNode;
|
||||
|
@ -117,6 +118,15 @@ void CCNode::setID(std::string&& id) {
|
|||
}
|
||||
|
||||
CCNode* CCNode::getChildByID(std::string_view id) {
|
||||
return this->getChildByID(id, true);
|
||||
}
|
||||
CCNode* CCNode::getChildByID(std::string_view id, bool considerProxies) {
|
||||
if (considerProxies) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
if (meta->m_proxies.contains(std::string(id))) {
|
||||
return meta->m_proxies.at(std::string(id))(this);
|
||||
}
|
||||
}
|
||||
for (auto child : CCArrayExt<CCNode*>(this->getChildren())) {
|
||||
if (child->getID() == id) {
|
||||
return child;
|
||||
|
@ -124,7 +134,6 @@ CCNode* CCNode::getChildByID(std::string_view id) {
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCNode* CCNode::getChildByIDRecursive(std::string_view id) {
|
||||
if (auto child = this->getChildByID(id)) {
|
||||
return child;
|
||||
|
@ -294,9 +303,35 @@ CCNode* CCNode::querySelector(std::string_view queryStr) {
|
|||
}
|
||||
|
||||
void CCNode::removeChildByID(std::string_view id) {
|
||||
if (auto child = this->getChildByID(id)) {
|
||||
this->removeChild(child);
|
||||
// Remove proxies with this ID
|
||||
if (this->isProxyID(id)) {
|
||||
this->removeProxyID(id);
|
||||
}
|
||||
// Technically there can be multiple children with the same ID in addition
|
||||
// to the proxy ID. However, this is very bad practice, and removing actual
|
||||
// children only when there's no proxies with the ID mirrors the fact that
|
||||
// if there's four children with the same ID, you need to call
|
||||
// `removeChildByID` four times to remove them all
|
||||
else {
|
||||
if (auto child = this->getChildByID(id, false)) {
|
||||
this->removeChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CCNode::addProxyID(std::string_view id, std::function<CCNode*(CCNode*)> getter) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
if (meta->m_proxies.contains(std::string(id))) {
|
||||
return false;
|
||||
}
|
||||
meta->m_proxies.insert({ std::string(id), getter });
|
||||
return true;
|
||||
}
|
||||
void CCNode::removeProxyID(std::string_view id) {
|
||||
GeodeNodeMetadata::set(this)->m_proxies.erase(std::string(id));
|
||||
}
|
||||
bool CCNode::isProxyID(std::string_view id) {
|
||||
return GeodeNodeMetadata::set(this)->m_proxies.contains(std::string(id));
|
||||
}
|
||||
|
||||
void CCNode::setLayout(Layout* layout, bool apply, bool respectAnchor) {
|
||||
|
|
Loading…
Reference in a new issue