From c9a3836a2965caacc5a0501c303c98cee78e748b Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Mon, 5 Feb 2024 15:31:06 +0800 Subject: [PATCH] Add "View" button to tele drop down in editor This allows mappers to find teles by number. Partially fixed #2194 --- src/game/editor/editor.cpp | 2 +- src/game/editor/editor.h | 1 + src/game/editor/mapitems/layer_tele.cpp | 57 +++++++++++++++++++++++++ src/game/editor/mapitems/layer_tele.h | 4 ++ src/game/editor/popups.cpp | 54 +++++++++++++++++------ 5 files changed, 105 insertions(+), 13 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 7c7fa130b..0a3a2cd61 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -1328,7 +1328,7 @@ void CEditor::DoToolbarLayers(CUIRect ToolBar) { pButtonName = "Tele"; pfnPopupFunc = PopupTele; - Rows = 2; + Rows = 3; } if(pButtonName != nullptr) diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 243af6d1c..4cf89f235 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -1105,6 +1105,7 @@ public: unsigned char m_TeleNumber; unsigned char m_TeleCheckpointNumber; + unsigned char m_ViewTeleNumber; unsigned char m_TuningNum; diff --git a/src/game/editor/mapitems/layer_tele.cpp b/src/game/editor/mapitems/layer_tele.cpp index fbc621dbc..977344a58 100644 --- a/src/game/editor/mapitems/layer_tele.cpp +++ b/src/game/editor/mapitems/layer_tele.cpp @@ -10,6 +10,9 @@ CLayerTele::CLayerTele(CEditor *pEditor, int w, int h) : m_pTeleTile = new CTeleTile[w * h]; mem_zero(m_pTeleTile, (size_t)w * h * sizeof(CTeleTile)); + + m_GotoTeleOffset = 0; + m_GotoTeleLastPos = ivec2(-1, -1); } CLayerTele::CLayerTele(const CLayerTele &Other) : @@ -316,6 +319,60 @@ bool CLayerTele::ContainsElementWithId(int Id, bool Checkpoint) return false; } +void CLayerTele::GetPos(int Number, int Offset, int &TeleX, int &TeleY) +{ + int Match = -1; + ivec2 MatchPos = ivec2(-1, -1); + TeleX = -1; + TeleY = -1; + + auto FindTile = [this, &Match, &MatchPos, &Number, &Offset]() { + for(int x = 0; x < m_Width; x++) + { + for(int y = 0; y < m_Height; y++) + { + int i = y * m_Width + x; + int Tele = m_pTeleTile[i].m_Number; + if(Number == Tele) + { + Match++; + if(Offset != -1) + { + if(Match == Offset) + { + MatchPos = ivec2(x, y); + m_GotoTeleOffset = Match; + return; + } + continue; + } + MatchPos = ivec2(x, y); + if(m_GotoTeleLastPos != ivec2(-1, -1)) + { + if(distance(m_GotoTeleLastPos, MatchPos) < 10.0f) + { + m_GotoTeleOffset++; + continue; + } + } + m_GotoTeleLastPos = MatchPos; + if(Match == m_GotoTeleOffset) + return; + } + } + } + }; + FindTile(); + + if(MatchPos == ivec2(-1, -1)) + return; + if(Match < m_GotoTeleOffset) + m_GotoTeleOffset = -1; + TeleX = MatchPos.x; + TeleY = MatchPos.y; + m_GotoTeleOffset++; +} + std::shared_ptr CLayerTele::Duplicate() const { return std::make_shared(*this); diff --git a/src/game/editor/mapitems/layer_tele.h b/src/game/editor/mapitems/layer_tele.h index 9c652ff21..8d1c5570e 100644 --- a/src/game/editor/mapitems/layer_tele.h +++ b/src/game/editor/mapitems/layer_tele.h @@ -34,6 +34,10 @@ public: void BrushRotate(float Amount) override; void FillSelection(bool Empty, std::shared_ptr pBrush, CUIRect Rect) override; virtual bool ContainsElementWithId(int Id, bool Checkpoint); + virtual void GetPos(int Number, int Offset, int &TeleX, int &TeleY); + + int m_GotoTeleOffset; + ivec2 m_GotoTeleLastPos; EditorTileStateChangeHistory m_History; inline void ClearHistory() override diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 621719628..22775f410 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -2439,19 +2439,48 @@ CUI::EPopupMenuFunctionResult CEditor::PopupTele(void *pContext, CUIRect View, b static int s_PreviousTeleNumber; static int s_PreviousCheckpointNumber; + static int s_PreviousViewTeleNumber; CUIRect NumberPicker; CUIRect FindEmptySlot; - CUIRect FindFreeTeleSlot, FindFreeCheckpointSlot; + CUIRect FindFreeTeleSlot, FindFreeCheckpointSlot, FindFreeViewSlot; View.VSplitRight(15.f, &NumberPicker, &FindEmptySlot); NumberPicker.VSplitRight(2.f, &NumberPicker, nullptr); FindEmptySlot.HSplitTop(13.0f, &FindFreeTeleSlot, &FindEmptySlot); FindEmptySlot.HSplitTop(13.0f, &FindFreeCheckpointSlot, &FindEmptySlot); + FindEmptySlot.HSplitTop(13.0f, &FindFreeViewSlot, &FindEmptySlot); FindFreeTeleSlot.HMargin(1.0f, &FindFreeTeleSlot); FindFreeCheckpointSlot.HMargin(1.0f, &FindFreeCheckpointSlot); + FindFreeViewSlot.HMargin(1.0f, &FindFreeViewSlot); + + auto ViewTele = [](CEditor *pEd) -> bool { + if(!pEd->m_ViewTeleNumber) + return false; + int TeleX, TeleY; + pEd->m_Map.m_pTeleLayer->GetPos(pEd->m_ViewTeleNumber, -1, TeleX, TeleY); + if(TeleX != -1 && TeleY != -1) + { + pEd->MapView()->SetWorldOffset({32.0f * TeleX + 0.5f, 32.0f * TeleY + 0.5f}); + return true; + } + return false; + }; + + static std::vector s_vColors = { + ColorRGBA(0.5f, 1, 0.5f, 0.5f), + ColorRGBA(0.5f, 1, 0.5f, 0.5f), + ColorRGBA(0.5f, 1, 0.5f, 0.5f), + }; + enum + { + PROP_TELE = 0, + PROP_TELE_CP, + PROP_TELE_VIEW, + NUM_PROPS, + }; // find next free numbers buttons { @@ -2474,24 +2503,19 @@ CUI::EPopupMenuFunctionResult CEditor::PopupTele(void *pContext, CUIRect View, b if(CPNumber != -1) pEditor->m_TeleCheckpointNumber = CPNumber; } + + static int s_NextFreeViewPid = 0; + int btn = pEditor->DoButton_Editor(&s_NextFreeViewPid, "N", 0, &FindFreeViewSlot, 0, "[n] Show next tele with this number"); + if(btn || (Active && pEditor->Input()->KeyPress(KEY_N))) + s_vColors[PROP_TELE_VIEW] = ViewTele(pEditor) ? ColorRGBA(0.5f, 1, 0.5f, 0.5f) : ColorRGBA(1, 0.5f, 0.5f, 0.5f); } // number picker { - static std::vector s_vColors = { - ColorRGBA(0.5f, 1, 0.5f, 0.5f), - ColorRGBA(0.5f, 1, 0.5f, 0.5f), - }; - - enum - { - PROP_TELE = 0, - PROP_TELE_CP = 1, - NUM_PROPS, - }; CProperty aProps[] = { {"Number", pEditor->m_TeleNumber, PROPTYPE_INT_STEP, 1, 255}, {"Checkpoint", pEditor->m_TeleCheckpointNumber, PROPTYPE_INT_STEP, 1, 255}, + {"View", pEditor->m_ViewTeleNumber, PROPTYPE_INT_STEP, 1, 255}, {nullptr}, }; @@ -2503,16 +2527,22 @@ CUI::EPopupMenuFunctionResult CEditor::PopupTele(void *pContext, CUIRect View, b pEditor->m_TeleNumber = (NewVal - 1 + 255) % 255 + 1; else if(Prop == PROP_TELE_CP) pEditor->m_TeleCheckpointNumber = (NewVal - 1 + 255) % 255 + 1; + else if(Prop == PROP_TELE_VIEW) + pEditor->m_ViewTeleNumber = (NewVal - 1 + 255) % 255 + 1; if(s_PreviousTeleNumber == 1 || s_PreviousTeleNumber != pEditor->m_TeleNumber) s_vColors[PROP_TELE] = pEditor->m_Map.m_pTeleLayer->ContainsElementWithId(pEditor->m_TeleNumber, false) ? ColorRGBA(1, 0.5f, 0.5f, 0.5f) : ColorRGBA(0.5f, 1, 0.5f, 0.5f); if(s_PreviousCheckpointNumber == 1 || s_PreviousCheckpointNumber != pEditor->m_TeleCheckpointNumber) s_vColors[PROP_TELE_CP] = pEditor->m_Map.m_pTeleLayer->ContainsElementWithId(pEditor->m_TeleCheckpointNumber, true) ? ColorRGBA(1, 0.5f, 0.5f, 0.5f) : ColorRGBA(0.5f, 1, 0.5f, 0.5f); + + if(s_PreviousViewTeleNumber != pEditor->m_ViewTeleNumber) + s_vColors[PROP_TELE_VIEW] = ViewTele(pEditor) ? ColorRGBA(0.5f, 1, 0.5f, 0.5f) : ColorRGBA(1, 0.5f, 0.5f, 0.5f); } s_PreviousTeleNumber = pEditor->m_TeleNumber; s_PreviousCheckpointNumber = pEditor->m_TeleCheckpointNumber; + s_PreviousViewTeleNumber = pEditor->m_ViewTeleNumber; return CUI::POPUP_KEEP_OPEN; }