diff --git a/src/features/LayerManager/EditorLayerInput.cpp b/src/features/LayerManager/EditorLayerInput.cpp new file mode 100644 index 00000000..245defb7 --- /dev/null +++ b/src/features/LayerManager/EditorLayerInput.cpp @@ -0,0 +1,90 @@ +#include "EditorLayerInput.hpp" +#include "LayerManager.hpp" + +void updateEditorLayerButtons(EditorUI* editorUI) { + if(!editorUI) + return; + + auto menu = editorUI->getChildByID("layer-menu"); + auto layer = LayerManager::get()->getLayer(editorUI->m_editorLayer->m_currentLayer); + + // update layer lock button + if(auto lockLayerBtn = as(menu->getChildByTag(LOCKLAYER_TAG))) { + const char* lockSpr = "GJ_lockGray_001.png"; + + if (layer) { + lockSpr = layer->m_locked ? "GJ_lock_001.png" : "GJ_lock_open_001.png"; + } + + auto btnSpr = CCSprite::createWithSpriteFrameName(lockSpr); + btnSpr->setScale(.7f); + btnSpr->setPosition(lockLayerBtn->getNormalImage()->getPosition()); + btnSpr->setOpacity(layer ? 255 : 120); + + lockLayerBtn->setNormalImage(btnSpr); + + // for some reason setNormalImage resets the anchor point + if (!strcmp(lockSpr, "GJ_lock_open_001.png")) { + lockLayerBtn->getNormalImage()->setAnchorPoint({ 0.52f, 0.2f }); + } + else { + lockLayerBtn->getNormalImage()->setAnchorPoint({ 0.5f, 0.5f }); + } + lockLayerBtn->setEnabled(layer); + } +} + +void updateEditorLayerInputText(EditorUI* editorUI) { + if(!editorUI) + return; + + auto menu = editorUI->getChildByID("layer-menu"); + auto layer = LayerManager::get()->getLayer(editorUI->m_editorLayer->m_currentLayer); + + updateEditorLayerButtons(editorUI); + + // update layer input + if(auto layerInput = menu->getChildByTag(LAYERINPUT_TAG)) { + as(layerInput)->setString(editorUI->m_currentLayerLabel->getString()); + } +} + +EUITextDelegate* EUITextDelegate::create() { + auto ret = new EUITextDelegate(); + + if (ret && ret->init()) { + ret->autorelease(); + return ret; + } + + CC_SAFE_DELETE(ret); + return nullptr; +} + +int strToInt(const char* str, bool* is = nullptr) { + bool isStr = true; + for (auto i = 0u; i < strlen(str); i++) + if (!isdigit(str[i]) && str[i] != '-') + isStr = false; + + if (is) *is = isStr; + + return isStr ? std::atoi(str) : -1; +} + +void EUITextDelegate::textChanged(CCTextInputNode* input) { + auto editor = LevelEditorLayer::get(); + + if (input->getString() && strlen(input->getString())) { + editor->m_currentLayer = strToInt(input->getString()); + } + else { + editor->m_currentLayer = -1; + } + + if(editor->m_editorUI) { + editor->m_editorUI->m_currentLayerLabel->setString(fmt::format("{}", editor->m_currentLayer).c_str()); + + updateEditorLayerButtons(editor->m_editorUI); + } +} \ No newline at end of file diff --git a/src/features/LayerManager/EditorLayerInput.hpp b/src/features/LayerManager/EditorLayerInput.hpp new file mode 100644 index 00000000..0b34d361 --- /dev/null +++ b/src/features/LayerManager/EditorLayerInput.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +using namespace geode::prelude; + +static constexpr const int LAYERINPUT_TAG = 6978; +static constexpr const int LAYERINPUTBG_TAG = 6977; +static constexpr const int NEXTFREELAYER_TAG = 7001; +static constexpr const int LOCKLAYER_TAG = 7002; +static constexpr const int VIEWLAYERS_TAG = 7003; + +void updateEditorLayerButtons(EditorUI*); +void updateEditorLayerInputText(EditorUI*); + +class EUITextDelegate : public CCNode, public TextInputDelegate { +public: + virtual void textChanged(CCTextInputNode*) override; + + static EUITextDelegate* create(); +}; diff --git a/src/features/LayerManager/LayerManager.cpp b/src/features/LayerManager/LayerManager.cpp index 18a5efd6..2c9eca7f 100644 --- a/src/features/LayerManager/LayerManager.cpp +++ b/src/features/LayerManager/LayerManager.cpp @@ -34,18 +34,15 @@ bool LayerManager::init() { } LayerManager* LayerManager::get() { - return g_manager; -} - -bool LayerManager::initGlobal() { - g_manager = new LayerManager(); + if(!g_manager) { + g_manager = new LayerManager(); - if (g_manager && g_manager->init()) { - return true; + if(!g_manager || !g_manager->init()) { + CC_SAFE_DELETE(g_manager); + } } - CC_SAFE_DELETE(g_manager); - return false; + return g_manager; } LayerManager::Level* LayerManager::Level::createWithCoder(DS_Dictionary* dict) { @@ -132,7 +129,7 @@ class $modify(LMGJGameLevel, GJGameLevel) { class $modify(LMGameObject, GameObject) { void setOpacity(GLubyte opacity) { - if(opacity < 255) { + if(m_editor && opacity < 255) { auto layer = LayerManager::get()->getLayer(m_editorLayer); if(layer) { @@ -164,6 +161,7 @@ void filterObjects(CCArray* objs) { auto layer = LayerManager::get()->getLayer(obj->m_editorLayer); if(layer && layer->m_locked) { objs->removeObjectAtIndex(i, false); + obj->deselectObject(); maxCount--; } else { @@ -176,8 +174,12 @@ class $modify(LMEditorLayer, LevelEditorLayer) { GameObject* objectAtPosition(CCPoint position) { auto obj = LevelEditorLayer::objectAtPosition(position); - if(LayerManager::get()->getLayer(obj->m_editorLayer)->m_locked) { - obj = nullptr; + if(obj != nullptr) { + if(auto layer = LayerManager::get()->getLayer(obj->m_editorLayer)) { + if(layer->m_locked) { + obj = nullptr; + } + } } return obj; @@ -206,6 +208,12 @@ class $modify(EditorUI) { return EditorUI::processSelectObjects(objs); } + + void selectObjects(CCArray* objs, bool ignoreFilters) { + EditorUI::selectObjects(objs, ignoreFilters); + + filterObjects(m_selectedObjects); + } }; // needa put this here cuz of LMGJGameLevel @@ -217,9 +225,4 @@ LayerManager::Level * LayerManager::getLevel() { } return lvl->m_fields->associatedLevel; -} - -// temporary maybe or maybe not -$on_mod(Loaded) { - LayerManager::initGlobal(); } \ No newline at end of file diff --git a/src/features/LayerManager/LayerManager.hpp b/src/features/LayerManager/LayerManager.hpp index 4ba70543..7eabe7f6 100644 --- a/src/features/LayerManager/LayerManager.hpp +++ b/src/features/LayerManager/LayerManager.hpp @@ -57,6 +57,5 @@ class LayerManager { Layer * getLayer(int number); Level* getLevel(); - static bool initGlobal(); static LayerManager* get(); }; \ No newline at end of file diff --git a/src/features/LayerManager/LayerViewPopup.cpp b/src/features/LayerManager/LayerViewPopup.cpp index ccf81211..c4fd73c9 100644 --- a/src/features/LayerManager/LayerViewPopup.cpp +++ b/src/features/LayerManager/LayerViewPopup.cpp @@ -1,6 +1,7 @@ #include "LayerViewPopup.hpp" #include "LayerEditPopup.hpp" #include "LayerSettingsPopup.hpp" +#include "EditorLayerInput.hpp" #include @@ -738,6 +739,7 @@ LayerViewPopup* LayerViewPopup::create() { return nullptr; } + /* HOOKS */ @@ -746,6 +748,51 @@ class $modify(LayerPopupUI, EditorUI) { LayerViewPopup::create()->show(); } + void onLockLayer(CCObject*) { + if (LayerManager::get()->getLevel()->isMultiple()) { + for (auto const& num : LayerManager::get()->getLevel()->m_visibleLayers) { + auto layer = LayerManager::get()->getLayer(num); + + if (layer) { + layer->m_locked = !layer->m_locked; + } + } + } else { + auto layer = LayerManager::get()->getLayer(m_editorLayer->m_currentLayer); + + if (layer) { + layer->m_locked = !layer->m_locked; + } + } + + updateEditorLayerInputText(this); + } + + void onNextFreeEditorLayer(CCObject*) { + auto objs = m_editorLayer->getAllObjects(); + + std::set layers; + + for(auto& obj : CCArrayExt(objs)) { + layers.insert(obj->m_editorLayer); + layers.insert(obj->m_editorLayer2); + } + + int last = -1; + for (auto const& layer : layers) { + if (last + 1 != layer) + break; + last = layer; + } + + m_editorLayer->m_currentLayer = last + 1; + m_currentLayerLabel->setString(fmt::format("{}", last + 1).c_str()); + + LayerManager::get()->getLevel()->clearVisible(); + + updateEditorLayerInputText(this); + } + bool init(LevelEditorLayer* editor) { if(!EditorUI::init(editor)) return false; @@ -761,11 +808,115 @@ class $modify(LayerPopupUI, EditorUI) { this, menu_selector(LayerPopupUI::onShowLayerPopup) ); - - layersBtn->setPosition(allLayersBtn->getPosition() + CCPoint(-55, 0)); + layersBtn->setPosition(allLayersBtn->getPosition() + CCPoint(-50.f, 0)); + layersBtn->setTag(VIEWLAYERS_TAG); menu->addChild(layersBtn); + // layer lock button + auto lockBtnSpr = CCSprite::createWithSpriteFrameName("GJ_lock_open_001.png"); + lockBtnSpr->setScale(.7f); + auto lockBtn = CCMenuItemSpriteExtra::create(lockBtnSpr, this, menu_selector(LayerPopupUI::onLockLayer)); + lockBtn->setPosition(allLayersBtn->getPosition() + CCPoint(-25.f, 0)); + lockBtn->setTag(LOCKLAYER_TAG); + + menu->addChild(lockBtn); + + // move buttons + #define MoveButton(buttonID, xMove) \ + if(auto btn = menu->getChildByID(buttonID)) { \ + btn->setPositionX(btn->getPositionX() + xMove); \ + } + + MoveButton("all-layers-button", -7.5f); + MoveButton("prev-layer-button", -15.5f); + MoveButton("next-layer-button", -17.5f); + + // move layer label + m_currentLayerLabel->setVisible(false); + m_currentLayerLabel->setPositionX(m_currentLayerLabel->getPositionX() - 16.5f); + + // layer input + auto eLayerInput = InputNode::create(50.f, "All", "bigFont.fnt", "0123456789", 3); + eLayerInput->getInput()->setLabelPlaceholderColor({ 120, 120, 120 }); + eLayerInput->setScale(.7f); + eLayerInput->getInput()->setDelegate(EUITextDelegate::create()); + eLayerInput->setTag(LAYERINPUT_TAG); + eLayerInput->setString(m_currentLayerLabel->getString()); + eLayerInput->setPosition(m_currentLayerLabel->getPosition()); + + menu->addChild(eLayerInput); + + // next free layer button + auto nextFreeBtnSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_02_001.png"); + nextFreeBtnSpr->setScale(.54f); + nextFreeBtnSpr->setOpacity(175); + nextFreeBtnSpr->setFlipX(true); + auto nextFreeBtn = CCMenuItemSpriteExtra::create(nextFreeBtnSpr, this, menu_selector(LayerPopupUI::onNextFreeEditorLayer)); + nextFreeBtn->setTag(NEXTFREELAYER_TAG); + + // bruh + auto prevBtn = menu->getChildByID("prev-layer-button"); + auto nextBtn = menu->getChildByID("next-layer-button"); + + nextFreeBtn->setPosition(nextBtn->getPositionX() + prevBtn->getPositionX() - allLayersBtn->getPositionX(), allLayersBtn->getPositionY()); + + menu->addChild(nextFreeBtn); + + // done + updateEditorLayerInputText(this); + return true; } + + void onGoToLayer(CCObject* pSender) { + EditorUI::onGoToLayer(pSender); + + LayerManager::get()->getLevel()->clearVisible(); + + updateEditorLayerInputText(this); + } + + void onGroupDown(CCObject* pSender) { + EditorUI::onGroupDown(pSender); + + LayerManager::get()->getLevel()->clearVisible(); + + updateEditorLayerInputText(this); + } + + void onGroupUp(CCObject* pSender) { + EditorUI::onGroupUp(pSender); + + LayerManager::get()->getLevel()->clearVisible(); + + updateEditorLayerInputText(this); + } + + void onGoToBaseLayer(CCObject* pSender) { + EditorUI::onGoToBaseLayer(pSender); + + LayerManager::get()->getLevel()->clearVisible(); + + updateEditorLayerInputText(this); + } + + void showUI(bool show) { + EditorUI::showUI(show); + + if(!GameManager::sharedState()->getGameVariable("0046")) { + show = true; + } + + m_currentLayerLabel->setVisible(false); + + auto menu = this->getChildByID("layer-menu"); + + #define ToggleNode(tag) if(auto node = menu->getChildByTag(tag)) node->setVisible(show) + + ToggleNode(LOCKLAYER_TAG); + ToggleNode(VIEWLAYERS_TAG); + ToggleNode(LAYERINPUT_TAG); + ToggleNode(NEXTFREELAYER_TAG); + } }; \ No newline at end of file