Merge branch 'main' into new-index-but-better

This commit is contained in:
HJfod 2024-02-25 18:44:36 +02:00
commit 44ae5c83c7
80 changed files with 558 additions and 131 deletions
CHANGELOG.mdCMakeLists.txtVERSION
cmake
loader
include/Geode
resources/blanks
src
test

View file

@ -1,5 +1,21 @@
# Geode Changelog
## v2.0.0-beta.21
* Fix `numFromString` for floating point numbers (6d91804)
* Fix `ScrollLayer` cropping (5c8ee29)
* Show featured mods on top (4e06c20)
* Don't require admin for installer (5f8dc3a)
* Add `char const*` and `std::string` overloads for `gd::string` (982e8ab, a19d26d)
* Remove dithering from some textures (b9a76b3, 76a615c)
* Replace node attributes with id based user objects (363a028)
* Add FMOD initialization check for Android (0623563)
* Remove deprecated values from `Permissions` (b082dd1)
* Add a progress percentage to index unzipping (baf3a6b)
* Fix `pushNest/popNest` not doing correct indent value (c7a1f76)
* Optimize `DispatchEvent` to use their own pools, greatly increasing performance (d8ac85b)
* Check for presence of children in `handleTouchPriority` (28bd757)
* Fix floating point returns for optcall/membercall functions (dba5b01)
## v2.0.0-beta.20
* Enable PCH on Mac for better compile times (dd62eac)
* Add `numFromString` utility for safely parsing numbers (c4e9c17)

View file

@ -192,10 +192,10 @@ if (WIN32)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
# target x86 on windows with clang
target_compile_options(${PROJECT_NAME} INTERFACE --target=i686-windows-msvc)
target_link_options(${PROJECT_NAME} INTERFACE --target=i686-windows-msvc)
add_compile_options(--target=i686-windows-msvc)
add_link_options(--target=i686-windows-msvc)
target_compile_options(${PROJECT_NAME} INTERFACE --target=i686-pc-windows-msvc)
target_link_options(${PROJECT_NAME} INTERFACE --target=i686-pc-windows-msvc)
add_compile_options(--target=i686-pc-windows-msvc)
add_link_options(--target=i686-pc-windows-msvc)
endif()
endif()
@ -231,7 +231,7 @@ if (DEFINED GEODE_TULIPHOOK_REPO_PATH)
message(STATUS "Using ${GEODE_TULIPHOOK_REPO_PATH} for TulipHook")
add_subdirectory(${GEODE_TULIPHOOK_REPO_PATH} ${GEODE_TULIPHOOK_REPO_PATH}/build)
else()
CPMAddPackage("gh:geode-sdk/TulipHook#9dc223d")
CPMAddPackage("gh:geode-sdk/TulipHook#047031e")
endif()
set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE)

View file

@ -1 +1 @@
2.0.0-beta.20
2.0.0-beta.21

View file

@ -75,6 +75,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android32")
)
target_link_libraries(${PROJECT_NAME} INTERFACE
c
${GEODE_LOADER_PATH}/include/link/android32/libcurl.a
${GEODE_LOADER_PATH}/include/link/android32/libssl.a
${GEODE_LOADER_PATH}/include/link/android32/libcrypto.a
@ -93,6 +94,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android64")
)
target_link_libraries(${PROJECT_NAME} INTERFACE
c
${GEODE_LOADER_PATH}/include/link/android64/libcurl.a
${GEODE_LOADER_PATH}/include/link/android64/libssl.a
${GEODE_LOADER_PATH}/include/link/android64/libcrypto.a

View file

@ -868,7 +868,17 @@ private:
geode::EventListenerProtocol* protocol
);
#ifdef GEODE_EXPORTING
[[deprecated("Will be removed, it's an ABI break")]]
GEODE_DLL std::optional<matjson::Value> getAttributeInternal(std::string const& attribute);
#endif
public:
#ifdef GEODE_EXPORTING
[[deprecated("Will be removed, it's an ABI break")]]
GEODE_DLL void setAttribute(std::string const& attribute, matjson::Value const& value);
#endif
/**
* Get the string ID of this node
* @returns The ID, or an empty string if the node has no ID.

View file

@ -9,6 +9,8 @@
namespace geode {
// Mod interoperability
GEODE_DLL std::unordered_map<std::string, EventListenerPool*>& dispatchPools();
template <class... Args>
class DispatchEvent : public Event {
protected:
@ -26,6 +28,13 @@ namespace geode {
std::string getID() const {
return m_id;
}
EventListenerPool* getPool() const override {
if (dispatchPools().count(m_id) == 0) {
dispatchPools()[m_id] = new DefaultEventListenerPool();
}
return dispatchPools()[m_id];
}
};
template <class... Args>
@ -37,6 +46,13 @@ namespace geode {
using Ev = DispatchEvent<Args...>;
using Callback = ListenerResult(Args...);
EventListenerPool* getPool() const {
if (dispatchPools().count(m_id) == 0) {
dispatchPools()[m_id] = new DefaultEventListenerPool();
}
return dispatchPools()[m_id];
}
ListenerResult handle(utils::MiniFunction<Callback> fn, Ev* event) {
if (event->getID() == m_id) {
return std::apply(fn, event->getArgs());

View file

@ -109,8 +109,16 @@ namespace geode {
logImpl(Severity::Error, getMod(), str, std::forward<Args>(args)...);
}
GEODE_DLL void pushNest();
GEODE_DLL void popNest();
GEODE_DLL void pushNest(Mod* mod);
GEODE_DLL void popNest(Mod* mod);
inline void pushNest() {
pushNest(getMod());
}
inline void popNest() {
popNest(getMod());
}
class Nest final {
private:

View file

@ -1,5 +0,0 @@
#include "Mod.hpp"
#include <matjson.hpp>
namespace geode {}

View file

@ -288,6 +288,19 @@ namespace geode {
static T get(SettingValue* setting);
static void set(SettingValue* setting, T const& value);
};
template<class T>
bool GeodeSettingValue<T>::load(matjson::Value const& json) {
if (!json.is<ValueType>()) return false;
m_value = json.as<ValueType>();
return true;
}
template<class T>
bool GeodeSettingValue<T>::save(matjson::Value& json) const {
json = m_value;
return true;
}
}
#pragma warning(pop)

View file

@ -1,17 +0,0 @@
#include "Setting.hpp"
#include <matjson.hpp>
namespace geode {
template<class T>
bool GeodeSettingValue<T>::load(matjson::Value const& json) {
if (!json.is<ValueType>()) return false;
m_value = json.as<ValueType>();
return true;
}
template<class T>
bool GeodeSettingValue<T>::save(matjson::Value& json) const {
json = m_value;
return true;
}
}

View file

@ -1,11 +0,0 @@
#pragma once
#include <Geode/utils/Result.hpp>
#include <tulip/TulipHook.hpp>
namespace geode::modifier {
// template <uint32_t Id>
// GEODE_HIDDEN uintptr_t address();
// Result<tulip::hook::HandlerMetadata> handlerMetadataForAddress(uintptr_t address);
}

View file

@ -1,8 +0,0 @@
#pragma once
#include <Geode/Bindings.hpp>
namespace geode::modifier {
// struct types {
// #include <Geode/GeneratedType.hpp>
// };
}

View file

@ -154,6 +154,16 @@ namespace geode::utils::file {
*/
static Result<Unzip> create(ByteVector const& data);
/**
* Set a callback to be called with the progress of the unzip operation, first
* argument is the current entry, second argument is the total entries
* @note This is not thread-safe
* @param callback Callback to call with the progress of the unzip operation
*/
void setProgressCallback(
utils::MiniFunction<void(uint32_t, uint32_t)> callback
);
/**
* Path to the opened zip
* @returns The path to the zip that is being read, or an empty path
@ -200,6 +210,13 @@ namespace geode::utils::file {
Path const& to,
bool deleteZipAfter = false
);
static Result<> intoDir(
utils::MiniFunction<void(uint32_t, uint32_t)> progressCallback,
Path const& from,
Path const& to,
bool deleteZipAfter = false
);
};
/**

View file

@ -6,11 +6,8 @@
namespace geode::utils::permission {
enum class Permission {
ReadAudio [[deprecated("This permission is Android 13+ specific! Use ReadFiles instead.")]],
ReadImages [[deprecated("This permission is Android 13+ specific! Use ReadFiles instead.")]],
ReadVideo [[deprecated("This permission is Android 13+ specific! Use ReadFiles instead.")]],
ReadAllFiles,
RecordAudio,
ReadAllFiles = 0x3, // maintain compatibility with some older mods
RecordAudio
};
/**

Binary file not shown.

Before

(image error) Size: 26 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 45 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 44 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 34 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 25 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 45 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 57 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 71 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 42 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 40 KiB

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 31 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 36 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 29 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 30 KiB

After

(image error) Size: 9.8 KiB

Binary file not shown.

Before

(image error) Size: 29 KiB

After

(image error) Size: 9.8 KiB

Binary file not shown.

Before

(image error) Size: 39 KiB

After

(image error) Size: 9.7 KiB

Binary file not shown.

Before

(image error) Size: 30 KiB

After

(image error) Size: 9.7 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

After

(image error) Size: 10 KiB

Binary file not shown.

Before

(image error) Size: 28 KiB

After

(image error) Size: 8.9 KiB

Binary file not shown.

Before

(image error) Size: 33 KiB

After

(image error) Size: 9 KiB

Binary file not shown.

Before

(image error) Size: 22 KiB

After

(image error) Size: 8.7 KiB

Binary file not shown.

Before

(image error) Size: 34 KiB

After

(image error) Size: 8.8 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

After

(image error) Size: 9 KiB

Binary file not shown.

Before

(image error) Size: 27 KiB

After

(image error) Size: 8.1 KiB

Binary file not shown.

Before

(image error) Size: 24 KiB

After

(image error) Size: 8.1 KiB

Binary file not shown.

Before

(image error) Size: 30 KiB

After

(image error) Size: 7.9 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

After

(image error) Size: 8 KiB

Binary file not shown.

Before

(image error) Size: 26 KiB

After

(image error) Size: 8.2 KiB

Binary file not shown.

Before

(image error) Size: 23 KiB

After

(image error) Size: 5.3 KiB

Binary file not shown.

Before

(image error) Size: 24 KiB

After

(image error) Size: 5.3 KiB

Binary file not shown.

Before

(image error) Size: 20 KiB

After

(image error) Size: 5.2 KiB

Binary file not shown.

Before

(image error) Size: 25 KiB

After

(image error) Size: 5.3 KiB

Binary file not shown.

Before

(image error) Size: 22 KiB

After

(image error) Size: 5.3 KiB

View file

@ -0,0 +1,27 @@
<svg width="216" height="226" viewBox="0 0 216 226" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_732_175)">
<circle cx="108" cy="113" r="103" fill="white"/>
</g>
<circle cx="108" cy="113" r="95" fill="black"/>
<circle cx="108" cy="113" r="86" fill="url(#paint0_linear_732_175)"/>
<path d="M108 199C155.496 199 194 160.496 194 113H22C22 160.496 60.5035 199 108 199Z" fill="url(#paint1_linear_732_175)"/>
<defs>
<filter id="filter0_d_732_175" x="5" y="10" width="210.1" height="213" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4.1" dy="7"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_732_175"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_732_175" result="shape"/>
</filter>
<linearGradient id="paint0_linear_732_175" x1="22" y1="199" x2="194" y2="199" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_732_175" x1="22" y1="113.348" x2="194" y2="113.348" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="225" height="243" viewBox="0 0 225 243" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_732_207)">
<circle cx="112" cy="120" r="102" fill="white"/>
</g>
<circle cx="112" cy="120" r="93.5" fill="black"/>
<circle cx="112" cy="120" r="85.5" fill="url(#paint0_linear_732_207)"/>
<path d="M112 205.5C159.22 205.5 197.5 167.22 197.5 120H26.5C26.5 167.22 64.7797 205.5 112 205.5Z" fill="url(#paint1_linear_732_207)"/>
<defs>
<filter id="filter0_d_732_207" x="10" y="18" width="211" height="218" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="7" dy="14"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_732_207"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_732_207" result="shape"/>
</filter>
<linearGradient id="paint0_linear_732_207" x1="26.5" y1="205.5" x2="197.5" y2="205.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_732_207" x1="26.5" y1="120.346" x2="197.5" y2="120.346" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="321" height="333" viewBox="0 0 321 333" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_727_17)">
<circle cx="160.5" cy="163.5" r="148.5" fill="white"/>
</g>
<circle cx="160.5" cy="163.5" r="137" fill="black"/>
<circle cx="160.5" cy="163.5" r="124" fill="url(#paint0_linear_727_17)"/>
<path d="M160.5 287.5C228.983 287.5 284.5 231.983 284.5 163.5H36.5C36.5 231.983 92.0167 287.5 160.5 287.5Z" fill="url(#paint1_linear_727_17)"/>
<defs>
<filter id="filter0_d_727_17" x="12" y="15" width="304.905" height="310.834" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="7.90537" dy="13.8344"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_727_17"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_727_17" result="shape"/>
</filter>
<linearGradient id="paint0_linear_727_17" x1="36.5" y1="287.5" x2="284.5" y2="287.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_727_17" x1="36.5" y1="164.002" x2="284.5" y2="164.002" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="187" height="196" viewBox="0 0 187 196" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_910_101)">
<ellipse cx="93.5" cy="98" rx="87.5" ry="87" fill="white"/>
</g>
<ellipse cx="93.5" cy="98" rx="80.5" ry="81" fill="black"/>
<circle cx="93.5" cy="98" r="73" fill="url(#paint0_linear_910_101)"/>
<path d="M93.5 171C133.817 171 166.5 138.317 166.5 98H20.5C20.5 138.317 53.1832 171 93.5 171Z" fill="url(#paint1_linear_910_101)"/>
<defs>
<filter id="filter0_d_910_101" x="6" y="11" width="178.556" height="182" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="3.55575" dy="8"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_910_101"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_910_101" result="shape"/>
</filter>
<linearGradient id="paint0_linear_910_101" x1="20.5" y1="171" x2="166.5" y2="171" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_910_101" x1="20.5" y1="98.2955" x2="166.5" y2="98.2955" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="210" height="228" viewBox="0 0 210 228" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_910_124)">
<ellipse cx="105" cy="113.5" rx="94" ry="93.5" fill="white"/>
</g>
<circle cx="105" cy="113.5" r="86" fill="black"/>
<circle cx="105" cy="113.5" r="78.5" fill="url(#paint0_linear_910_124)"/>
<path d="M105 192C148.354 192 183.5 156.854 183.5 113.5H26.5C26.5 156.854 61.6456 192 105 192Z" fill="url(#paint1_linear_910_124)"/>
<defs>
<filter id="filter0_d_910_124" x="11" y="20" width="195" height="202" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="7" dy="15"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_910_124"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_910_124" result="shape"/>
</filter>
<linearGradient id="paint0_linear_910_124" x1="26.5" y1="192" x2="183.5" y2="192" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_910_124" x1="26.5" y1="113.818" x2="183.5" y2="113.818" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="154" height="164" viewBox="0 0 154 164" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_910_130)">
<circle cx="77" cy="82" r="71.9497" fill="white"/>
</g>
<circle cx="77.0001" cy="82" r="66.3614" fill="black"/>
<circle cx="77" cy="82" r="60" fill="url(#paint0_linear_910_130)"/>
<path d="M77 142C110.137 142 137 115.137 137 82H17C17 115.137 43.8629 142 77 142Z" fill="url(#paint1_linear_910_130)"/>
<defs>
<filter id="filter0_d_910_130" x="5.05029" y="10.0503" width="147.899" height="150.899" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4" dy="7"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_910_130"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_910_130" result="shape"/>
</filter>
<linearGradient id="paint0_linear_910_130" x1="17" y1="142" x2="137" y2="142" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_910_130" x1="17" y1="82.2429" x2="137" y2="82.2429" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,27 @@
<svg width="166" height="176" viewBox="0 0 166 176" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_911_204)">
<ellipse cx="83.0529" cy="87.614" rx="78.1505" ry="77.7348" fill="white"/>
</g>
<circle cx="83.0526" cy="87.614" r="71.4994" fill="black"/>
<circle cx="83" cy="87.614" r="64" fill="url(#paint0_linear_911_204)"/>
<path d="M83 151.614C118.346 151.614 147 122.96 147 87.614H19C19 122.96 47.6538 151.614 83 151.614Z" fill="url(#paint1_linear_911_204)"/>
<defs>
<filter id="filter0_d_911_204" x="4.90234" y="9.87921" width="160.301" height="163.47" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4" dy="8"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_911_204"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_911_204" result="shape"/>
</filter>
<linearGradient id="paint0_linear_911_204" x1="19" y1="151.614" x2="147" y2="151.614" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_911_204" x1="19" y1="87.8731" x2="147" y2="87.8731" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.6 KiB

View file

@ -0,0 +1,27 @@
<svg width="106" height="116" viewBox="0 0 106 116" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_911_217)">
<ellipse cx="52.7393" cy="57.7456" rx="48.4141" ry="48.1565" fill="white"/>
</g>
<circle cx="52.7395" cy="57.7456" r="44.2937" fill="black"/>
<circle cx="52.7393" cy="57.7456" r="39.5" fill="url(#paint0_linear_911_217)"/>
<path d="M52.7393 97.2456C74.5545 97.2456 92.2393 79.5609 92.2393 57.7456H13.2393C13.2393 79.5609 30.924 97.2456 52.7393 97.2456Z" fill="url(#paint1_linear_911_217)"/>
<defs>
<filter id="filter0_d_911_217" x="4.3252" y="9.58908" width="100.828" height="103.313" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="4" dy="7"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_911_217"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_911_217" result="shape"/>
</filter>
<linearGradient id="paint0_linear_911_217" x1="13.2393" y1="97.2456" x2="92.2393" y2="97.2456" gradientUnits="userSpaceOnUse">
<stop stop-color="#D6FF5A"/>
<stop offset="1" stop-color="#66CC11"/>
</linearGradient>
<linearGradient id="paint1_linear_911_217" x1="13.2393" y1="57.9055" x2="92.2393" y2="57.9055" gradientUnits="userSpaceOnUse">
<stop stop-color="#90FF44"/>
<stop offset="1" stop-color="#449906"/>
</linearGradient>
</defs>
</svg>

After

(image error) Size: 1.6 KiB

View file

@ -0,0 +1,42 @@
import subprocess
# you must run this in the same directory as the script!
# and also you must have rsvg-convert
# on ubuntu you can get this with `apt install librsvg2-bin`
sizes = [
"Large",
"Big",
"BigAlt",
"Medium",
"MediumAlt",
"Small",
"SmallAlt",
"Tiny",
]
# the green gradient colors we are replacing in the base svgs
color_from = ["#D6FF5A", "#66CC11", "#90FF44", "#449906"]
# each pair of colors represents a gradient,
# first pair is for the top part of the button,
# second pair is for the bottom.
colors = {
"Green": ["#D6FF5A", "#66CC11", "#90FF44", "#449906"],
"Pink": ["#FACCFC", "#FF71FF", "#FBB1FF", "#FB58FF"],
"Cyan": ["#58FDFA", "#13D5EA", "#44F9F6", "#0B9FBE"],
"Blue": ["#1AF1F8", "#0AB4FF", "#23DCFA", "#0077FA"],
"Gray": ["#DEDEE0", "#979997", "#CACCCA", "#747472"],
# "DarkPurple": ["#41384b", "#2f2937", "#393142", "#221e28"],
}
for size in sizes:
with open(f"baseCircle_{size}.svg", "r") as file:
svg_base = file.read()
for name, cols in colors.items():
svg = svg_base
out = f"../baseCircle_{size}_{name.title()}.png"
print(f"Generating {out}")
for color_orig, color_to in zip(color_from, cols):
svg = svg.replace(color_orig, color_to)
subprocess.run(["rsvg-convert", "-o", out], input=svg.encode())

View file

@ -0,0 +1,67 @@
#include <Geode/Geode.hpp>
#ifdef GEODE_IS_ANDROID
using namespace geode::prelude;
auto g_systemInitialized = false;
FMOD_RESULT FMOD_System_init_hook(
FMOD::System* system, int maxChannels, FMOD_INITFLAGS flags, void* extraData
) {
g_systemInitialized = true;
return system->init(maxChannels, flags, extraData);
}
FMOD_RESULT FMOD_ChannelControl_setVolume_hook(FMOD::ChannelControl* channel, float volume) {
if (!g_systemInitialized) {
return FMOD_ERR_UNINITIALIZED;
}
return channel->setVolume(volume);
}
$execute {
// Workaround for a bug where FMOD::ChannelControl::setVolume is called with
// uninitialized (invalid) channel pointers from FMODAudioEngine.
// This creates a very annoying crash during load in some cases.
(void)geode::Mod::get()->hook(
reinterpret_cast<void*>(geode::addresser::getNonVirtual(&FMOD::System::init)),
&FMOD_System_init_hook,
"FMOD::System::init"
);
(void)geode::Mod::get()->hook(
reinterpret_cast<void*>(geode::addresser::getNonVirtual(&FMOD::ChannelControl::setVolume)),
&FMOD_ChannelControl_setVolume_hook,
"FMOD::ChannelControl::setVolume"
);
}
/*
// this hook requires a tuliphook update
// (setEffectsVolume is too small to hook, so it overwrites the stopAllMusic call below it)
#include <Geode/modify/FMODAudioEngine.hpp>
struct AndroidFMODFix : Modify<AndroidFMODFix, FMODAudioEngine> {
void setEffectsVolume(float volume) {
if (this->m_system == nullptr) [[unlikely]] {
return;
}
FMODAudioEngine::setEffectsVolume(volume);
}
void setBackgroundMusicVolume(float volume) {
if (this->m_system == nullptr) [[unlikely]] {
return;
}
FMODAudioEngine::setBackgroundMusicVolume(volume);
}
};
*/
#endif

View file

@ -285,4 +285,13 @@ void CCNode::updateAnchoredPosition(Anchor anchor, CCPoint const& offset, CCPoin
}
}
#ifdef GEODE_EXPORTING
void CCNode::setAttribute(std::string const& attr, matjson::Value const& value) {}
std::optional<matjson::Value> CCNode::getAttributeInternal(std::string const& attr) {
return std::nullopt;
}
#endif
#pragma warning(pop)

View file

@ -8,7 +8,6 @@
#include <Geode/loader/Log.hpp>
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/SettingEvent.hpp>
#include <Geode/loader/ModJsonTest.hpp>
#include <Geode/utils/JsonValidation.hpp>
#include <loader/LogImpl.hpp>

View file

@ -0,0 +1,8 @@
#include <Geode/loader/Dispatch.hpp>
using namespace geode::prelude;
std::unordered_map<std::string, EventListenerPool*>& geode::dispatchPools() {
static std::unordered_map<std::string, EventListenerPool*> pools;
return pools;
}

View file

@ -337,9 +337,20 @@ void Index::Impl::downloadIndex(std::string commitHash) {
// unzip new index
log::debug("Unzipping index");
IndexUpdateEvent(UpdateProgress(100, "Unzipping index")).post();
auto unzip = file::Unzip::intoDir(targetFile, targetDir, true)
.expect("Unable to unzip new index");
uint32_t nextPercent = 1;
auto unzip = file::Unzip::intoDir(
[&](uint32_t current, uint32_t total) {
if (total == 0) return;
if (static_cast<float>(current) / total * 100 >= nextPercent) {
Loader::get()->queueInMainThread([nextPercent]() {
IndexUpdateEvent(UpdateProgress(nextPercent, "Extracting")).post();
});
nextPercent++;
}
},
targetFile, targetDir, true
).expect("Unable to unzip new index");
if (!unzip) {
auto const err = unzip.unwrapErr();
log::error("Failed to unzip latest index: {}", err);

View file

@ -255,14 +255,16 @@ std::string geode::log::generateLogName() {
return fmt::format("Geode {:%F %H.%M.%S}.log", convertTime(log_clock::now()));
}
void log::pushNest() {
void log::pushNest(Mod* mod) {
if (s_nestLevel == 0)
s_nestCountOffset = static_cast<int32_t>(Mod::get()->getName().size() + thread::getName().size());
s_nestCountOffset = static_cast<int32_t>(mod->getName().size() + thread::getName().size());
s_nestLevel++;
}
void log::popNest() {
void log::popNest(Mod* mod) {
s_nestLevel--;
if (s_nestLevel == 0)
s_nestCountOffset = 0;
}
std::shared_ptr<Nest> log::saveNest() {

View file

@ -4,7 +4,6 @@
#include <Geode/loader/Setting.hpp>
#include <Geode/loader/SettingEvent.hpp>
#include <Geode/loader/SettingNode.hpp>
#include <Geode/loader/SettingJsonTest.hpp>
#include <Geode/utils/general.hpp>
#include <Geode/utils/JsonValidation.hpp>
#include <re2/re2.h>

View file

@ -321,9 +321,6 @@ static const char* permissionToName(Permission permission) {
#define PERM(x) "android.permission." x
#define INTERNAL_PERM(x) "geode.permission_internal." x
switch (permission) {
case Permission::ReadAudio: return PERM("READ_MEDIA_AUDIO");
case Permission::ReadImages: return PERM("READ_MEDIA_IMAGES");
case Permission::ReadVideo: return PERM("READ_MEDIA_VIDEO");
case Permission::RecordAudio: return PERM("RECORD_AUDIO");
case Permission::ReadAllFiles: return INTERNAL_PERM("MANAGE_ALL_FILES");
}

View file

@ -628,7 +628,7 @@ void ModListLayer::onIndexUpdate(IndexUpdateEvent* event) {
[&](UpdateProgress const& prog) {
auto msg = prog.second;
// amazing
if (prog.second == "Downloading") {
if (prog.second == "Downloading" || prog.second == "Extracting") {
msg += fmt::format(" {}%", prog.first);
}
m_listLabel->setString((msg + "...").c_str());

View file

@ -1,5 +1,6 @@
#include "ModsLayer.hpp"
#include "SwelvyBG.hpp"
#include <Geode/ui/TextInput.hpp>
static bool BIG_VIEW = false;
@ -58,9 +59,20 @@ bool ModList::init(ModListSource* src, CCSize const& size) {
);
this->addChildAtPosition(pageRightMenu, Anchor::Right, ccp(5, 0));
auto pageLabelMenu = CCMenu::create();
pageLabelMenu->setContentWidth(30.f);
pageLabelMenu->setAnchorPoint({ .5f, 1.f });
m_pageLabel = CCLabelBMFont::create("", "bigFont.fnt");
m_pageLabel->setAnchorPoint({ .5f, 1.f });
this->addChildAtPosition(m_pageLabel, Anchor::Bottom, ccp(0, -5));
m_pageLabelBtn = CCMenuItemSpriteExtra::create(
m_pageLabel, this, menu_selector(ModList::onGoToPage)
);
pageLabelMenu->addChild(m_pageLabelBtn);
pageLabelMenu->setLayout(RowLayout::create());
this->addChildAtPosition(pageLabelMenu, Anchor::Bottom, ccp(0, -5));
m_statusText = SimpleTextArea::create("", "bigFont.fnt", .6f);
m_statusText->setAlignment(kCCTextAlignmentCenter);
@ -114,6 +126,14 @@ void ModList::onPromise(PromiseEvent<typename ModListSource::Page>* event) {
}
}
void ModList::onGoToPage(CCObject*) {
auto popup = SetTextPopup::create("", "Page", 5, "Go to Page", "OK", true, 60.f);
popup->m_delegate = this;
popup->m_input->m_allowedChars = getCommonFilterAllowedChars(CommonFilter::Uint);
popup->setID("go-to-page"_spr);
popup->show();
}
void ModList::onPage(CCObject* sender) {
// If no page count has been loaded yet, we can't do anything
if (!m_source->getPageCount()) return;
@ -148,7 +168,7 @@ void ModList::updatePageUI(bool hide) {
}
m_pagePrevBtn->setVisible(!hide && m_page > 0);
m_pageNextBtn->setVisible(!hide && m_page < pageCount.value() - 1);
m_pageLabel->setVisible(!hide);
m_pageLabelBtn->setVisible(!hide);
if (pageCount > 0u) {
auto fmt = fmt::format("Page {}/{}", m_page + 1, pageCount.value());
m_pageLabel->setString(fmt.c_str());
@ -156,6 +176,14 @@ void ModList::updatePageUI(bool hide) {
}
}
void ModList::setTextPopupClosed(SetTextPopup* popup, gd::string value) {
if (popup->getID() == "go-to-page"_spr) {
if (auto num = numFromString<size_t>(value)) {
this->gotoPage(num.unwrap());
}
}
}
void ModList::reloadPage() {
// Just force an update on the current page
this->gotoPage(m_page, true);

View file

@ -8,7 +8,7 @@
using namespace geode::prelude;
class ModList : public CCNode {
class ModList : public CCNode, public SetTextPopupDelegate {
protected:
ModListSource* m_source;
size_t m_page = 0;
@ -18,12 +18,16 @@ protected:
ModListSource::PageLoadEventListener m_listener;
CCMenuItemSpriteExtra* m_pagePrevBtn;
CCMenuItemSpriteExtra* m_pageNextBtn;
CCMenuItemSpriteExtra* m_pageLabelBtn;
CCLabelBMFont* m_pageLabel;
bool init(ModListSource* src, CCSize const& size);
void onPromise(PromiseEvent<ModListSource::Page>* event);
void onPage(CCObject*);
void onGoToPage(CCObject*);
void setTextPopupClosed(SetTextPopup*, gd::string value) override;
void updatePageUI(bool hide = false);

View file

@ -463,6 +463,9 @@ void geode::cocos::reloadTextures(CreateLayerFunc returnTo) {
}
void GEODE_DLL geode::cocos::handleTouchPriorityWith(cocos2d::CCNode* node, int priority, bool force) {
if (node == nullptr) return;
if (node->getChildrenCount() == 0) return;
for (auto child : CCArrayExt<CCNode*>(node->getChildren())) {
if (auto delegate = typeinfo_cast<CCTouchDelegate*>(child)) {
if (auto handler = CCTouchDispatcher::get()->findHandler(delegate)) {

View file

@ -170,6 +170,7 @@ private:
int32_t m_mode;
std::variant<Path, ByteVector> m_srcDest;
std::unordered_map<Path, ZipEntry> m_entries;
utils::MiniFunction<void(uint32_t, uint32_t)> m_progressCallback;
Result<> init() {
// open stream from file
@ -281,6 +282,10 @@ public:
return Ok(std::move(ret));
}
void setProgressCallback(utils::MiniFunction<void(uint32_t, uint32_t)> callback) {
m_progressCallback = callback;
}
Result<> extractAt(Path const& dir, Path const& name) {
auto entry = m_entries.at(name);
@ -318,12 +323,21 @@ public:
.expect("Unable to navigate to first entry (code {error})")
);
uint64_t numEntries;
GEODE_UNWRAP(
mzTry(mz_zip_get_number_entry(m_handle, &numEntries))
.expect("Unable to get number of entries (code {error})")
);
uint32_t currentEntry = 0;
// while not at MZ_END_OF_LIST
do {
mz_zip_file* info = nullptr;
if (mz_zip_entry_get_info(m_handle, &info) != MZ_OK) {
return Err("Unable to get entry info");
}
currentEntry++;
Path filePath;
filePath.assign(info->filename, info->filename + info->filename_size);
@ -341,6 +355,7 @@ public:
else {
GEODE_UNWRAP(this->extractAt(dir, filePath));
}
m_progressCallback(currentEntry, numEntries);
}
else {
log::error(
@ -505,6 +520,12 @@ Unzip::Path Unzip::getPath() const {
return m_impl->getPath();
}
void Unzip::setProgressCallback(
utils::MiniFunction<void(uint32_t, uint32_t)> callback
) {
return m_impl->setProgressCallback(callback);
}
std::vector<Unzip::Path> Unzip::getEntries() const {
return map::keys(m_impl->getEntries());
}
@ -550,6 +571,22 @@ Result<> Unzip::intoDir(
return Ok();
}
Result<> Unzip::intoDir(
utils::MiniFunction<void(uint32_t, uint32_t)> progressCallback,
Path const& from,
Path const& to,
bool deleteZipAfter
) {
GEODE_UNWRAP_INTO(auto unzip, Unzip::create(from));
unzip.setProgressCallback(progressCallback);
GEODE_UNWRAP(unzip.extractAllTo(to));
if (deleteZipAfter) {
std::error_code ec;
ghc::filesystem::remove(from, ec);
}
return Ok();
}
// Zip
Zip::Zip() : m_impl(nullptr) {}

View file

@ -1,9 +1,8 @@
#include <Geode/Loader.hpp>
#include <Geode/modify/MenuLayer.hpp>
#include <Geode/loader/SettingNode.hpp>
#include <Geode/loader/ModJsonTest.hpp>
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
#include <Geode/binding/FLAlertLayer.hpp>
#include <Geode/loader/Dispatch.hpp>
#include <Geode/Bindings.hpp>
#include "main.hpp"
using namespace geode::prelude;
@ -164,11 +163,12 @@ struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
$on_mod(Loaded) {
Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
// Dispatcher::get()->addFunction<void(GJGarageLayer*)>("test-garage-open", [](GJGarageLayer*
// gl) { auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
// label->setPosition(100, 80);
// label->setScale(.4f);
// label->setZOrder(99999);
// gl->addChild(label);
// });
}
(void)new EventListener(+[](GJGarageLayer* gl) {
auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
label->setPosition(100, 80);
label->setScale(.4f);
label->setZOrder(99999);
gl->addChild(label);
return ListenerResult::Propagate;
}, MyDispatchFilter("geode.test/test-garage-open"));
}

View file

@ -1,6 +1,8 @@
#pragma once
#include <Geode/loader/Event.hpp>
#include <Geode/loader/Dispatch.hpp>
#include <Geode/binding/GJGarageLayer.hpp>
using namespace geode::prelude;
@ -31,3 +33,6 @@ public:
TestEventFilter();
TestEventFilter(TestEventFilter const&) = default;
};
using MyDispatchEvent = geode::DispatchEvent<GJGarageLayer*>;
using MyDispatchFilter = geode::DispatchFilter<GJGarageLayer*>;

View file

@ -1,5 +1,4 @@
#include <Geode/Loader.hpp>
#include <Geode/loader/ModJsonTest.hpp>
#include <Geode/loader/ModEvent.hpp>
#include <Geode/utils/cocos.hpp>
#include "../dependency/main.hpp"
@ -12,23 +11,17 @@ auto test = []() {
};
// Exported functions
$on_mod(Enabled) {
log::info("Enabled");
}
$on_mod(Disabled) {
log::info("Disabled");
}
$on_mod(Loaded) {
log::info("Loaded");
}
$on_mod(Unloaded) {
log::info("Unloaded");
}
static std::string s_recievedEvent;
// Events
$execute {
new EventListener<TestEventFilter>(+[](TestEvent* event) {
log::info("Received event: {}", event->getData());
s_recievedEvent = event->getData();
});
}
@ -108,37 +101,16 @@ struct GJGarageLayerTest : Modify<GJGarageLayerTest, GJGarageLayer> {
addChild(label2);
// Dispatch system pt. 1
// auto fn = Dispatcher::get()->getFunction<void(GJGarageLayer*)>("test-garage-open");
// fn(this);
MyDispatchEvent("geode.test/test-garage-open", this).post();
if (s_recievedEvent.size() > 0) {
auto label = CCLabelBMFont::create("Event works!", "bigFont.fnt");
label->setPosition(100, 70);
label->setScale(.4f);
label->setZOrder(99999);
addChild(label);
}
return true;
}
};
/*// Event system pt. 2
int a = (0, []() {
Dispatcher::get()->addSelector("test-garage-open", [](GJGarageLayer* gl) {
auto label = CCLabelBMFont::create("EventCenter works!", "bigFont.fnt");
label->setPosition(100, 80);
label->setScale(.4f);
label->setZOrder(99999);
gl->addChild(label);
TestDependency::depTest(gl);
});
// Event system pt. 2
// $observe("test-garage-open", GJGarageLayer*, evt) {
// auto gl = evt.object();
// auto label = CCLabelBMFont::create("EventCenter works!", "bigFont.fnt");
// label->setPosition(100, 80);
// label->setScale(.4f);
// label->setZOrder(99999);
// gl->addChild(label);
// // API pt. 2
// TestDependency::depTest(gl);
// }
return 0;
}());*/

View file

@ -10,7 +10,7 @@
{
"id": "geode.testdep",
"version": ">=1.0.0",
"required": true
"importance": "required"
}
]
}

View file

@ -1,10 +0,0 @@
#define EXPORT_NAME TestDependency
#include <Geode/Loader.hpp>
API_INIT("com.geode.testdep")
class TestDependency {
public:
static void depTest(GJGarageLayer* gl);
// API_DECL(&TestDependency::depTest, gl);
};