mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-17 13:38:18 +00:00
Add quick actions for game tiles
This commit is contained in:
parent
36f0bcc509
commit
e1cb617c42
|
@ -2462,6 +2462,7 @@ if(CLIENT)
|
|||
editor_trackers.cpp
|
||||
editor_trackers.h
|
||||
editor_ui.h
|
||||
enums.h
|
||||
explanations.cpp
|
||||
layer_selector.cpp
|
||||
layer_selector.h
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <game/client/ui_listbox.h>
|
||||
#include <game/mapitems.h>
|
||||
|
||||
#include <game/editor/enums.h>
|
||||
#include <game/editor/mapitems/envelope.h>
|
||||
#include <game/editor/mapitems/layer.h>
|
||||
#include <game/editor/mapitems/layer_front.h>
|
||||
|
@ -323,6 +324,8 @@ public:
|
|||
const CMapView *MapView() const { return &m_MapView; }
|
||||
CLayerSelector *LayerSelector() { return &m_LayerSelector; }
|
||||
|
||||
void FillGameTiles(EGameTileOp FillTile) const;
|
||||
bool CanFillGameTiles() const;
|
||||
void AddGroup();
|
||||
void AddTileLayer();
|
||||
void LayerSelectImage();
|
||||
|
|
36
src/game/editor/enums.h
Normal file
36
src/game/editor/enums.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef GAME_EDITOR_ENUMS_H
|
||||
#define GAME_EDITOR_ENUMS_H
|
||||
|
||||
constexpr const char *g_apGametileOpNames[] = {
|
||||
"Air",
|
||||
"Hookable",
|
||||
"Death",
|
||||
"Unhookable",
|
||||
"Hookthrough",
|
||||
"Freeze",
|
||||
"Unfreeze",
|
||||
"Deep Freeze",
|
||||
"Deep Unfreeze",
|
||||
"Blue Check-Tele",
|
||||
"Red Check-Tele",
|
||||
"Live Freeze",
|
||||
"Live Unfreeze",
|
||||
};
|
||||
enum class EGameTileOp
|
||||
{
|
||||
AIR,
|
||||
HOOKABLE,
|
||||
DEATH,
|
||||
UNHOOKABLE,
|
||||
HOOKTHROUGH,
|
||||
FREEZE,
|
||||
UNFREEZE,
|
||||
DEEP_FREEZE,
|
||||
DEEP_UNFREEZE,
|
||||
BLUE_CHECK_TELE,
|
||||
RED_CHECK_TELE,
|
||||
LIVE_FREEZE,
|
||||
LIVE_UNFREEZE,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
#include <engine/shared/map.h>
|
||||
#include <game/editor/editor.h>
|
||||
#include <game/editor/editor_actions.h>
|
||||
#include <game/editor/enums.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
|
@ -693,93 +694,126 @@ void CLayerTiles::ShowInfo()
|
|||
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
|
||||
}
|
||||
|
||||
CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
||||
void CLayerTiles::FillGameTiles(EGameTileOp Fill)
|
||||
{
|
||||
CUIRect Button;
|
||||
|
||||
const bool EntitiesLayer = IsEntitiesLayer();
|
||||
if(!CanFillGameTiles())
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayerGroup> pGroup = m_pEditor->m_Map.m_vpGroups[m_pEditor->m_SelectedGroup];
|
||||
|
||||
// Game tiles can only be constructed if the layer is relative to the game layer
|
||||
if(!EntitiesLayer && !(pGroup->m_OffsetX % 32) && !(pGroup->m_OffsetY % 32) && pGroup->m_ParallaxX == 100 && pGroup->m_ParallaxY == 100)
|
||||
int Result = (int)Fill;
|
||||
switch(Fill)
|
||||
{
|
||||
pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
|
||||
static int s_GameTilesButton = 0;
|
||||
if(m_pEditor->DoButton_Editor(&s_GameTilesButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer"))
|
||||
m_pEditor->PopupSelectGametileOpInvoke(m_pEditor->Ui()->MouseX(), m_pEditor->Ui()->MouseY());
|
||||
const int Selected = m_pEditor->PopupSelectGameTileOpResult();
|
||||
int Result = Selected;
|
||||
switch(Selected)
|
||||
case EGameTileOp::HOOKTHROUGH:
|
||||
Result = TILE_THROUGH_CUT;
|
||||
break;
|
||||
case EGameTileOp::FREEZE:
|
||||
Result = TILE_FREEZE;
|
||||
break;
|
||||
case EGameTileOp::UNFREEZE:
|
||||
Result = TILE_UNFREEZE;
|
||||
break;
|
||||
case EGameTileOp::DEEP_FREEZE:
|
||||
Result = TILE_DFREEZE;
|
||||
break;
|
||||
case EGameTileOp::DEEP_UNFREEZE:
|
||||
Result = TILE_DUNFREEZE;
|
||||
break;
|
||||
case EGameTileOp::BLUE_CHECK_TELE:
|
||||
Result = TILE_TELECHECKIN;
|
||||
break;
|
||||
case EGameTileOp::RED_CHECK_TELE:
|
||||
Result = TILE_TELECHECKINEVIL;
|
||||
break;
|
||||
case EGameTileOp::LIVE_FREEZE:
|
||||
Result = TILE_LFREEZE;
|
||||
break;
|
||||
case EGameTileOp::LIVE_UNFREEZE:
|
||||
Result = TILE_LUNFREEZE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(Result > -1)
|
||||
{
|
||||
const int OffsetX = -pGroup->m_OffsetX / 32;
|
||||
const int OffsetY = -pGroup->m_OffsetY / 32;
|
||||
|
||||
std::vector<std::shared_ptr<IEditorAction>> vpActions;
|
||||
std::shared_ptr<CLayerTiles> pGLayer = m_pEditor->m_Map.m_pGameLayer;
|
||||
int GameLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pGLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin();
|
||||
|
||||
if(Result != TILE_TELECHECKIN && Result != TILE_TELECHECKINEVIL)
|
||||
{
|
||||
case 4:
|
||||
Result = TILE_THROUGH_CUT;
|
||||
break;
|
||||
case 5:
|
||||
Result = TILE_FREEZE;
|
||||
break;
|
||||
case 6:
|
||||
Result = TILE_UNFREEZE;
|
||||
break;
|
||||
case 7:
|
||||
Result = TILE_DFREEZE;
|
||||
break;
|
||||
case 8:
|
||||
Result = TILE_DUNFREEZE;
|
||||
break;
|
||||
case 9:
|
||||
Result = TILE_TELECHECKIN;
|
||||
break;
|
||||
case 10:
|
||||
Result = TILE_TELECHECKINEVIL;
|
||||
break;
|
||||
case 11:
|
||||
Result = TILE_LFREEZE;
|
||||
break;
|
||||
case 12:
|
||||
Result = TILE_LUNFREEZE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(Result > -1)
|
||||
{
|
||||
const int OffsetX = -pGroup->m_OffsetX / 32;
|
||||
const int OffsetY = -pGroup->m_OffsetY / 32;
|
||||
|
||||
static const char *s_apGametileOpNames[] = {
|
||||
"Air",
|
||||
"Hookable",
|
||||
"Death",
|
||||
"Unhookable",
|
||||
"Hookthrough",
|
||||
"Freeze",
|
||||
"Unfreeze",
|
||||
"Deep Freeze",
|
||||
"Deep Unfreeze",
|
||||
"Blue Check-Tele",
|
||||
"Red Check-Tele",
|
||||
"Live Freeze",
|
||||
"Live Unfreeze",
|
||||
};
|
||||
|
||||
std::vector<std::shared_ptr<IEditorAction>> vpActions;
|
||||
std::shared_ptr<CLayerTiles> pGLayer = m_pEditor->m_Map.m_pGameLayer;
|
||||
int GameLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pGLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin();
|
||||
|
||||
if(Result != TILE_TELECHECKIN && Result != TILE_TELECHECKINEVIL)
|
||||
if(pGLayer->m_Width < m_Width + OffsetX || pGLayer->m_Height < m_Height + OffsetY)
|
||||
{
|
||||
if(pGLayer->m_Width < m_Width + OffsetX || pGLayer->m_Height < m_Height + OffsetY)
|
||||
std::map<int, std::shared_ptr<CLayer>> savedLayers;
|
||||
savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate();
|
||||
savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES];
|
||||
|
||||
int PrevW = pGLayer->m_Width;
|
||||
int PrevH = pGLayer->m_Height;
|
||||
const int NewW = pGLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pGLayer->m_Width;
|
||||
const int NewH = pGLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pGLayer->m_Height;
|
||||
pGLayer->Resize(NewW, NewH);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW));
|
||||
const std::shared_ptr<CEditorActionEditLayerTilesProp> &Action1 = std::static_pointer_cast<CEditorActionEditLayerTilesProp>(vpActions[vpActions.size() - 1]);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH));
|
||||
const std::shared_ptr<CEditorActionEditLayerTilesProp> &Action2 = std::static_pointer_cast<CEditorActionEditLayerTilesProp>(vpActions[vpActions.size() - 1]);
|
||||
|
||||
Action1->SetSavedLayers(savedLayers);
|
||||
Action2->SetSavedLayers(savedLayers);
|
||||
}
|
||||
|
||||
int Changes = 0;
|
||||
for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++)
|
||||
{
|
||||
for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++)
|
||||
{
|
||||
if(GetTile(x, y).m_Index)
|
||||
{
|
||||
const CTile ResultTile = {(unsigned char)Result};
|
||||
pGLayer->SetTile(x + OffsetX, y + OffsetY, ResultTile);
|
||||
Changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorBrushDrawAction>(m_pEditor, m_pEditor->m_SelectedGroup));
|
||||
char aDisplay[256];
|
||||
str_format(aDisplay, sizeof(aDisplay), "Construct '%s' game tiles (x%d)", g_apGametileOpNames[(int)Fill], Changes);
|
||||
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions, aDisplay, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!m_pEditor->m_Map.m_pTeleLayer)
|
||||
{
|
||||
std::shared_ptr<CLayerTele> pLayer = std::make_shared<CLayerTele>(m_pEditor, m_Width, m_Height);
|
||||
m_pEditor->m_Map.MakeTeleLayer(pLayer);
|
||||
m_pEditor->m_Map.m_pGameGroup->AddLayer(pLayer);
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorActionAddLayer>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_Map.m_pGameGroup->m_vpLayers.size() - 1));
|
||||
|
||||
if(m_Width != pGLayer->m_Width || m_Height > pGLayer->m_Height)
|
||||
{
|
||||
std::map<int, std::shared_ptr<CLayer>> savedLayers;
|
||||
savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate();
|
||||
savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES];
|
||||
|
||||
int NewW = pGLayer->m_Width;
|
||||
int NewH = pGLayer->m_Height;
|
||||
if(m_Width > pGLayer->m_Width)
|
||||
{
|
||||
NewW = m_Width;
|
||||
}
|
||||
if(m_Height > pGLayer->m_Height)
|
||||
{
|
||||
NewH = m_Height;
|
||||
}
|
||||
|
||||
int PrevW = pGLayer->m_Width;
|
||||
int PrevH = pGLayer->m_Height;
|
||||
const int NewW = pGLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pGLayer->m_Width;
|
||||
const int NewH = pGLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pGLayer->m_Height;
|
||||
pGLayer->Resize(NewW, NewH);
|
||||
pLayer->Resize(NewW, NewH);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW));
|
||||
const std::shared_ptr<CEditorActionEditLayerTilesProp> &Action1 = std::static_pointer_cast<CEditorActionEditLayerTilesProp>(vpActions[vpActions.size() - 1]);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH));
|
||||
|
@ -788,124 +822,94 @@ CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
Action1->SetSavedLayers(savedLayers);
|
||||
Action2->SetSavedLayers(savedLayers);
|
||||
}
|
||||
|
||||
int Changes = 0;
|
||||
for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++)
|
||||
{
|
||||
for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++)
|
||||
{
|
||||
if(GetTile(x, y).m_Index)
|
||||
{
|
||||
const CTile ResultTile = {(unsigned char)Result};
|
||||
pGLayer->SetTile(x + OffsetX, y + OffsetY, ResultTile);
|
||||
Changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorBrushDrawAction>(m_pEditor, m_pEditor->m_SelectedGroup));
|
||||
char aDisplay[256];
|
||||
str_format(aDisplay, sizeof(aDisplay), "Construct '%s' game tiles (x%d)", s_apGametileOpNames[Selected], Changes);
|
||||
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions, aDisplay, true));
|
||||
}
|
||||
else
|
||||
|
||||
std::shared_ptr<CLayerTele> pTLayer = m_pEditor->m_Map.m_pTeleLayer;
|
||||
int TeleLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pTLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin();
|
||||
|
||||
if(pTLayer->m_Width < m_Width + OffsetX || pTLayer->m_Height < m_Height + OffsetY)
|
||||
{
|
||||
if(!m_pEditor->m_Map.m_pTeleLayer)
|
||||
{
|
||||
std::shared_ptr<CLayerTele> pLayer = std::make_shared<CLayerTele>(m_pEditor, m_Width, m_Height);
|
||||
m_pEditor->m_Map.MakeTeleLayer(pLayer);
|
||||
m_pEditor->m_Map.m_pGameGroup->AddLayer(pLayer);
|
||||
std::map<int, std::shared_ptr<CLayer>> savedLayers;
|
||||
savedLayers[LAYERTYPE_TILES] = pTLayer->Duplicate();
|
||||
savedLayers[LAYERTYPE_TELE] = savedLayers[LAYERTYPE_TILES];
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorActionAddLayer>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_Map.m_pGameGroup->m_vpLayers.size() - 1));
|
||||
int PrevW = pTLayer->m_Width;
|
||||
int PrevH = pTLayer->m_Height;
|
||||
int NewW = pTLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pTLayer->m_Width;
|
||||
int NewH = pTLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pTLayer->m_Height;
|
||||
pTLayer->Resize(NewW, NewH);
|
||||
std::shared_ptr<CEditorActionEditLayerTilesProp> Action1, Action2;
|
||||
vpActions.push_back(Action1 = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW));
|
||||
vpActions.push_back(Action2 = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH));
|
||||
|
||||
if(m_Width != pGLayer->m_Width || m_Height > pGLayer->m_Height)
|
||||
{
|
||||
std::map<int, std::shared_ptr<CLayer>> savedLayers;
|
||||
savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate();
|
||||
savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES];
|
||||
|
||||
int NewW = pGLayer->m_Width;
|
||||
int NewH = pGLayer->m_Height;
|
||||
if(m_Width > pGLayer->m_Width)
|
||||
{
|
||||
NewW = m_Width;
|
||||
}
|
||||
if(m_Height > pGLayer->m_Height)
|
||||
{
|
||||
NewH = m_Height;
|
||||
}
|
||||
|
||||
int PrevW = pGLayer->m_Width;
|
||||
int PrevH = pGLayer->m_Height;
|
||||
pLayer->Resize(NewW, NewH);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW));
|
||||
const std::shared_ptr<CEditorActionEditLayerTilesProp> &Action1 = std::static_pointer_cast<CEditorActionEditLayerTilesProp>(vpActions[vpActions.size() - 1]);
|
||||
vpActions.push_back(std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH));
|
||||
const std::shared_ptr<CEditorActionEditLayerTilesProp> &Action2 = std::static_pointer_cast<CEditorActionEditLayerTilesProp>(vpActions[vpActions.size() - 1]);
|
||||
|
||||
Action1->SetSavedLayers(savedLayers);
|
||||
Action2->SetSavedLayers(savedLayers);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CLayerTele> pTLayer = m_pEditor->m_Map.m_pTeleLayer;
|
||||
int TeleLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pTLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin();
|
||||
|
||||
if(pTLayer->m_Width < m_Width + OffsetX || pTLayer->m_Height < m_Height + OffsetY)
|
||||
{
|
||||
std::map<int, std::shared_ptr<CLayer>> savedLayers;
|
||||
savedLayers[LAYERTYPE_TILES] = pTLayer->Duplicate();
|
||||
savedLayers[LAYERTYPE_TELE] = savedLayers[LAYERTYPE_TILES];
|
||||
|
||||
int PrevW = pTLayer->m_Width;
|
||||
int PrevH = pTLayer->m_Height;
|
||||
int NewW = pTLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pTLayer->m_Width;
|
||||
int NewH = pTLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pTLayer->m_Height;
|
||||
pTLayer->Resize(NewW, NewH);
|
||||
std::shared_ptr<CEditorActionEditLayerTilesProp> Action1, Action2;
|
||||
vpActions.push_back(Action1 = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW));
|
||||
vpActions.push_back(Action2 = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH));
|
||||
|
||||
Action1->SetSavedLayers(savedLayers);
|
||||
Action2->SetSavedLayers(savedLayers);
|
||||
}
|
||||
|
||||
int Changes = 0;
|
||||
for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++)
|
||||
{
|
||||
for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++)
|
||||
{
|
||||
if(GetTile(x, y).m_Index)
|
||||
{
|
||||
auto TileIndex = (y + OffsetY) * pTLayer->m_Width + x + OffsetX;
|
||||
Changes++;
|
||||
|
||||
STeleTileStateChange::SData Previous{
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number,
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type,
|
||||
pTLayer->m_pTiles[TileIndex].m_Index};
|
||||
|
||||
pTLayer->m_pTiles[TileIndex].m_Index = TILE_AIR + Result;
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number = 1;
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type = TILE_AIR + Result;
|
||||
|
||||
STeleTileStateChange::SData Current{
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number,
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type,
|
||||
pTLayer->m_pTiles[TileIndex].m_Index};
|
||||
|
||||
pTLayer->RecordStateChange(x, y, Previous, Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorBrushDrawAction>(m_pEditor, m_pEditor->m_SelectedGroup));
|
||||
char aDisplay[256];
|
||||
str_format(aDisplay, sizeof(aDisplay), "Construct 'tele' game tiles (x%d)", Changes);
|
||||
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions, aDisplay, true));
|
||||
Action1->SetSavedLayers(savedLayers);
|
||||
Action2->SetSavedLayers(savedLayers);
|
||||
}
|
||||
|
||||
int Changes = 0;
|
||||
for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++)
|
||||
{
|
||||
for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++)
|
||||
{
|
||||
if(GetTile(x, y).m_Index)
|
||||
{
|
||||
auto TileIndex = (y + OffsetY) * pTLayer->m_Width + x + OffsetX;
|
||||
Changes++;
|
||||
|
||||
STeleTileStateChange::SData Previous{
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number,
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type,
|
||||
pTLayer->m_pTiles[TileIndex].m_Index};
|
||||
|
||||
pTLayer->m_pTiles[TileIndex].m_Index = TILE_AIR + Result;
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number = 1;
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type = TILE_AIR + Result;
|
||||
|
||||
STeleTileStateChange::SData Current{
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Number,
|
||||
pTLayer->m_pTeleTile[TileIndex].m_Type,
|
||||
pTLayer->m_pTiles[TileIndex].m_Index};
|
||||
|
||||
pTLayer->RecordStateChange(x, y, Previous, Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vpActions.push_back(std::make_shared<CEditorBrushDrawAction>(m_pEditor, m_pEditor->m_SelectedGroup));
|
||||
char aDisplay[256];
|
||||
str_format(aDisplay, sizeof(aDisplay), "Construct 'tele' game tiles (x%d)", Changes);
|
||||
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions, aDisplay, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CLayerTiles::CanFillGameTiles() const
|
||||
{
|
||||
const bool EntitiesLayer = IsEntitiesLayer();
|
||||
if(EntitiesLayer)
|
||||
return false;
|
||||
|
||||
std::shared_ptr<CLayerGroup> pGroup = m_pEditor->m_Map.m_vpGroups[m_pEditor->m_SelectedGroup];
|
||||
|
||||
// Game tiles can only be constructed if the layer is relative to the game layer
|
||||
return !(pGroup->m_OffsetX % 32) && !(pGroup->m_OffsetY % 32) && pGroup->m_ParallaxX == 100 && pGroup->m_ParallaxY == 100;
|
||||
}
|
||||
|
||||
CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
||||
{
|
||||
CUIRect Button;
|
||||
|
||||
const bool EntitiesLayer = IsEntitiesLayer();
|
||||
|
||||
if(CanFillGameTiles())
|
||||
{
|
||||
pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
|
||||
static int s_GameTilesButton = 0;
|
||||
if(m_pEditor->DoButton_Editor(&s_GameTilesButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer"))
|
||||
m_pEditor->PopupSelectGametileOpInvoke(m_pEditor->Ui()->MouseX(), m_pEditor->Ui()->MouseY());
|
||||
const int Selected = m_pEditor->PopupSelectGameTileOpResult();
|
||||
FillGameTiles((EGameTileOp)Selected);
|
||||
}
|
||||
|
||||
if(m_pEditor->m_Map.m_pGameLayer.get() != this)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define GAME_EDITOR_MAPITEMS_LAYER_TILES_H
|
||||
|
||||
#include <game/editor/editor_trackers.h>
|
||||
#include <game/editor/enums.h>
|
||||
#include <map>
|
||||
|
||||
#include "layer.h"
|
||||
|
@ -122,6 +123,8 @@ public:
|
|||
void BrushSelecting(CUIRect Rect) override;
|
||||
int BrushGrab(std::shared_ptr<CLayerGroup> pBrush, CUIRect Rect) override;
|
||||
void FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect) override;
|
||||
void FillGameTiles(EGameTileOp Fill);
|
||||
bool CanFillGameTiles() const;
|
||||
void BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy) override;
|
||||
void BrushFlipX() override;
|
||||
void BrushFlipY() override;
|
||||
|
|
|
@ -4,12 +4,28 @@
|
|||
|
||||
#include "editor_actions.h"
|
||||
|
||||
void CEditor::FillGameTiles(EGameTileOp FillTile) const
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTileLayer = std::static_pointer_cast<CLayerTiles>(GetSelectedLayerType(0, LAYERTYPE_TILES));
|
||||
if(pTileLayer)
|
||||
pTileLayer->FillGameTiles(FillTile);
|
||||
}
|
||||
|
||||
bool CEditor::CanFillGameTiles() const
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTileLayer = std::static_pointer_cast<CLayerTiles>(GetSelectedLayerType(0, LAYERTYPE_TILES));
|
||||
if(pTileLayer)
|
||||
return pTileLayer->CanFillGameTiles();
|
||||
return false;
|
||||
}
|
||||
|
||||
void CEditor::AddGroup()
|
||||
{
|
||||
m_Map.NewGroup();
|
||||
m_SelectedGroup = m_Map.m_vpGroups.size() - 1;
|
||||
m_EditorHistory.RecordAction(std::make_shared<CEditorActionGroup>(this, m_SelectedGroup, false));
|
||||
}
|
||||
|
||||
void CEditor::AddTileLayer()
|
||||
{
|
||||
std::shared_ptr<CLayer> pTileLayer = std::make_shared<CLayerTiles>(this, m_Map.m_pGameLayer->m_Width, m_Map.m_pGameLayer->m_Height);
|
||||
|
|
|
@ -7,6 +7,110 @@
|
|||
#define ALWAYS_FALSE []() -> bool { return false; }
|
||||
#define DEFAULT_BTN []() -> int { return -1; }
|
||||
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesAir,
|
||||
"Game tiles: Air",
|
||||
[&]() { FillGameTiles(EGameTileOp::AIR); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesHookable,
|
||||
"Game tiles: Hookable",
|
||||
[&]() { FillGameTiles(EGameTileOp::HOOKABLE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesDeath,
|
||||
"Game tiles: Death",
|
||||
[&]() { FillGameTiles(EGameTileOp::DEATH); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesUnhookable,
|
||||
"Game tiles: Unhookable",
|
||||
[&]() { FillGameTiles(EGameTileOp::UNHOOKABLE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesHookthrough,
|
||||
"Game tiles: Hookthrough",
|
||||
[&]() { FillGameTiles(EGameTileOp::HOOKTHROUGH); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesFreeze,
|
||||
"Game tiles: Freeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::FREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesUnfreeze,
|
||||
"Game tiles: Unfreeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::UNFREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesDeepFreeze,
|
||||
"Game tiles: Deep Freeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::DEEP_FREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesDeepUnfreeze,
|
||||
"Game tiles: Deep Unfreeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::DEEP_UNFREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesBlueCheckTele,
|
||||
"Game tiles: Blue Check Tele",
|
||||
[&]() { FillGameTiles(EGameTileOp::BLUE_CHECK_TELE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesRedCheckTele,
|
||||
"Game tiles: Red Check Tele",
|
||||
[&]() { FillGameTiles(EGameTileOp::RED_CHECK_TELE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesLiveFreeze,
|
||||
"Game tiles: Live Freeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::LIVE_FREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
GameTilesLiveUnfreeze,
|
||||
"Game tiles: Live Unfreeze",
|
||||
[&]() { FillGameTiles(EGameTileOp::LIVE_UNFREEZE); },
|
||||
[&]() -> bool { return !CanFillGameTiles(); },
|
||||
ALWAYS_FALSE,
|
||||
DEFAULT_BTN,
|
||||
"")
|
||||
REGISTER_QUICK_ACTION(
|
||||
AddGroup, "Add group", [&]() { AddGroup(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Adds a new group")
|
||||
REGISTER_QUICK_ACTION(
|
||||
|
|
Loading…
Reference in a new issue