Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ add_library(${PROJECT_NAME} SHARED ${SOURCES} src/platform/Mac.mm)

set_source_files_properties(src/platform/Mac.mm PROPERTIES SKIP_PRECOMPILE_HEADERS ON)

if ("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS" OR IOS)
target_link_libraries(${PROJECT_NAME} "-framework CoreGraphics")
endif()

if (NOT DEFINED ENV{GEODE_SDK})
message(FATAL_ERROR "Unable to find Geode SDK! Please define GEODE_SDK environment variable to point to Geode")
else()
Expand Down
2 changes: 1 addition & 1 deletion mod.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"geode": "4.8.0",
"geode": "4.9.0",
"version": "v1.10.0",
"gd": {
"win": "2.2074",
Expand Down
4 changes: 4 additions & 0 deletions src/DevTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ void DevTools::toggle() {
this->show(!m_visible);
}

bool DevTools::isVisible() {
return m_visible;
}

void DevTools::sceneChanged() {
m_selectedNode = nullptr;
}
Expand Down
2 changes: 2 additions & 0 deletions src/DevTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@ class DevTools {

void show(bool visible);
void toggle();

bool isVisible();
};
27 changes: 27 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <Geode/modify/CCDirector.hpp>
#include <Geode/modify/CCEGLView.hpp>
#include <Geode/modify/CCNode.hpp>
#include <Geode/modify/GameToolbox.hpp>
#include "DevTools.hpp"
#include <imgui.h>
#include "ImGui.hpp"
Expand Down Expand Up @@ -41,6 +42,32 @@ class $modify(MenuLayer) {

#endif

class $modify(GameToolbox) {
static void preVisitWithClippingRect(CCNode* node, CCRect clipRect) {
if (!node->isVisible() || !DevTools::get()->isVisible())
return GameToolbox::preVisitWithClippingRect(node, clipRect);

glEnable(GL_SCISSOR_TEST);

clipRect.origin = node->convertToWorldSpace(clipRect.origin);

kmMat4 mat;
kmGLGetMatrix(KM_GL_PROJECTION, &mat);
if (mat.mat[5] < 0) {
auto ws = CCDirector::get()->getWinSize();
clipRect.origin.y = ws.height - (clipRect.origin.y + node->getContentSize().height);
}

CCEGLView::get()->setScissorInPoints(
clipRect.origin.x,
clipRect.origin.y,
clipRect.size.width,
clipRect.size.height
);
}

};

class $modify(CCDirector) {
void willSwitchToScene(CCScene* scene) {
CCDirector::willSwitchToScene(scene);
Expand Down
24 changes: 22 additions & 2 deletions src/pages/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
#include <ccTypes.h>
#include <Geode/ui/SimpleAxisLayout.hpp>
#include <Geode/ui/Layout.hpp>
#include <Geode/utils/file.hpp>

using namespace geode::prelude;

#define AXIS_GET(Name_) \
&AxisLayoutOptions::get##Name_, \
&AxisLayoutOptions::set##Name_


template <class T, class R>
bool checkbox(const char* text, T* ptr, bool(T::* get)(), R(T::* set)(bool)) {
bool value = (ptr->*get)();
Expand Down Expand Up @@ -72,13 +74,31 @@ void DevTools::drawBasicAttributes(CCNode* node) {
}
ImGui::SameLine();
if (ImGui::Button(U8STR(FEATHER_COPY " Copy Class Name"))) {
clipboard::write(getNodeName(node));
clipboard::write(std::string(geode::cocos::getObjectName(node)));
}
ImGui::SameLine();
if (ImGui::Button(U8STR(FEATHER_SAVE " Screenshot"))) {
file::pick(file::PickMode::SaveFile, file::FilePickOptions {
.filters = {{ .description = "PNG Image", .files = {"*.png"} }}
}).listen([node](auto choice) {
if (auto file = choice->ok()) {
int width, height;
auto bytes = renderToBytes(node, width, height);

auto path = string::pathToString(*file);
if (!path.ends_with(".png")) {
path += ".png";
}
saveRenderToFile(bytes, width, height, path.c_str());
}
});
}

ImGui::Text("Address: %s", fmt::to_string(fmt::ptr(node)).c_str());
ImGui::SameLine();
if (ImGui::Button(U8STR(FEATHER_COPY " Copy"))) {
clipboard::write(
utils::intToHex(reinterpret_cast<uintptr_t>(node))
fmt::format("{:#x}", reinterpret_cast<uintptr_t>(node))
);
}
if (node->getUserData()) {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void DevTools::drawTreeBranch(CCNode* node, size_t index) {
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
}
std::stringstream name;
name << "[" << index << "] " << getNodeName(node) << " ";
name << "[" << index << "] " << geode::cocos::getObjectName(node) << " ";
if (node->getTag() != -1) {
name << "(" << node->getTag() << ") ";
}
Expand Down
3 changes: 2 additions & 1 deletion src/platform/Android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ using namespace geode::prelude;
#include "utils.hpp"

std::string formatAddressIntoOffsetImpl(uintptr_t addr, bool module) {
if (addr > base::get() && addr - 0x1000000 < base::get())
if (addr > base::get() && addr - 0x1000000 < base::get()) {
if(module) return fmt::format("libcocos2d.so + {:#x}", addr - base::get());
else return fmt::format("{:#x}", addr - base::get());
}
return fmt::format("{:#x}", addr);
}

Expand Down
10 changes: 10 additions & 0 deletions src/platform/Mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "utils.hpp"

#include <Geode/utils/string.hpp>
#include <Geode/utils/file.hpp>
#include <Geode/loader/Log.hpp>
#include <array>
#include <thread>
#include <execinfo.h>
Expand All @@ -18,6 +20,13 @@
#include <mach-o/dyld.h>
#import <Foundation/Foundation.h>

#import <CoreGraphics/CoreGraphics.h>
#ifdef GEODE_IS_MACOS
#include <ImageIO/CGImageDestination.h>
#else
#import <UIKit/UIKit.h>
#endif

static std::vector<struct dyld_image_info const*> getAllImages() {
std::vector<struct dyld_image_info const*> images;
struct task_dyld_info dyldInfo;
Expand Down Expand Up @@ -86,4 +95,5 @@
else return fmt::format("{:#x}", addr - base);
}


#endif
96 changes: 96 additions & 0 deletions src/platform/utils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
#include "utils.hpp"

#if defined(GEODE_IS_MACOS)
#include <OpenGL/gl.h>
#elif defined(GEODE_IS_IOS)
#include <OpenGLES/ES2/gl.h>
#endif
#include <unordered_map>
#include <cocos2d.h>

using namespace cocos2d;

std::string formatAddressIntoOffset(uintptr_t addr, bool module) {
static std::unordered_map<uintptr_t, std::pair<std::string, std::string>> formatted;
Expand All @@ -16,4 +24,92 @@ std::string formatAddressIntoOffset(uintptr_t addr, bool module) {
if(module) return pair.first;
else return pair.second;
}
}

std::vector<uint8_t> renderToBytes(CCNode* node, int& width, int& height) {
// Get scale from cocos2d units to opengl units
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
auto winSize = CCDirector::get()->getWinSize();

width = node->getContentSize().width * (viewport[2] / winSize.width);
height = node->getContentSize().height * (viewport[3] / winSize.height);

// Create Texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Create Framebuffer Object
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

// Unbind texture
glBindTexture(GL_TEXTURE_2D, 0);

// Clear any data
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Flip Y when projecting
kmGLMatrixMode(KM_GL_PROJECTION);
kmGLPushMatrix();
kmGLLoadIdentity();

kmMat4 ortho;
kmMat4OrthographicProjection(&ortho,
0.0f, winSize.width,
winSize.height, 0.0f,
-1.0f, 1.0f
);
kmGLMultMatrix(&ortho);

// Transform matrix so the node is drawn at 0,0
kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLPushMatrix();
kmGLLoadIdentity();

auto anchor = node->isIgnoreAnchorPointForPosition() ? ccp(0, 0) : node->getAnchorPointInPoints();
kmGLTranslatef(
anchor.x - node->getPositionX(),
anchor.y - node->getPositionY() + (winSize.height - node->getContentSize().height),
0
);

// Visit
node->visit();

// Undo matrix transformations
kmGLPopMatrix();
kmGLMatrixMode(KM_GL_PROJECTION);
kmGLPopMatrix();
kmGLMatrixMode(KM_GL_MODELVIEW);

// Read from Framebuffer
std::vector<unsigned char> pixels(width * height * 4); // RGBA8
glReadPixels(
0, 0, width, height,
GL_RGBA, GL_UNSIGNED_BYTE,
pixels.data()
);

// Unbind Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Delete
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);

return pixels;
}

void saveRenderToFile(std::vector<uint8_t> const& data, int width, int height, char const* filename) {
auto img = new CCImage();
img->initWithImageData((void*)data.data(), data.size(), CCImage::kFmtRawData, width, height, 8);
img->saveToFile(filename, false);
}
23 changes: 3 additions & 20 deletions src/platform/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,10 @@
#include <string>
#include <stdint.h>
#include <Geode/cocos/cocoa/CCObject.h>
#ifndef GEODE_IS_WINDOWS
#include <cxxabi.h>
#endif

static inline std::string getNodeName(cocos2d::CCObject* node) {
#ifdef GEODE_IS_WINDOWS
return typeid(*node).name() + 6;
#else
std::string ret;

int status = 0;
auto demangle = abi::__cxa_demangle(typeid(*node).name(), 0, 0, &status);
if (status == 0) {
ret = demangle;
}
free(demangle);

return ret;
#endif
}

std::string formatAddressIntoOffset(uintptr_t addr, bool module);

std::string formatAddressIntoOffsetImpl(uintptr_t addr, bool module);

std::vector<uint8_t> renderToBytes(cocos2d::CCNode* node, int& width, int& height);
void saveRenderToFile(std::vector<uint8_t> const& data, int width, int height, char const* filename);
Loading