diff --git a/src/DevTools.cpp b/src/DevTools.cpp index ffe7243..dbc3d40 100644 --- a/src/DevTools.cpp +++ b/src/DevTools.cpp @@ -36,6 +36,7 @@ struct matjson::Serialize { assign(value["button_game"], s.buttonInGame); assign(value["button_enabled"], s.buttonEnabled); assign(value["tree_drag_reorder"], s.treeDragReorder); + assign(value["hide_flagged_nodes"], s.hideFlaggedNodes); return Ok(s); } @@ -58,7 +59,8 @@ struct matjson::Serialize { { "button_editor", settings.buttonInEditor }, { "button_game", settings.buttonInGame }, { "button_enabled", settings.buttonEnabled }, - { "tree_drag_reorder", settings.treeDragReorder } + { "tree_drag_reorder", settings.treeDragReorder }, + { "hide_flagged_nodes", settings.hideFlaggedNodes }, }); } }; diff --git a/src/DevTools.hpp b/src/DevTools.hpp index 3838f37..3007e83 100644 --- a/src/DevTools.hpp +++ b/src/DevTools.hpp @@ -36,6 +36,20 @@ struct Settings { bool buttonInGame = false; bool buttonEnabled = false; bool treeDragReorder = false; + bool hideFlaggedNodes = false; +}; + +struct TreeBranchOptions { + bool drag = true; + bool visible = true; + bool fake = false; + bool flagHidden = false; +}; + +struct ParentNodeInformation { + bool drag = true; + bool visible = true; + bool flagHidden = false; }; class DevTools { @@ -66,7 +80,8 @@ class DevTools { void setupPlatform(); void drawTree(); - void drawTreeBranch(CCNode* node, size_t index, bool drag, bool visible); + void drawTreeBranch(CCNode* node, size_t index, TreeBranchOptions options); + void drawNodeChildren(CCNode* node, ParentNodeInformation info); void drawSettings(); void drawAdvancedSettings(); void drawNodeAttributes(CCNode* node); diff --git a/src/pages/Settings.cpp b/src/pages/Settings.cpp index 57f4b4e..6768650 100644 --- a/src/pages/Settings.cpp +++ b/src/pages/Settings.cpp @@ -64,6 +64,14 @@ void DevTools::drawSettings() { "(Experimental)\nAllows you to drag/drop nodes in the node tree, changing\ntheir parents or ordering." ); } + ImGui::Checkbox("Hide Flagged Nodes", &m_settings.hideFlaggedNodes); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "If enabled, hides nodes in the node tree with the \"geode.devtools/hide\"\n" + "user flag set. Allows for hiding nodes irrelevant to debugging, such as containers.\n" + "This will keep the children of those nodes visible in the node tree." + ); + } ImGui::Checkbox("Advanced Settings", &m_settings.advancedSettings); if (ImGui::IsItemHovered()) { ImGui::SetTooltip( diff --git a/src/pages/Tree.cpp b/src/pages/Tree.cpp index af2c284..c0586c0 100644 --- a/src/pages/Tree.cpp +++ b/src/pages/Tree.cpp @@ -13,8 +13,11 @@ using namespace geode::prelude; -std::string formatNodeName(CCNode* node, size_t index) { - std::string name = fmt::format("[{}] {} ", index, geode::cocos::getObjectName(node)); +std::string formatNodeName(CCNode* node, size_t index, bool fake, bool flagHidden) { + std::string prefix = ""; + if (fake) prefix += "*"; + if (flagHidden) prefix += "..."; + std::string name = fmt::format("[{}{}] {} ", prefix, index, geode::cocos::getObjectName(node)); if (node->getTag() != -1) { name += fmt::format("({}) ", node->getTag()); } @@ -36,12 +39,21 @@ bool isNodeParentOf(CCNode* parent, CCNode* child) { return false; } -void DevTools::drawTreeBranch(CCNode* node, size_t index, bool drag, bool visible) { +void DevTools::drawTreeBranch(CCNode* node, size_t index, TreeBranchOptions options) { if (!this->searchBranch(node)) { return; } - visible = node->isVisible() && visible; + if (node->getUserFlag("hide"_spr) && m_settings.hideFlaggedNodes) { + this->drawNodeChildren(node, { + .drag = options.drag, + .visible = options.visible, + .flagHidden = true + }); + return; + } + + options.visible = node->isVisible() && options.visible; auto selected = DevTools::get()->getSelectedNode() == node; @@ -58,7 +70,7 @@ void DevTools::drawTreeBranch(CCNode* node, size_t index, bool drag, bool visibl bool drawSeparator = false; - if (auto dragged = this->getDraggedNode(); dragged && dragged != node && !drag) { + if (auto dragged = this->getDraggedNode(); dragged && dragged != node && !options.drag && !options.fake) { float mouseY = ImGui::GetMousePos().y; float cursorY = ImGui::GetCursorPosY() + ImGui::GetWindowPos().y - ImGui::GetScrollY(); float height = ImGui::GetTextLineHeight(); @@ -109,10 +121,10 @@ void DevTools::drawTreeBranch(CCNode* node, size_t index, bool drag, bool visibl auto alpha = ImGui::GetStyle().DisabledAlpha; ImGui::GetStyle().DisabledAlpha = node->isVisible() ? alpha + 0.15f : alpha; - ImGui::BeginDisabled(!visible); + ImGui::BeginDisabled(!options.visible); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, false); // Bypass iteract blocking in imgui - const auto name = formatNodeName(node, index); + const auto name = formatNodeName(node, index, options.fake, options.flagHidden); // The order here is unusual due to imgui weirdness; see the second-to-last paragraph in https://kahwei.dev/2022/06/20/imgui-tree-node/ bool expanded = ImGui::TreeNodeEx(node, flags, "%s", name.c_str()); float height = ImGui::GetItemRectSize().y; @@ -164,10 +176,13 @@ void DevTools::drawTreeBranch(CCNode* node, size_t index, bool drag, bool visibl if (m_settings.attributesInTree) { this->drawNodeAttributes(node); } - size_t i = 0; - for (auto& child : CCArrayExt(node->getChildren())) { - this->drawTreeBranch(child, i++, drag || isDrag, visible); - } + + this->drawNodeChildren(node, { + .drag = options.drag || isDrag, + .visible = options.visible, + .flagHidden = false + }); + ImGui::TreePop(); } // on leaf nodes expanded is true @@ -176,6 +191,30 @@ void DevTools::drawTreeBranch(CCNode* node, size_t index, bool drag, bool visibl } } +void DevTools::drawNodeChildren(CCNode* node, ParentNodeInformation info) { + size_t i = 0; + for (auto& child : CCArrayExt(node->getChildren())) { + this->drawTreeBranch(child, i++, { + .drag = info.drag, + .visible = info.visible, + .fake = false, + .flagHidden = info.flagHidden + }); + } + + i = 0; + if (auto fakeChildren = typeinfo_cast(node->getUserObject("extra-children"_spr))) { + for (auto& child : CCArrayExt(fakeChildren)) { + this->drawTreeBranch(child, i++, { + .drag = info.drag, + .visible = info.visible, + .fake = true, + .flagHidden = info.flagHidden + }); + } + } +} + void DevTools::drawTree() { #ifdef GEODE_IS_MOBILE ImGui::Dummy({0.f, 60.f}); @@ -191,11 +230,11 @@ void DevTools::drawTree() { m_searchQuery.clear(); } - this->drawTreeBranch(CCDirector::get()->getRunningScene(), 0, false, true); - this->drawTreeBranch(OverlayManager::get(), 1, false, true); + this->drawTreeBranch(CCDirector::get()->getRunningScene(), 0, { .drag = false }); + this->drawTreeBranch(OverlayManager::get(), 1, { .drag = false }); if (auto* dragged = this->getDraggedNode()) { - const auto name = formatNodeName(dragged, 0); + const auto name = formatNodeName(dragged, 0, false, false); auto bgColor = ImGui::GetColorU32(ImGui::GetStyle().Colors[ImGuiCol_Header]); auto textColor = ImGui::GetColorU32(ImGui::GetStyle().Colors[ImGuiCol_Text]);