diff --git a/src/features/ObjectIndicators.cpp b/src/features/ObjectIndicators.cpp new file mode 100644 index 00000000..795613b8 --- /dev/null +++ b/src/features/ObjectIndicators.cpp @@ -0,0 +1,112 @@ + +#include +#include +#include +#include +#include + +using namespace geode::prelude; + +class ObjectIndicator : public CCNode { +protected: + Ref m_target; + CCSprite* m_arrow; + + bool init(GameObject* target, const char* sprName) { + if (!CCNode::init()) + return false; + + m_target = target; + this->setContentSize({ 65, 65 }); + this->setAnchorPoint({ .5f, .5f }); + + auto spr = CCSprite::createWithSpriteFrameName(sprName); + spr->setPosition(m_obContentSize / 2); + this->addChild(spr); + limitNodeSize(spr, { 30, 30 }, 1.f, .1f); + + m_arrow = CCSprite::createWithSpriteFrameName("edit_rightBtn_001.png"); + m_arrow->setScale(.75f); + m_arrow->setPosition(m_obContentSize / 2); + m_arrow->setAnchorPoint({ -1.5f, .5f }); + this->addChild(m_arrow); + + this->scheduleUpdate(); + + return true; + } + + void update(float) override { + if (!m_target->getParent()) { + return; + } + auto const winSize = CCDirector::sharedDirector()->getWinSize(); + auto targetPos = m_target->getParent()->convertToWorldSpace(m_target->getPosition()); + m_arrow->setRotation( + static_cast(winSize / 2).getAngle(targetPos) * (180.f / std::numbers::pi) + 90.f + ); + if (targetPos.x < 80.f) { + targetPos.x = 80.f; + } + if (targetPos.x > winSize.width - 140.f) { + targetPos.x = winSize.width - 140.f; + } + if (targetPos.y < 120.f) { + targetPos.y = 120.f; + } + if (targetPos.y > winSize.height - 70.f) { + targetPos.y = winSize.height - 70.f; + } + this->setPosition(targetPos); + } + +public: + static ObjectIndicator* create(GameObject* target, const char* spr) { + auto ret = new ObjectIndicator(); + if (ret && ret->init(target, spr)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } + + bool targets(GameObject* obj) const { + return m_target == obj; + } +}; + +class $modify(LevelEditorLayer) { + std::unordered_map indicators; + + bool init(GJGameLevel* level) { + if (!LevelEditorLayer::init(level)) + return false; + + for (auto& [_, i] : m_fields->indicators) { + m_editorUI->addChild(i); + } + + return true; + } + + void addSpecial(GameObject* obj) { + // wish we had tracking so you didn't need to hook all of this stuff every time... + LevelEditorLayer::addSpecial(obj); + if (typeinfo_cast(obj)) { + auto i = ObjectIndicator::create(obj, "start-pos-border.png"_spr); + if (m_editorUI) { + m_editorUI->addChild(i); + } + m_fields->indicators.insert({ obj, i }); + } + } + + void removeSpecial(GameObject* obj) { + LevelEditorLayer::removeSpecial(obj); + if (m_fields->indicators.contains(obj)) { + m_fields->indicators.at(obj)->removeFromParent(); + m_fields->indicators.erase(obj); + } + } +};