Skip to content

Commit 9a96ae1

Browse files
authored
Merge pull request #8 from geode-sdk/advanced-settings
Add advanced settings
2 parents 191a86e + 00cc3dd commit 9a96ae1

File tree

6 files changed

+287
-3
lines changed

6 files changed

+287
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Source/Geode/pkg/uber-apk-signer.jar
1010

1111
# ILY vscode
1212
**/.vscode
13+
**/.idea
1314

1415
imgui/**
1516
imgui

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ elseif(ANDROID)
4141
target_link_libraries(${PROJECT_NAME} GLESv2)
4242
endif()
4343

44+
# i still dont like this (alk)
45+
target_compile_definitions(geode-sdk INTERFACE GEODE_EXPOSE_SECRET_INTERNALS_IN_HEADERS_DO_NOT_DEFINE_PLEASE)
46+
4447
# Set up dependencies, resources, link Geode
4548
setup_geode_mod(${PROJECT_NAME})

src/DevTools.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ void DevTools::drawPages() {
6161

6262
ImGui::DockBuilderDockWindow("###devtools/tree", topLeftDock);
6363
ImGui::DockBuilderDockWindow("###devtools/settings", topLeftDock);
64+
ImGui::DockBuilderDockWindow("###devtools/advanced/settings", topLeftDock);
6465
ImGui::DockBuilderDockWindow("###devtools/attributes", bottomLeftTopHalfDock);
6566
ImGui::DockBuilderDockWindow("###devtools/preview", leftDock);
6667
ImGui::DockBuilderDockWindow("###devtools/geometry-dash", id);
68+
ImGui::DockBuilderDockWindow("###devtools/advanced/mod-graph", topLeftDock);
69+
ImGui::DockBuilderDockWindow("###devtools/advanced/mod-index", topLeftDock);
6770

6871
ImGui::DockBuilderFinish(id);
6972
}
@@ -78,6 +81,13 @@ void DevTools::drawPages() {
7881
&DevTools::drawSettings
7982
);
8083

84+
if (m_advancedSettings) {
85+
this->drawPage(
86+
U8STR(FEATHER_SETTINGS " Advanced Settings###devtools/advanced/settings"),
87+
&DevTools::drawAdvancedSettings
88+
);
89+
}
90+
8191
this->drawPage(
8292
U8STR(FEATHER_TOOL " Attributes###devtools/attributes"),
8393
&DevTools::drawAttributes
@@ -87,6 +97,20 @@ void DevTools::drawPages() {
8797
U8STR(FEATHER_DATABASE " Preview###devtools/preview"),
8898
&DevTools::drawPreview
8999
);
100+
101+
if (m_showModGraph) {
102+
this->drawPage(
103+
U8STR(FEATHER_SHARE_2 " Mod Graph###devtools/advanced/mod-graph"),
104+
&DevTools::drawModGraph
105+
);
106+
}
107+
108+
if (m_showModIndex) {
109+
this->drawPage(
110+
U8STR(FEATHER_LIST " Mod Index###devtools/advanced/mod-index"),
111+
&DevTools::drawModIndex
112+
);
113+
}
90114
}
91115

92116
void DevTools::draw(GLRenderCtx* ctx) {

src/DevTools.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cocos2d.h>
77
#include <Geode/utils/cocos.hpp>
88
#include <unordered_map>
9+
#include <Geode/loader/Index.hpp>
910

1011
using namespace geode::prelude;
1112

@@ -25,6 +26,9 @@ class DevTools {
2526
bool m_alwaysHighlight = true;
2627
bool m_shouldRelayout = false;
2728
bool m_highlightLayouts = false;
29+
bool m_advancedSettings = false;
30+
bool m_showModGraph = false;
31+
bool m_showModIndex = false;
2832
bool m_pauseGame = false;
2933
std::string m_theme = DARK_THEME;
3034
ImGuiID m_dockspaceID;
@@ -41,13 +45,19 @@ class DevTools {
4145
void drawTree();
4246
void drawTreeBranch(CCNode* node, size_t index);
4347
void drawSettings();
48+
void drawAdvancedSettings();
4449
void drawNodeAttributes(CCNode* node);
4550
void drawAttributes();
4651
void drawPreview();
4752
void drawNodePreview(CCNode* node);
4853
void drawHighlight(CCNode* node, HighlightMode mode);
4954
void drawLayoutHighlights(CCNode* node);
5055
void drawGD(GLRenderCtx* ctx);
56+
void drawModGraph();
57+
void drawModGraphNode(Mod* node);
58+
ModMetadata inputMetadata(void* treePtr, ModMetadata metadata);
59+
void drawModIndex();
60+
void drawIndexItem(IndexItemHandle const& node);
5161
void drawPage(const char* name, void(DevTools::* fun)());
5262
void drawPages();
5363
void draw(GLRenderCtx* ctx);

src/pages/Advanced.cpp

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
#include "../DevTools.hpp"
2+
#include "../ImGui.hpp"
3+
#include <misc/cpp/imgui_stdlib.h>
4+
#include <Geode/modify/AppDelegate.hpp>
5+
#include <Geode/loader/Index.hpp>
6+
7+
using namespace geode::prelude;
8+
9+
void DevTools::drawAdvancedSettings() {
10+
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 1.f, 1.f });
11+
ImGui::Checkbox("Show Mod Graph", &m_showModGraph);
12+
ImGui::Checkbox("Show Mod Index", &m_showModIndex);
13+
ImGui::PopStyleVar();
14+
}
15+
16+
void DevTools::drawModGraph() {
17+
// TODO: function to get loader mod
18+
this->drawModGraphNode(Mod::get()->getMetadata().getDependencies()[0].mod);
19+
}
20+
21+
namespace {
22+
std::string inputText(const char* label, std::string x) {
23+
ImGui::InputText(label, &x);
24+
return x;
25+
}
26+
std::optional<std::string> inputText(const char* label, std::optional<std::string> x) {
27+
std::string str = x ? *x : "";
28+
return ImGui::InputText(label, &str) ? str : x;
29+
}
30+
std::optional<std::string> inputTextMultiline(const char* label, std::optional<std::string> x) {
31+
std::string str = x ? *x : "";
32+
return ImGui::InputTextMultiline(label, &str) ? str : x;
33+
}
34+
bool inputBool(const char* label, bool x) {
35+
ImGui::Checkbox(label, &x);
36+
return x;
37+
}
38+
39+
VersionInfo inputVersion(VersionInfo version) {
40+
int major = (int)version.getMajor();
41+
int minor = (int)version.getMinor();
42+
int patch = (int)version.getPatch();
43+
std::optional<VersionTag> tag = version.getTag();
44+
ImGui::InputInt("version.major", &major);
45+
ImGui::InputInt("version.minor", &minor);
46+
ImGui::InputInt("version.patch", &patch);
47+
int tagSel = tag ? tag->value + 1 : 0;
48+
ImGui::Combo("version.tag.value", &tagSel, "std::monostate\0Alpha\0Beta\0Prerelease\0\0");
49+
if (tagSel == 0)
50+
tag.reset();
51+
else {
52+
int tagNum = tag && tag->number ? (int)*tag->number : -1;
53+
ImGui::InputInt("version.tag.number", &tagNum);
54+
auto t = (VersionTag::Type)(tagSel - 1);
55+
if (tagNum < 0)
56+
tag = VersionTag(t);
57+
else
58+
tag = VersionTag(t, tagNum);
59+
}
60+
return {(size_t)major, (size_t)minor, (size_t)patch, tag};
61+
}
62+
63+
std::optional<ModMetadata::IssuesInfo> inputIssues(std::optional<ModMetadata::IssuesInfo> x) {
64+
ModMetadata::IssuesInfo a = x ? *x : ModMetadata::IssuesInfo{"", std::nullopt};
65+
std::string url = a.url ? *a.url : "";
66+
bool inputInfo = ImGui::InputText("issues.info", &a.info);
67+
bool inputUrl = ImGui::InputText("issues.url", &url);
68+
if (inputUrl)
69+
a.url = url;
70+
return inputInfo || inputUrl ? a : x;
71+
}
72+
}
73+
74+
ModMetadata DevTools::inputMetadata(void* treePtr, ModMetadata metadata) {
75+
metadata.setVersion(inputVersion(metadata.getVersion()));
76+
metadata.setName(inputText("name", metadata.getName()));
77+
metadata.setDeveloper(inputText("developer", metadata.getDeveloper()));
78+
metadata.setDescription(inputTextMultiline("description", metadata.getDescription()));
79+
metadata.setDetails(inputTextMultiline("details", metadata.getDetails()));
80+
metadata.setChangelog(inputTextMultiline("changelog", metadata.getChangelog()));
81+
metadata.setSupportInfo(inputTextMultiline("supportInfo", metadata.getSupportInfo()));
82+
metadata.setRepository(inputTextMultiline("repository", metadata.getRepository()));
83+
metadata.setIssues(inputIssues(metadata.getIssues()));
84+
metadata.setNeedsEarlyLoad(inputBool("needsEarlyLoad", metadata.needsEarlyLoad()));
85+
metadata.setIsAPI(inputBool("isAPI", metadata.isAPI()));
86+
87+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(treePtr) + 1), "dependencies")) {
88+
for (auto const& item : metadata.getDependencies()) {
89+
if (item.mod) {
90+
if (!ImGui::TreeNode(item.mod, "%s", item.id.c_str()))
91+
continue;
92+
}
93+
else {
94+
if (!ImGui::TreeNode(item.id.data(), "%s", item.id.c_str()))
95+
continue;
96+
}
97+
ImGui::Text("version: %s", item.version.toString().c_str());
98+
const char* importance = "";
99+
switch (item.importance) {
100+
case geode::ModMetadata::Dependency::Importance::Required: importance = "required"; break;
101+
case geode::ModMetadata::Dependency::Importance::Recommended: importance = "recommended"; break;
102+
case geode::ModMetadata::Dependency::Importance::Suggested: importance = "suggested"; break;
103+
}
104+
ImGui::Text("importance: %s", importance);
105+
ImGui::Text("isResolved: %s", item.isResolved() ? "true" : "false");
106+
if (item.mod)
107+
drawModGraphNode(item.mod);
108+
ImGui::TreePop();
109+
}
110+
ImGui::TreePop();
111+
}
112+
113+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(treePtr) + 2), "incompatibilities")) {
114+
for (auto const& item : metadata.getIncompatibilities()) {
115+
if (item.mod) {
116+
if (!ImGui::TreeNode(item.mod, "%s", item.id.c_str()))
117+
continue;
118+
}
119+
else {
120+
if (!ImGui::TreeNode(item.id.data(), "%s", item.id.c_str()))
121+
continue;
122+
}
123+
ImGui::Text("version: %s", item.version.toString().c_str());
124+
const char* importance = "";
125+
switch (item.importance) {
126+
case geode::ModMetadata::Incompatibility::Importance::Breaking: importance = "breaking"; break;
127+
case geode::ModMetadata::Incompatibility::Importance::Conflicting: importance = "conflicting"; break;
128+
}
129+
ImGui::Text("importance: %s", importance);
130+
ImGui::Text("isResolved: %s", item.isResolved() ? "true" : "false");
131+
if (item.mod)
132+
drawModGraphNode(item.mod);
133+
ImGui::TreePop();
134+
}
135+
ImGui::TreePop();
136+
}
137+
138+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(treePtr) + 3), "spritesheets")) {
139+
for (auto const& item : metadata.getSpritesheets()) {
140+
ImGui::Text("%s", item.c_str());
141+
}
142+
ImGui::TreePop();
143+
}
144+
145+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(treePtr) + 4), "settings")) {
146+
for (auto const& [id, setting] : metadata.getSettings()) {
147+
if (!ImGui::TreeNode(id.data(), "%s", id.c_str()))
148+
continue;
149+
ImGui::Text("displayName: %s", setting.getDisplayName().c_str());
150+
if (setting.getDescription())
151+
ImGui::Text("description: %s", setting.getDescription()->c_str());
152+
ImGui::Text("isCustom: %s", setting.isCustom() ? "true" : "false");
153+
ImGui::TreePop();
154+
}
155+
ImGui::TreePop();
156+
}
157+
158+
return metadata;
159+
}
160+
161+
void DevTools::drawModGraphNode(Mod* node) {
162+
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None;
163+
164+
ImColor color = ImColor(1.f, 1.f, 1.f);
165+
if (node->isUninstalled())
166+
color = ImColor(0.1f, 0.1f, 0.1f);
167+
else if (!node->isLoaded())
168+
color = ImColor(1.f, 0.f, 0.f);
169+
else if (!node->isEnabled())
170+
color = ImColor(0.7f, 0.7f, 0.7f);
171+
172+
ImGui::PushStyleColor(ImGuiCol_Text, (ImU32)color);
173+
auto treeNode = ImGui::TreeNodeEx(node, flags, "%s", node->getID().c_str());
174+
ImGui::PopStyleColor();
175+
176+
if (!treeNode)
177+
return;
178+
179+
node->setMetadata(this->inputMetadata(node, node->getMetadata()));
180+
181+
ImGui::Text("supportsDisabling: %s", node->supportsDisabling() ? "true" : "false");
182+
ImGui::Text("early: %s", node->needsEarlyLoad() ? "true" : "false");
183+
ImGui::Text("canEnable: %s", node->canEnable() ? "true" : "false");
184+
ImGui::Text("canDisable: %s", node->canDisable() ? "true" : "false");
185+
ImGui::Text("hasUnresolvedDependencies: %s", node->hasUnresolvedDependencies() ? "true" : "false");
186+
ImGui::Text("hasUnresolvedIncompatibilities: %s", node->hasUnresolvedIncompatibilities() ? "true" : "false");
187+
188+
for (auto& dep : node->getDependants()) {
189+
this->drawModGraphNode(dep);
190+
}
191+
192+
ImGui::TreePop();
193+
}
194+
195+
void DevTools::drawModIndex() {
196+
for (auto const& item : Index::get()->getItems()) {
197+
drawIndexItem(item);
198+
}
199+
}
200+
201+
void DevTools::drawIndexItem(IndexItemHandle const& node) {
202+
auto* item = node.get();
203+
if (!item || !ImGui::TreeNode(item, "%s", item->getMetadata().getID().c_str()))
204+
return;
205+
item->setMetadata(this->inputMetadata(item, item->getMetadata()));
206+
item->setDownloadURL(inputText("downloadURL", item->getDownloadURL()));
207+
item->setPackageHash(inputText("packageHash", item->getPackageHash()));
208+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(item) + 5), "availablePlatforms")) {
209+
auto platforms = item->getAvailablePlatforms();
210+
for (PlatformID::Type type = PlatformID::Type::Unknown; type <= PlatformID::Type::Linux; (*(int*)&type)++) {
211+
bool contains = platforms.contains({type});
212+
if (!ImGui::Checkbox(PlatformID::toString(type), &contains))
213+
continue;
214+
if (contains)
215+
platforms.insert({type});
216+
else
217+
platforms.erase({type});
218+
}
219+
item->setAvailablePlatforms(platforms);
220+
ImGui::TreePop();
221+
}
222+
item->setIsFeatured(inputBool("isFeatured", item->isFeatured()));
223+
if (ImGui::TreeNode(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(item) + 6), "tags")) {
224+
auto tags = item->getTags();
225+
static std::string current;
226+
ImGui::InputText("", &current);
227+
ImGui::SameLine();
228+
if (ImGui::Button("Add")) {
229+
tags.insert(current);
230+
current = "";
231+
}
232+
for (auto const& tag : item->getTags()) {
233+
ImGui::Text("%s", tag.c_str());
234+
ImGui::SameLine();
235+
if (ImGui::Button("Remove"))
236+
tags.erase(tag);
237+
}
238+
item->setTags(tags);
239+
ImGui::TreePop();
240+
}
241+
ImGui::Text("isInstalled: %s", item->isInstalled() ? "true" : "false");
242+
ImGui::TreePop();
243+
}

src/pages/Settings.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
2-
#include "../fonts/FeatherIcons.hpp"
31
#include "../DevTools.hpp"
42
#include <Geode/loader/Loader.hpp>
53
#include <Geode/loader/Mod.hpp>
64
#include <Geode/utils/ranges.hpp>
7-
#include <Geode/binding/GameSoundManager.hpp>
85
#include <Geode/binding/FMODAudioEngine.hpp>
96
#include <Geode/modify/AppDelegate.hpp>
107
#include <fmod.hpp>
@@ -37,6 +34,12 @@ void DevTools::drawSettings() {
3734
"Highlights the borders of all layouts applied to nodes"
3835
);
3936
}
37+
ImGui::Checkbox("Advanced Settings", &m_advancedSettings);
38+
if (ImGui::IsItemHovered()) {
39+
ImGui::SetTooltip(
40+
"Shows advanced settings. Mostly useful only for development of Geode itself."
41+
);
42+
}
4043
ImGui::PopStyleVar();
4144

4245
ImGui::Separator();

0 commit comments

Comments
 (0)