diff --git a/api/include/MoreTabs.hpp b/api/include/MoreTabs.hpp index f3a0cdb0..a14aff1a 100644 --- a/api/include/MoreTabs.hpp +++ b/api/include/MoreTabs.hpp @@ -10,6 +10,10 @@ using namespace geode::prelude; struct MoreTabsUI; namespace editor_api { + /** + * Class for adding more tabs to the editor, including the edit and delete menus + * @class MoreTabs + */ class EDITOR_API_EXPORT MoreTabs : public CCNode { protected: int m_selectedEditTab; @@ -23,21 +27,74 @@ namespace editor_api { CCMenuItemToggler* createTab(const char* icon, CCObject* target, SEL_MenuHandler selector); + /** + * Create + */ + static MoreTabs* create(EditorUI* ui); + friend struct ::MoreTabsUI; public: + /** + * Add a new create tab + * @param icon The sprite frame name of the icon of the tab + * @param content The content of the tab + * @returns The tag of the created tab + */ int addCreateTab(const char* icon, EditButtonBar* content); + + /** + * Add a new create tab + * @param icon The sprite frame name of the icon of the tab + * @param buttons The list of buttons to add to the EditButtonBar + * @returns The tag of the created tab + */ int addCreateTab(const char* icon, CCArray* buttons); + + /** + * Add a new create tab + * @param icon The sprite frame name of the icon of the tab + * @param objIDs The list of objects to add to the tab + * @returns The tag of the created tab + */ int addCreateTab(const char* icon, std::vector const& objIDs); + + /** + * Add a new edit tab + * @param icon The sprite frame name of the icon of the tab + * @param content The contents of the tab + * @returns The tag of the created tab + */ int addEditTab(const char* icon, CCNode* content); + /** + * Get a create tab based on its tag + * @param tag The tag of the tab + * @returns The EditButtonBar with the tag, or nullptr + */ EditButtonBar* getCreateTab(int tag) const; + + /** + * Go to a specific edit tab based on its tag + */ void switchEditTab(int tag); + /** + * Cycle tab selection to the right + */ void nextTab(); + + /** + * Cycle tab selection to the left + */ void prevTab(); - static MoreTabs* create(EditorUI* ui); + /** + * Get the MoreTabs controller for a specific Editor UI + * @param ui The editor + * @param create Whether to create the controller if it hasn't been created yet + * @returns The MoreTabs controller, or nullptr if one doesn't exist + */ static MoreTabs* get(EditorUI* ui, bool create = true); }; } diff --git a/api/include/Utils.hpp b/api/include/Utils.hpp index 79eacfae..13a6c514 100644 --- a/api/include/Utils.hpp +++ b/api/include/Utils.hpp @@ -9,13 +9,92 @@ using namespace geode::prelude; namespace editor_api { + /** + * Convert a ZLayer into a readable string (like T1 or B3) + * @param z The ZLayer value to convert (as an instance of the ZLayer enum) + * @returns The Z layer as a string + */ EDITOR_API_EXPORT std::string zLayerToString(ZLayer z); + /** + * Helper function to iterate objects for GD + * @param target The first object to add to the iteration; may be nullptr + * @param targets The array of objects to iterate; may be nullptr + * @returns CCArrayExt iterator for the passed objects + * @note If neither are nullptr, target is first in the iteration list + */ EDITOR_API_EXPORT CCArrayExt iterTargets(GameObject* target, CCArray* targets); + + /** + * Helper function to iterate selected objects + * @param ui Editor UI + * @returns CCArrayExt iterator for selected objects + */ EDITOR_API_EXPORT CCArrayExt iterSelected(EditorUI* ui); + + /** + * Check whether a point is within a polygon + * @warning Currently unimplemented!! + */ EDITOR_API_EXPORT bool polygonIntersect(std::vector const& a, CCPoint const& b); + + /** + * Smartly expand selection to a whole structure based on an object in it + * @param ui The editor + * @param from The object to expand the selection from + * @returns List of objects to select for the structure + * @note Actually doesn't select the structure, only returns the objects in the structure + */ EDITOR_API_EXPORT CCArray* selectStructure(EditorUI* ui, GameObject* from); + + /** + * Smartly expand selection to a whole structure based on objects in it + * @param ui The editor + * @param from The objects to expand the selection from + * @returns List of objects to select for the structure + * @note Actually doesn't select the structure, only returns the objects in the structure + */ EDITOR_API_EXPORT CCArray* selectStructure(EditorUI* ui, CCArray* from); + + /** + * Color an object a different color + * @param obj The object to tint + * @param color The color to tint the object to, or nullopt to reset to default + * @warning Currently unimplemented!! + */ EDITOR_API_EXPORT void tintObject(GameObject* obj, std::optional const& color); + + /** + * Helper to create a square button that fits in the editor's UI + * @param top The top sprite's frame name + * @param bg The background sprite + * @returns The created sprite + */ EDITOR_API_EXPORT ButtonSprite* createEditorButtonSprite(const char* top, const char* bg = "GJ_button_01.png"); + + /** + * Move the object layer in the editor to focus on a point + * @param ui Editor UI + * @param pos The position to move to (centered on screen) + * @param smooth Whether to smoothly animate, or instantly move the camera + * @param relative Whether to add the position to the current position of + * the camera, or treat pos as an absolute position + */ + EDITOR_API_EXPORT void moveGameLayerTo(EditorUI* ui, CCPoint const& pos, bool smooth = true, bool relative = false); + + /** + * Move the object layer in the editor to focus on an object + * @param ui Editor UI + * @param pos The object to focus on (centered on screen) + * @param smooth Whether to smoothly animate, or instantly move the camera + */ + EDITOR_API_EXPORT void moveGameLayerTo(EditorUI* ui, GameObject* obj, bool smooth = true); + + /** + * Move the object layer in the editor to focus on an object + * @param ui Editor UI + * @param objs Array of GameObjects + * @param smooth Whether to smoothly animate, or instantly move the camera + */ + EDITOR_API_EXPORT void moveGameLayerTo(EditorUI* ui, CCArray* objs, bool smooth = true); } diff --git a/api/mod.json b/api/mod.json index 4cdfabb1..4f0fab46 100644 --- a/api/mod.json +++ b/api/mod.json @@ -1,6 +1,6 @@ { "geode": "1.3.4", - "version": "v1.0.0", + "version": "v1.1.0", "id": "be_team.editorapi", "name": "EditorAPI", "developer": "BE Team", diff --git a/api/src/Utils.cpp b/api/src/Utils.cpp index 25e52807..e2ea8699 100644 --- a/api/src/Utils.cpp +++ b/api/src/Utils.cpp @@ -112,3 +112,46 @@ ButtonSprite* editor_api::createEditorButtonSprite(const char* top, const char* 32, true, 32, bg, 1.f ); } + +void editor_api::moveGameLayerTo(EditorUI* ui, CCPoint const& pos, bool smooth, bool relative) { + constexpr int GAME_LAYER_MOVE_ACTION_TAG = -48237; + auto layer = ui->m_editorLayer->m_objectLayer; + // Stop any running movements + layer->stopActionByTag(GAME_LAYER_MOVE_ACTION_TAG); + auto a = CCEaseInOut::create( + CCMoveTo::create( + (smooth ? .4f : .0f), + (relative ? layer->getPosition() + pos : pos) + ), + 2.f + ); + a->setTag(GAME_LAYER_MOVE_ACTION_TAG); + layer->runAction(a); +} + +void editor_api::moveGameLayerTo(EditorUI* ui, GameObject* obj, bool smooth) { + moveGameLayerTo( + ui, + (-obj->getPosition() + CCDirector::get()->getWinSize() / 2) * + ui->m_editorLayer->m_objectLayer->getScale(), + smooth, + false + ); +} + +void editor_api::moveGameLayerTo(EditorUI* ui, CCArray* objs, bool smooth) { + constexpr float WINDOW_EDGE_SIZE = 120.f; + + auto layer = ui->m_editorLayer->m_objectLayer; + auto pos = ui->getGroupCenter(objs, false); + auto winSize = CCDirector::get()->getWinSize(); + + auto gpos = layer->convertToWorldSpace(pos); + auto npos = (-pos + winSize / 2) * layer->getScale(); + auto opos = layer->getPosition(); + + // clamping so the position doesn't go past screen boundaries + auto mx = gpos.x < WINDOW_EDGE_SIZE || gpos.x > winSize.width - WINDOW_EDGE_SIZE; + auto my = gpos.y < WINDOW_EDGE_SIZE || gpos.y > winSize.height - WINDOW_EDGE_SIZE; + moveGameLayerTo(ui, { (mx ? npos.x : opos.x), (my ? npos.y : opos.y) }, smooth, false); +}