Skip to content

Commit c662d4b

Browse files
authored
Merge branch 'geode-sdk:main' into contribute
2 parents 0c0302b + e3ada8f commit c662d4b

16 files changed

Lines changed: 328 additions & 240 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION 3.21)
2-
set(CMAKE_CXX_STANDARD 20)
2+
set(CMAKE_CXX_STANDARD 23)
33
set(CMAKE_CXX_STANDARD_REQUIRED ON)
44
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS" OR IOS)
55
set(CMAKE_OSX_ARCHITECTURES "arm64")

changelog.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## v1.13.0
2+
* Updated for Geode v5.0.0 and Geometry Dash 2.2081
3+
4+
## v1.12.0
5+
* Add ability to restructure the node tree via drag/drop
6+
* Add more api functions for more advanced UI control
7+
* Visualize node visibility in tree graph (#68)
8+
* Show ImGui cursor when mouse is out of GD window on Windows (#67)
9+
* Improved dragging on mobile (#67)
10+
111
## v1.11.0
212
* Made properties api use drag inputs
313
* Fix waitForDevTools on mods that load before DevTools
@@ -61,4 +71,4 @@ Thanks to <cj>Alphalaneous</c> for doing <co>most of the changes in this update!
6171

6272
* Adds Node IDs into the Attributes menu, along with a button to copy them
6373
* Adds a way to create and modify an AnchorLayout
64-
* Removes the Show Mod Index option in preparation for the new index
74+
* Removes the Show Mod Index option in preparation for the new index

include/API.hpp

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <initializer_list>
88
#include <string>
99
#include <type_traits>
10+
#include <Geode/loader/Dispatch.hpp>
11+
#define MY_MOD_ID "geode.devtools"
1012

1113
namespace devtools {
1214
template <typename T>
@@ -22,36 +24,23 @@ namespace devtools {
2224
std::is_same_v<T, cocos2d::CCSize> ||
2325
std::is_same_v<T, cocos2d::CCRect>;
2426

25-
struct RegisterNodeEvent final : geode::Event {
26-
RegisterNodeEvent(std::function<void(cocos2d::CCNode*)>&& callback)
27-
: callback(std::move(callback)) {}
28-
std::function<void(cocos2d::CCNode*)> callback;
29-
};
30-
3127
template <typename T>
32-
struct PropertyFnEvent final : geode::Event {
33-
PropertyFnEvent() {}
34-
using Fn = bool(const char* name, T&);
35-
Fn* fn = nullptr;
36-
};
28+
concept UnderlyingIntegral = std::is_integral_v<T> || std::is_integral_v<std::underlying_type_t<T>>;
3729

38-
struct DrawLabelFnEvent final : geode::Event {
39-
DrawLabelFnEvent() {}
40-
using Fn = void(const char* text);
41-
Fn* fn = nullptr;
30+
struct RegisterNodeEvent final : geode::Event<RegisterNodeEvent, bool(geode::Function<void(cocos2d::CCNode*)>&)> {
31+
using Event::Event;
4232
};
4333

4434
template <typename T>
45-
struct EnumerableFnEvent final : geode::Event {
46-
EnumerableFnEvent() {}
47-
using Fn = bool(const char* label, T* value, std::span<std::pair<T, const char*> const> items);
48-
Fn* fn = nullptr;
35+
struct PropertyFnEvent final : geode::Event<PropertyFnEvent<T>, bool(bool(*&)(geode::ZStringView name, T&))> {
36+
using Fn = bool(geode::ZStringView name, T&);
37+
using geode::Event<PropertyFnEvent, bool(Fn*&)>::Event;
4938
};
5039

51-
struct ButtonFnEvent final : geode::Event {
52-
ButtonFnEvent() {}
53-
using Fn = bool(const char* label);
54-
Fn* fn = nullptr;
40+
template <typename T>
41+
struct EnumerableFnEvent final : geode::Event<EnumerableFnEvent<T>, bool(bool(*&)(geode::ZStringView label, T* value, std::span<std::pair<T, geode::ZStringView> const>))> {
42+
using Fn = bool(geode::ZStringView label, T* value, std::span<std::pair<T, geode::ZStringView> const>);
43+
using geode::Event<EnumerableFnEvent, bool(Fn*&)>::Event;
5544
};
5645

5746
/// @brief Checks if DevTools is currently loaded.
@@ -60,6 +49,10 @@ namespace devtools {
6049
return geode::Loader::get()->getLoadedMod("geode.devtools") != nullptr;
6150
}
6251

52+
/// @brief Checks if DevTools is currently open.
53+
/// @return True if DevTools is open, false otherwise.
54+
inline bool isOpen() GEODE_EVENT_EXPORT_NORES(&isOpen, ());
55+
6356
/// @brief Waits for DevTools to be loaded and then calls the provided callback.
6457
/// @param callback The function to call once DevTools is loaded.
6558
template <typename F>
@@ -70,12 +63,11 @@ namespace devtools {
7063
auto devtools = geode::Loader::get()->getInstalledMod("geode.devtools");
7164
if (!devtools) return;
7265

73-
new geode::EventListener(
74-
[callback = std::forward<F>(callback)](geode::ModStateEvent*) {
66+
geode::ModStateEvent(geode::ModEventType::Loaded, devtools).listen(
67+
[callback = std::forward<F>(callback)]() {
7568
callback();
76-
},
77-
geode::ModStateFilter(devtools, geode::ModEventType::Loaded)
78-
);
69+
}
70+
).leak();
7971
}
8072
}
8173

@@ -84,11 +76,13 @@ namespace devtools {
8476
/// @see `devtools::property`, `devtools::label`, `devtools::enumerable`, `devtools::button`
8577
template <typename T, std::invocable<std::remove_pointer_t<T>*> F> requires IsCCNode<T>
8678
void registerNode(F&& callback) {
87-
RegisterNodeEvent([callback = std::forward<F>(callback)](cocos2d::CCNode* node) {
79+
geode::Function<void(cocos2d::CCNode*)> func = [callback = std::forward<F>(callback)](cocos2d::CCNode* node) {
8880
if (auto casted = geode::cast::typeinfo_cast<std::remove_pointer_t<T>*>(node)) {
8981
callback(casted);
9082
}
91-
}).post();
83+
};
84+
85+
RegisterNodeEvent().send(func);
9286
}
9387

9488
/// @brief Renders a property editor for the given value in the DevTools UI.
@@ -97,47 +91,40 @@ namespace devtools {
9791
/// @return True if the property was changed, false otherwise.
9892
/// @warning This function should only ever be called from within a registered node callback.
9993
template <typename T> requires SupportedProperty<T>
100-
bool property(const char* name, T& prop) {
94+
bool property(geode::ZStringView name, T& prop) {
10195
static auto fn = ([] {
102-
PropertyFnEvent<T> event;
103-
event.post();
104-
return event.fn;
96+
typename PropertyFnEvent<T>::Fn* fnPtr = nullptr;
97+
PropertyFnEvent<T>().send(fnPtr);
98+
return fnPtr;
10599
})();
106100
return fn ? fn(name, prop) : false;
107101
}
108102

109103
/// @brief Renders a label in the DevTools UI.
110104
/// @param text The text to display in the label.
111105
/// @warning This function should only ever be called from within a registered node callback.
112-
inline void label(const char* text) {
113-
static auto fn = ([] {
114-
DrawLabelFnEvent event;
115-
event.post();
116-
return event.fn;
117-
})();
118-
if (fn) fn(text);
119-
}
106+
inline void label(geode::ZStringView text) GEODE_EVENT_EXPORT_NORES(&label, (text));
120107

121108
/// @brief Renders an enumerable property editor using radio buttons for the given value in the DevTools UI.
122109
/// @param label The label for the enumerable property.
123110
/// @param value The value to edit, which should be an enum or integral type.
124111
/// @param items A list of pairs where each pair contains a value and its corresponding label.
125112
/// @return True if the value was changed, false otherwise.
126113
/// @warning This function should only ever be called from within a registered node callback.
127-
template <typename T> requires std::is_integral_v<std::underlying_type_t<T>>
128-
bool enumerable(const char* label, T& value, std::initializer_list<std::pair<T, const char*>> items) {
114+
template <UnderlyingIntegral T>
115+
bool enumerable(geode::ZStringView label, T& value, std::initializer_list<std::pair<T, geode::ZStringView>> items) {
129116
using ValueType = std::underlying_type_t<T>;
130117
static auto fn = ([] {
131-
EnumerableFnEvent<ValueType> event;
132-
event.post();
133-
return event.fn;
118+
typename EnumerableFnEvent<ValueType>::Fn* fnPtr = nullptr;
119+
EnumerableFnEvent<ValueType>().send(fnPtr);
120+
return fnPtr;
134121
})();
135122
return fn ? fn(
136123
label,
137124
reinterpret_cast<ValueType*>(&value),
138125
std::span(
139-
reinterpret_cast<std::pair<ValueType, const char*> const*>(&*items.begin()),
140-
reinterpret_cast<std::pair<ValueType, const char*> const*>(&*items.end())
126+
reinterpret_cast<std::pair<ValueType, geode::ZStringView> const*>(&*items.begin()),
127+
reinterpret_cast<std::pair<ValueType, geode::ZStringView> const*>(&*items.end())
141128
)
142129
) : false;
143130
}
@@ -146,23 +133,52 @@ namespace devtools {
146133
/// @param label The label for the button.
147134
/// @return True if the button was clicked, false otherwise.
148135
/// @warning This function should only ever be called from within a registered node callback.
149-
inline bool button(const char* label) {
150-
static auto fn = ([] {
151-
ButtonFnEvent event;
152-
event.post();
153-
return event.fn;
154-
})();
155-
return fn ? fn(label) : false;
156-
}
136+
inline bool button(geode::ZStringView label) GEODE_EVENT_EXPORT_NORES(&button, (label));
157137

158138
/// @brief Renders a button in the DevTools UI and calls the provided callback if the button is clicked.
159139
/// @param label The label for the button.
160140
/// @param callback The function to call when the button is clicked.
161141
/// @warning This function should only ever be called from within a registered node callback.
162142
template <typename F>
163-
void button(const char* label, F&& callback) {
143+
void button(geode::ZStringView label, F&& callback) {
164144
if (button(label)) {
165145
callback();
166146
}
167147
}
168-
}
148+
149+
inline void newLine() GEODE_EVENT_EXPORT_NORES(&newLine, ());
150+
inline void sameLine() GEODE_EVENT_EXPORT_NORES(&sameLine, ());
151+
inline void separator() GEODE_EVENT_EXPORT_NORES(&separator, ());
152+
inline void nextItemWidth(float width) GEODE_EVENT_EXPORT_NORES(&nextItemWidth, (width));
153+
inline void indent() GEODE_EVENT_EXPORT_NORES(&indent, ());
154+
inline void unindent() GEODE_EVENT_EXPORT_NORES(&unindent, ());
155+
156+
inline bool combo(
157+
geode::ZStringView label,
158+
int& current,
159+
std::span<char const*> items,
160+
int maxHeight = -1
161+
) GEODE_EVENT_EXPORT_NORES(&combo, (label, current, items, maxHeight));
162+
163+
template <UnderlyingIntegral T, typename R = std::initializer_list<geode::ZStringView>>
164+
requires
165+
std::ranges::range<R> &&
166+
std::same_as<std::remove_pointer_t<decltype(&*std::declval<R>().begin())> const, geode::ZStringView const>
167+
bool combo(geode::ZStringView label, T& current, R&& range, int maxHeight = -1) {
168+
return combo(
169+
label,
170+
reinterpret_cast<int&>(current),
171+
std::span(const_cast<geode::ZStringView*>(&*range.begin()), const_cast<geode::ZStringView*>(&*range.end())),
172+
maxHeight
173+
);
174+
}
175+
176+
inline bool radio(geode::ZStringView label, int& current, int num) GEODE_EVENT_EXPORT_NORES(&radio, (label, current, num));
177+
178+
template <UnderlyingIntegral T, UnderlyingIntegral U>
179+
bool radio(geode::ZStringView label, T& current, U value) {
180+
return radio(label, reinterpret_cast<int&>(current), reinterpret_cast<int&>(value));
181+
}
182+
183+
inline void inputMultiline(geode::ZStringView label, std::string& text) GEODE_EVENT_EXPORT_NORES(&inputMultiline, (label, text));
184+
}

mod.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"geode": "4.9.0",
3-
"version": "v1.11.0",
2+
"geode": "5.0.1",
3+
"version": "v1.13.1",
44
"gd": {
5-
"win": "2.2074",
6-
"android": "*",
7-
"mac": "2.2074",
8-
"ios": "2.2074"
5+
"win": "2.2081",
6+
"android": "2.2081",
7+
"mac": "2.2081",
8+
"ios": "2.2081"
99
},
1010
"id": "geode.devtools",
1111
"name": "DevTools",

0 commit comments

Comments
 (0)