diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 263610eb5..cd73cbd56 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -212,6 +212,17 @@ void CLayerGroup::DeleteLayer(int Index) m_pMap->m_Modified = true; } +void CLayerGroup::DuplicateLayer(int Index) +{ + if(Index < 0 || Index >= (int)m_vpLayers.size()) + return; + + auto *pDup = m_vpLayers[Index]->Duplicate(); + m_vpLayers.insert(m_vpLayers.begin() + Index + 1, pDup); + + m_pMap->m_Modified = true; +} + void CLayerGroup::GetSize(float *pWidth, float *pHeight) const { *pWidth = 0; @@ -745,6 +756,11 @@ int CEditor::FindSelectedQuadIndex(int Index) const return -1; } +bool CEditor::IsSpecialLayer(const CLayer *pLayer) const +{ + return m_Map.m_pGameLayer == pLayer || m_Map.m_pTeleLayer == pLayer || m_Map.m_pSpeedupLayer == pLayer || m_Map.m_pFrontLayer == pLayer || m_Map.m_pSwitchLayer == pLayer || m_Map.m_pTuneLayer == pLayer; +} + void CEditor::CallbackOpenMap(const char *pFileName, int StorageType, void *pUser) { CEditor *pEditor = (CEditor *)pUser; @@ -3480,7 +3496,7 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect View) else s_LayerPopupContext.m_vpLayers.clear(); - UiInvokePopupMenu(&s_LayerPopupContext, 0, UI()->MouseX(), UI()->MouseY(), 120, 300, PopupLayer, &s_LayerPopupContext); + UiInvokePopupMenu(&s_LayerPopupContext, 0, UI()->MouseX(), UI()->MouseY(), 120, 320, PopupLayer, &s_LayerPopupContext); } } diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index a4df6e923..604aa7ec2 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -127,6 +127,17 @@ public: m_BrushRefCount = 0; } + CLayer(const CLayer &Other) + { + str_copy(m_aName, Other.m_aName, sizeof(m_aName)); + m_Flags = Other.m_Flags; + m_pEditor = Other.m_pEditor; + m_Type = Other.m_Type; + m_BrushRefCount = 0; + m_Visible = true; + m_Readonly = false; + } + virtual ~CLayer() { } @@ -147,6 +158,8 @@ public: virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {} virtual void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) {} + virtual CLayer *Duplicate() const = 0; + virtual void GetSize(float *pWidth, float *pHeight) { *pWidth = 0; @@ -159,7 +172,6 @@ public: bool m_Readonly; bool m_Visible; - int m_BrushRefCount; }; @@ -198,6 +210,7 @@ public: void GetSize(float *pWidth, float *pHeight) const; void DeleteLayer(int Index); + void DuplicateLayer(int Index); int SwapLayers(int Index0, int Index1); bool IsEmpty() const @@ -554,6 +567,7 @@ protected: public: CLayerTiles(int w, int h); + CLayerTiles(const CLayerTiles &Other); ~CLayerTiles(); virtual CTile GetTile(int x, int y); @@ -580,6 +594,8 @@ public: void BrushFlipY() override; void BrushRotate(float Amount) override; + CLayer *Duplicate() const override; + virtual void ShowInfo(); int RenderProperties(CUIRect *pToolbox) override; @@ -637,6 +653,7 @@ class CLayerQuads : public CLayer { public: CLayerQuads(); + CLayerQuads(const CLayerQuads &Other); ~CLayerQuads(); void Render(bool QuadPicker = false) override; @@ -655,6 +672,7 @@ public: void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override; void GetSize(float *pWidth, float *pHeight) override; + CLayer *Duplicate() const override; int m_Image; std::vector m_vQuads; @@ -842,6 +860,7 @@ public: void DeleteSelectedQuads(); bool IsQuadSelected(int Index) const; int FindSelectedQuadIndex(int Index) const; + bool IsSpecialLayer(const CLayer *pLayer) const; float ScaleFontSize(char *pText, int TextSize, float FontSize, int Width); int DoProperties(CUIRect *pToolbox, CProperty *pProps, int *pIDs, int *pNewVal, ColorRGBA Color = ColorRGBA(1, 1, 1, 0.5f)); @@ -1318,6 +1337,7 @@ class CLayerSounds : public CLayer { public: CLayerSounds(); + CLayerSounds(const CLayerSounds &Other); ~CLayerSounds(); void Render(bool Tileset = false) override; @@ -1332,6 +1352,8 @@ public: void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override; void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) override; + CLayer *Duplicate() const override; + int m_Sound; std::vector m_vSources; }; diff --git a/src/game/editor/layer_quads.cpp b/src/game/editor/layer_quads.cpp index 67774d21e..c5854e95c 100644 --- a/src/game/editor/layer_quads.cpp +++ b/src/game/editor/layer_quads.cpp @@ -14,6 +14,13 @@ CLayerQuads::CLayerQuads() m_Image = -1; } +CLayerQuads::CLayerQuads(const CLayerQuads &Other) : + CLayer(Other) +{ + m_Image = Other.m_Image; + m_vQuads = Other.m_vQuads; +} + CLayerQuads::~CLayerQuads() = default; void CLayerQuads::Render(bool QuadPicker) @@ -255,3 +262,8 @@ void CLayerQuads::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) Func(&Quad.m_ColorEnv); } } + +CLayer *CLayerQuads::Duplicate() const +{ + return new CLayerQuads(*this); +} diff --git a/src/game/editor/layer_sounds.cpp b/src/game/editor/layer_sounds.cpp index 279be18b1..5937d2f61 100644 --- a/src/game/editor/layer_sounds.cpp +++ b/src/game/editor/layer_sounds.cpp @@ -12,6 +12,13 @@ CLayerSounds::CLayerSounds() m_Sound = -1; } +CLayerSounds::CLayerSounds(const CLayerSounds &Other) : + CLayer(Other) +{ + m_Sound = Other.m_Sound; + m_vSources = Other.m_vSources; +} + CLayerSounds::~CLayerSounds() = default; void CLayerSounds::Render(bool Tileset) @@ -219,3 +226,8 @@ void CLayerSounds::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func) Func(&Source.m_PosEnv); } } + +CLayer *CLayerSounds::Duplicate() const +{ + return new CLayerSounds(*this); +} diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index bc1ab3f1d..98f74ec81 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -40,6 +40,33 @@ CLayerTiles::CLayerTiles(int w, int h) mem_zero(m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile)); } +CLayerTiles::CLayerTiles(const CLayerTiles &Other) : + CLayer(Other) +{ + m_Width = Other.m_Width; + m_Height = Other.m_Height; + m_pTiles = new CTile[m_Width * m_Height]; + mem_copy(m_pTiles, Other.m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile)); + + m_Image = Other.m_Image; + m_Texture = Other.m_Texture; + m_Game = Other.m_Game; + m_Color = Other.m_Color; + m_ColorEnv = Other.m_ColorEnv; + m_ColorEnvOffset = Other.m_ColorEnvOffset; + + m_AutoMapperConfig = Other.m_AutoMapperConfig; + m_Seed = Other.m_Seed; + m_AutoAutoMap = Other.m_AutoAutoMap; + m_Tele = Other.m_Tele; + m_Speedup = Other.m_Speedup; + m_Front = Other.m_Front; + m_Switch = Other.m_Switch; + m_Tune = Other.m_Tune; + + mem_copy(m_aFileName, Other.m_aFileName, IO_MAX_PATH_LENGTH); +} + CLayerTiles::~CLayerTiles() { delete[] m_pTiles; @@ -571,6 +598,11 @@ void CLayerTiles::BrushRotate(float Amount) } } +CLayer *CLayerTiles::Duplicate() const +{ + return new CLayerTiles(*this); +} + void CLayerTiles::Resize(int NewW, int NewH) { CTile *pNewData = new CTile[NewW * NewH]; diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index a5578db39..3b6b29716 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -397,6 +397,21 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View, void *pContext) return CLayerTiles::RenderCommonProperties(pPopup->m_CommonPropState, pEditor, &View, pPopup->m_vpLayers); } + // duplicate layer button + CUIRect DupButton; + static int s_DuplicationButton = 0; + View.HSplitBottom(4.0f, &View, nullptr); + View.HSplitBottom(12.0f, &View, &DupButton); + + if(!pEditor->IsSpecialLayer(pEditor->GetSelectedLayer(0))) + { + if(pEditor->DoButton_Editor(&s_DuplicationButton, "Duplicate layer", 0, &DupButton, 0, "Duplicates the layer")) + { + pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->DuplicateLayer(pEditor->m_vSelectedLayers[0]); + return 1; + } + } + // don't allow deletion of game layer if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) && pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer"))