Created
February 13, 2025 21:20
-
-
Save camila314/5c0b53725024715856779ceca5219061 to your computer and use it in GitHub Desktop.
Hot-reloadable dynamic variables for Geode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Geode/cocos/include/cocos2d.h> | |
| #include <filesystem> | |
| #include <fstream> | |
| #include <Geode/utils/string.hpp> | |
| #include <string> | |
| class DynamicVarNode : public cocos2d::CCNode { | |
| std::filesystem::path m_path; | |
| std::filesystem::file_time_type m_last_write; | |
| std::string m_last_code; | |
| int m_line; | |
| std::function<void(std::string const&)> m_callback; | |
| public: | |
| inline static DynamicVarNode* create(cocos2d::CCNode* parent, std::filesystem::path const& path, int line) { | |
| auto ret = new DynamicVarNode(); | |
| if (ret && ret->init(parent, path, line)) { | |
| ret->autorelease(); | |
| return ret; | |
| } | |
| CC_SAFE_DELETE(ret); | |
| return nullptr; | |
| } | |
| inline bool init(cocos2d::CCNode* parent, std::filesystem::path const& path, int line) { | |
| cocos2d::CCNode::init(); | |
| parent->addChild(this); | |
| scheduleUpdate(); | |
| m_path = path; | |
| m_line = line; | |
| m_last_code = ""; | |
| return true; | |
| } | |
| inline void operator<<(std::function<void(std::string const&)> callback) { | |
| m_callback = callback; | |
| update(0.0); | |
| } | |
| inline void update(float dt) override { | |
| if (!m_callback) | |
| return; | |
| auto last_write = std::filesystem::last_write_time(m_path); | |
| if (m_last_write == last_write) | |
| return; | |
| m_last_write = last_write; | |
| std::ifstream stream(m_path); | |
| std::string code((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); | |
| auto lines = geode::utils::string::split(code, "\n"); | |
| if (m_line >= lines.size()) | |
| return; | |
| auto data = geode::utils::string::split(lines[m_line], "//"); | |
| if (data.size() < 2) | |
| return; | |
| data.erase(data.begin()); | |
| m_callback(geode::utils::string::trim(geode::utils::string::join(data, ""))); | |
| } | |
| }; | |
| #define $dynamic(obj, var) *DynamicVarNode::create(obj, __FILE__, __LINE__ - 1) << [=, obj](std::string const& var) | |
| /* | |
| Example Usage: | |
| class $modify(PauseLayer) { | |
| void customSetup() { | |
| PauseLayer::customSetup(); | |
| static CCSprite* btn = nullptr; | |
| $dynamic(this, val) { // d_largeSquare_02_001.png | |
| if (btn) | |
| btn->removeFromParent(); | |
| btn = CCSprite::createWithSpriteFrameName(val.c_str()); | |
| btn->setPosition({100, 100}); | |
| addChild(btn); | |
| }; | |
| } | |
| }; | |
| Put your hot-reloadable value in a comment to the right of $dynamic | |
| Whitespaces are trimmed and 'val' will be std::string const& | |
| Edit the comment and save the file to trigger the $dynamic block | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment