mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge pull request #7082 from Marmare314/editor-seperate-mapitems
extract code from editor mapitems into separate files
This commit is contained in:
commit
c7f3be7d75
|
@ -2303,7 +2303,7 @@ if(CLIENT)
|
|||
ui_scrollregion.cpp
|
||||
ui_scrollregion.h
|
||||
)
|
||||
set_src(GAME_EDITOR GLOB src/game/editor
|
||||
set_src(GAME_EDITOR GLOB_RECURSE src/game/editor
|
||||
auto_map.cpp
|
||||
auto_map.h
|
||||
component.cpp
|
||||
|
@ -2312,14 +2312,23 @@ if(CLIENT)
|
|||
editor.h
|
||||
explanations.cpp
|
||||
io.cpp
|
||||
layer_game.cpp
|
||||
layer_quads.cpp
|
||||
layer_sounds.cpp
|
||||
layer_tiles.cpp
|
||||
map_grid.cpp
|
||||
map_grid.h
|
||||
map_view.cpp
|
||||
map_view.h
|
||||
mapitems/image.cpp
|
||||
mapitems/layer_front.cpp
|
||||
mapitems/layer_game.cpp
|
||||
mapitems/layer_group.cpp
|
||||
mapitems/layer_quads.cpp
|
||||
mapitems/layer_sounds.cpp
|
||||
mapitems/layer_speedup.cpp
|
||||
mapitems/layer_switch.cpp
|
||||
mapitems/layer_tele.cpp
|
||||
mapitems/layer_tiles.cpp
|
||||
mapitems/layer_tune.cpp
|
||||
mapitems/map.cpp
|
||||
mapitems/sound.cpp
|
||||
popups.cpp
|
||||
proof_mode.cpp
|
||||
proof_mode.h
|
||||
|
|
|
@ -87,206 +87,6 @@ enum
|
|||
BUTTON_CONTEXT = 1,
|
||||
};
|
||||
|
||||
CEditorImage::~CEditorImage()
|
||||
{
|
||||
m_pEditor->Graphics()->UnloadTexture(&m_Texture);
|
||||
free(m_pData);
|
||||
m_pData = nullptr;
|
||||
}
|
||||
|
||||
CEditorSound::~CEditorSound()
|
||||
{
|
||||
m_pEditor->Sound()->UnloadSample(m_SoundID);
|
||||
free(m_pData);
|
||||
m_pData = nullptr;
|
||||
}
|
||||
|
||||
CLayerGroup::CLayerGroup()
|
||||
{
|
||||
m_vpLayers.clear();
|
||||
m_aName[0] = 0;
|
||||
m_Visible = true;
|
||||
m_Collapse = false;
|
||||
m_GameGroup = false;
|
||||
m_OffsetX = 0;
|
||||
m_OffsetY = 0;
|
||||
m_ParallaxX = 100;
|
||||
m_ParallaxY = 100;
|
||||
m_CustomParallaxZoom = 0;
|
||||
m_ParallaxZoom = 100;
|
||||
|
||||
m_UseClipping = 0;
|
||||
m_ClipX = 0;
|
||||
m_ClipY = 0;
|
||||
m_ClipW = 0;
|
||||
m_ClipH = 0;
|
||||
}
|
||||
|
||||
CLayerGroup::~CLayerGroup()
|
||||
{
|
||||
m_vpLayers.clear();
|
||||
}
|
||||
|
||||
void CLayerGroup::Convert(CUIRect *pRect)
|
||||
{
|
||||
pRect->x += m_OffsetX;
|
||||
pRect->y += m_OffsetY;
|
||||
}
|
||||
|
||||
void CLayerGroup::Mapping(float *pPoints)
|
||||
{
|
||||
float ParallaxZoom = m_pMap->m_pEditor->m_PreviewZoom ? m_ParallaxZoom : 100.0f;
|
||||
|
||||
m_pMap->m_pEditor->RenderTools()->MapScreenToWorld(
|
||||
m_pMap->m_pEditor->MapView()->GetWorldOffset().x, m_pMap->m_pEditor->MapView()->GetWorldOffset().y,
|
||||
m_ParallaxX, m_ParallaxY, ParallaxZoom, m_OffsetX, m_OffsetY,
|
||||
m_pMap->m_pEditor->Graphics()->ScreenAspect(), m_pMap->m_pEditor->MapView()->GetWorldZoom(), pPoints);
|
||||
|
||||
pPoints[0] += m_pMap->m_pEditor->MapView()->GetEditorOffset().x;
|
||||
pPoints[1] += m_pMap->m_pEditor->MapView()->GetEditorOffset().y;
|
||||
pPoints[2] += m_pMap->m_pEditor->MapView()->GetEditorOffset().x;
|
||||
pPoints[3] += m_pMap->m_pEditor->MapView()->GetEditorOffset().y;
|
||||
}
|
||||
|
||||
void CLayerGroup::MapScreen()
|
||||
{
|
||||
float aPoints[4];
|
||||
Mapping(aPoints);
|
||||
m_pMap->m_pEditor->Graphics()->MapScreen(aPoints[0], aPoints[1], aPoints[2], aPoints[3]);
|
||||
}
|
||||
|
||||
void CLayerGroup::Render()
|
||||
{
|
||||
MapScreen();
|
||||
IGraphics *pGraphics = m_pMap->m_pEditor->Graphics();
|
||||
|
||||
if(m_UseClipping)
|
||||
{
|
||||
float aPoints[4];
|
||||
m_pMap->m_pGameGroup->Mapping(aPoints);
|
||||
float x0 = (m_ClipX - aPoints[0]) / (aPoints[2] - aPoints[0]);
|
||||
float y0 = (m_ClipY - aPoints[1]) / (aPoints[3] - aPoints[1]);
|
||||
float x1 = ((m_ClipX + m_ClipW) - aPoints[0]) / (aPoints[2] - aPoints[0]);
|
||||
float y1 = ((m_ClipY + m_ClipH) - aPoints[1]) / (aPoints[3] - aPoints[1]);
|
||||
|
||||
pGraphics->ClipEnable((int)(x0 * pGraphics->ScreenWidth()), (int)(y0 * pGraphics->ScreenHeight()),
|
||||
(int)((x1 - x0) * pGraphics->ScreenWidth()), (int)((y1 - y0) * pGraphics->ScreenHeight()));
|
||||
}
|
||||
|
||||
for(auto &pLayer : m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Visible)
|
||||
{
|
||||
if(pLayer->m_Type == LAYERTYPE_TILES)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
if(pTiles->m_Game || pTiles->m_Front || pTiles->m_Tele || pTiles->m_Speedup || pTiles->m_Tune || pTiles->m_Switch)
|
||||
continue;
|
||||
}
|
||||
if(m_pMap->m_pEditor->m_ShowDetail || !(pLayer->m_Flags & LAYERFLAG_DETAIL))
|
||||
pLayer->Render();
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &pLayer : m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Visible && pLayer->m_Type == LAYERTYPE_TILES && pLayer != m_pMap->m_pGameLayer && pLayer != m_pMap->m_pFrontLayer && pLayer != m_pMap->m_pTeleLayer && pLayer != m_pMap->m_pSpeedupLayer && pLayer != m_pMap->m_pSwitchLayer && pLayer != m_pMap->m_pTuneLayer)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
if(pTiles->m_Game || pTiles->m_Front || pTiles->m_Tele || pTiles->m_Speedup || pTiles->m_Tune || pTiles->m_Switch)
|
||||
{
|
||||
pLayer->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_UseClipping)
|
||||
pGraphics->ClipDisable();
|
||||
}
|
||||
|
||||
void CLayerGroup::AddLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pMap->OnModify();
|
||||
m_vpLayers.push_back(pLayer);
|
||||
}
|
||||
|
||||
void CLayerGroup::DeleteLayer(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpLayers.size())
|
||||
return;
|
||||
m_vpLayers.erase(m_vpLayers.begin() + Index);
|
||||
m_pMap->OnModify();
|
||||
}
|
||||
|
||||
void CLayerGroup::DuplicateLayer(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpLayers.size())
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayer> pDup = m_vpLayers[Index]->Duplicate();
|
||||
m_vpLayers.insert(m_vpLayers.begin() + Index + 1, pDup);
|
||||
|
||||
m_pMap->OnModify();
|
||||
}
|
||||
|
||||
void CLayerGroup::GetSize(float *pWidth, float *pHeight) const
|
||||
{
|
||||
*pWidth = 0;
|
||||
*pHeight = 0;
|
||||
for(const auto &pLayer : m_vpLayers)
|
||||
{
|
||||
float lw, lh;
|
||||
pLayer->GetSize(&lw, &lh);
|
||||
*pWidth = maximum(*pWidth, lw);
|
||||
*pHeight = maximum(*pHeight, lh);
|
||||
}
|
||||
}
|
||||
|
||||
int CLayerGroup::SwapLayers(int Index0, int Index1)
|
||||
{
|
||||
if(Index0 < 0 || Index0 >= (int)m_vpLayers.size())
|
||||
return Index0;
|
||||
if(Index1 < 0 || Index1 >= (int)m_vpLayers.size())
|
||||
return Index0;
|
||||
if(Index0 == Index1)
|
||||
return Index0;
|
||||
m_pMap->OnModify();
|
||||
std::swap(m_vpLayers[Index0], m_vpLayers[Index1]);
|
||||
return Index1;
|
||||
}
|
||||
|
||||
void CEditorImage::AnalyseTileFlags()
|
||||
{
|
||||
mem_zero(m_aTileFlags, sizeof(m_aTileFlags));
|
||||
|
||||
int tw = m_Width / 16; // tilesizes
|
||||
int th = m_Height / 16;
|
||||
if(tw == th && m_Format == CImageInfo::FORMAT_RGBA)
|
||||
{
|
||||
unsigned char *pPixelData = (unsigned char *)m_pData;
|
||||
|
||||
int TileID = 0;
|
||||
for(int ty = 0; ty < 16; ty++)
|
||||
for(int tx = 0; tx < 16; tx++, TileID++)
|
||||
{
|
||||
bool Opaque = true;
|
||||
for(int x = 0; x < tw; x++)
|
||||
for(int y = 0; y < th; y++)
|
||||
{
|
||||
int p = (ty * tw + y) * m_Width + tx * tw + x;
|
||||
if(pPixelData[p * 4 + 3] < 250)
|
||||
{
|
||||
Opaque = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(Opaque)
|
||||
m_aTileFlags[TileID] |= TILEFLAG_OPAQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEditor::EnvelopeEval(int TimeOffsetMillis, int Env, ColorRGBA &Channels, void *pUser)
|
||||
{
|
||||
CEditor *pThis = (CEditor *)pUser;
|
||||
|
@ -7625,154 +7425,6 @@ void CEditor::Reset(bool CreateDefault)
|
|||
m_SettingsCommandInput.Clear();
|
||||
}
|
||||
|
||||
void CEditorMap::OnModify()
|
||||
{
|
||||
m_Modified = true;
|
||||
m_ModifiedAuto = true;
|
||||
m_LastModifiedTime = m_pEditor->Client()->GlobalTime();
|
||||
}
|
||||
|
||||
void CEditorMap::DeleteEnvelope(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
|
||||
OnModify();
|
||||
|
||||
VisitEnvelopeReferences([Index](int &ElementIndex) {
|
||||
if(ElementIndex == Index)
|
||||
ElementIndex = -1;
|
||||
else if(ElementIndex > Index)
|
||||
ElementIndex--;
|
||||
});
|
||||
|
||||
m_vpEnvelopes.erase(m_vpEnvelopes.begin() + Index);
|
||||
}
|
||||
|
||||
void CEditorMap::SwapEnvelopes(int Index0, int Index1)
|
||||
{
|
||||
if(Index0 < 0 || Index0 >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
if(Index1 < 0 || Index1 >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
if(Index0 == Index1)
|
||||
return;
|
||||
|
||||
OnModify();
|
||||
|
||||
VisitEnvelopeReferences([Index0, Index1](int &ElementIndex) {
|
||||
if(ElementIndex == Index0)
|
||||
ElementIndex = Index1;
|
||||
else if(ElementIndex == Index1)
|
||||
ElementIndex = Index0;
|
||||
});
|
||||
|
||||
std::swap(m_vpEnvelopes[Index0], m_vpEnvelopes[Index1]);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void CEditorMap::VisitEnvelopeReferences(F &&Visitor)
|
||||
{
|
||||
for(auto &pGroup : m_vpGroups)
|
||||
{
|
||||
for(auto &pLayer : pGroup->m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Type == LAYERTYPE_QUADS)
|
||||
{
|
||||
std::shared_ptr<CLayerQuads> pLayerQuads = std::static_pointer_cast<CLayerQuads>(pLayer);
|
||||
for(auto &Quad : pLayerQuads->m_vQuads)
|
||||
{
|
||||
Visitor(Quad.m_PosEnv);
|
||||
Visitor(Quad.m_ColorEnv);
|
||||
}
|
||||
}
|
||||
else if(pLayer->m_Type == LAYERTYPE_TILES)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pLayerTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
Visitor(pLayerTiles->m_ColorEnv);
|
||||
}
|
||||
else if(pLayer->m_Type == LAYERTYPE_SOUNDS)
|
||||
{
|
||||
std::shared_ptr<CLayerSounds> pLayerSounds = std::static_pointer_cast<CLayerSounds>(pLayer);
|
||||
for(auto &Source : pLayerSounds->m_vSources)
|
||||
{
|
||||
Visitor(Source.m_PosEnv);
|
||||
Visitor(Source.m_SoundEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEditorMap::MakeGameLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pGameLayer = std::static_pointer_cast<CLayerGame>(pLayer);
|
||||
m_pGameLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeGameGroup(std::shared_ptr<CLayerGroup> pGroup)
|
||||
{
|
||||
m_pGameGroup = std::move(pGroup);
|
||||
m_pGameGroup->m_GameGroup = true;
|
||||
str_copy(m_pGameGroup->m_aName, "Game");
|
||||
}
|
||||
|
||||
void CEditorMap::Clean()
|
||||
{
|
||||
m_vpGroups.clear();
|
||||
m_vpEnvelopes.clear();
|
||||
m_vpImages.clear();
|
||||
m_vpSounds.clear();
|
||||
|
||||
m_MapInfo.Reset();
|
||||
m_MapInfoTmp.Reset();
|
||||
|
||||
m_vSettings.clear();
|
||||
|
||||
m_pGameLayer = nullptr;
|
||||
m_pGameGroup = nullptr;
|
||||
|
||||
m_Modified = false;
|
||||
m_ModifiedAuto = false;
|
||||
|
||||
m_pTeleLayer = nullptr;
|
||||
m_pSpeedupLayer = nullptr;
|
||||
m_pFrontLayer = nullptr;
|
||||
m_pSwitchLayer = nullptr;
|
||||
m_pTuneLayer = nullptr;
|
||||
}
|
||||
|
||||
void CEditorMap::CreateDefault(IGraphics::CTextureHandle EntitiesTexture)
|
||||
{
|
||||
// add background
|
||||
std::shared_ptr<CLayerGroup> pGroup = NewGroup();
|
||||
pGroup->m_ParallaxX = 0;
|
||||
pGroup->m_ParallaxY = 0;
|
||||
pGroup->m_CustomParallaxZoom = 0;
|
||||
pGroup->m_ParallaxZoom = 0;
|
||||
std::shared_ptr<CLayerQuads> pLayer = std::make_shared<CLayerQuads>();
|
||||
pLayer->m_pEditor = m_pEditor;
|
||||
CQuad *pQuad = pLayer->NewQuad(0, 0, 1600, 1200);
|
||||
pQuad->m_aColors[0].r = pQuad->m_aColors[1].r = 94;
|
||||
pQuad->m_aColors[0].g = pQuad->m_aColors[1].g = 132;
|
||||
pQuad->m_aColors[0].b = pQuad->m_aColors[1].b = 174;
|
||||
pQuad->m_aColors[2].r = pQuad->m_aColors[3].r = 204;
|
||||
pQuad->m_aColors[2].g = pQuad->m_aColors[3].g = 232;
|
||||
pQuad->m_aColors[2].b = pQuad->m_aColors[3].b = 255;
|
||||
pGroup->AddLayer(pLayer);
|
||||
|
||||
// add game layer and reset front, tele, speedup, tune and switch layer pointers
|
||||
MakeGameGroup(NewGroup());
|
||||
MakeGameLayer(std::make_shared<CLayerGame>(50, 50));
|
||||
m_pGameGroup->AddLayer(m_pGameLayer);
|
||||
|
||||
m_pFrontLayer = nullptr;
|
||||
m_pTeleLayer = nullptr;
|
||||
m_pSpeedupLayer = nullptr;
|
||||
m_pSwitchLayer = nullptr;
|
||||
m_pTuneLayer = nullptr;
|
||||
}
|
||||
|
||||
int CEditor::GetTextureUsageFlag()
|
||||
{
|
||||
return Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
||||
|
@ -8173,35 +7825,3 @@ void CEditor::LoadCurrentMap()
|
|||
}
|
||||
|
||||
IEditor *CreateEditor() { return new CEditor; }
|
||||
|
||||
// DDRace
|
||||
|
||||
void CEditorMap::MakeTeleLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pTeleLayer = std::static_pointer_cast<CLayerTele>(pLayer);
|
||||
m_pTeleLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeSpeedupLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pSpeedupLayer = std::static_pointer_cast<CLayerSpeedup>(pLayer);
|
||||
m_pSpeedupLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeFrontLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pFrontLayer = std::static_pointer_cast<CLayerFront>(pLayer);
|
||||
m_pFrontLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeSwitchLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pSwitchLayer = std::static_pointer_cast<CLayerSwitch>(pLayer);
|
||||
m_pSwitchLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeTuneLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pTuneLayer = std::static_pointer_cast<CLayerTune>(pLayer);
|
||||
m_pTuneLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
|
40
src/game/editor/mapitems/image.cpp
Normal file
40
src/game/editor/mapitems/image.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CEditorImage::~CEditorImage()
|
||||
{
|
||||
m_pEditor->Graphics()->UnloadTexture(&m_Texture);
|
||||
free(m_pData);
|
||||
m_pData = nullptr;
|
||||
}
|
||||
|
||||
void CEditorImage::AnalyseTileFlags()
|
||||
{
|
||||
mem_zero(m_aTileFlags, sizeof(m_aTileFlags));
|
||||
|
||||
int tw = m_Width / 16; // tilesizes
|
||||
int th = m_Height / 16;
|
||||
if(tw == th && m_Format == CImageInfo::FORMAT_RGBA)
|
||||
{
|
||||
unsigned char *pPixelData = (unsigned char *)m_pData;
|
||||
|
||||
int TileID = 0;
|
||||
for(int ty = 0; ty < 16; ty++)
|
||||
for(int tx = 0; tx < 16; tx++, TileID++)
|
||||
{
|
||||
bool Opaque = true;
|
||||
for(int x = 0; x < tw; x++)
|
||||
for(int y = 0; y < th; y++)
|
||||
{
|
||||
int p = (ty * tw + y) * m_Width + tx * tw + x;
|
||||
if(pPixelData[p * 4 + 3] < 250)
|
||||
{
|
||||
Opaque = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(Opaque)
|
||||
m_aTileFlags[TileID] |= TILEFLAG_OPAQUE;
|
||||
}
|
||||
}
|
||||
}
|
47
src/game/editor/mapitems/layer_front.cpp
Normal file
47
src/game/editor/mapitems/layer_front.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerFront::CLayerFront(int w, int h) :
|
||||
CLayerTiles(w, h)
|
||||
{
|
||||
str_copy(m_aName, "Front");
|
||||
m_Front = 1;
|
||||
}
|
||||
|
||||
void CLayerFront::SetTile(int x, int y, CTile Tile)
|
||||
{
|
||||
if(Tile.m_Index == TILE_THROUGH_CUT)
|
||||
{
|
||||
CTile nohook = {TILE_NOHOOK};
|
||||
m_pEditor->m_Map.m_pGameLayer->CLayerTiles::SetTile(x, y, nohook); // NOLINT(bugprone-parent-virtual-call)
|
||||
}
|
||||
else if(Tile.m_Index == TILE_AIR && CLayerTiles::GetTile(x, y).m_Index == TILE_THROUGH_CUT)
|
||||
{
|
||||
CTile air = {TILE_AIR};
|
||||
m_pEditor->m_Map.m_pGameLayer->CLayerTiles::SetTile(x, y, air); // NOLINT(bugprone-parent-virtual-call)
|
||||
}
|
||||
if(m_pEditor->m_AllowPlaceUnusedTiles || IsValidFrontTile(Tile.m_Index))
|
||||
{
|
||||
CLayerTiles::SetTile(x, y, Tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
CTile air = {TILE_AIR};
|
||||
CLayerTiles::SetTile(x, y, air);
|
||||
if(!m_pEditor->m_PreventUnusedTilesWasWarned)
|
||||
{
|
||||
m_pEditor->m_PopupEventType = CEditor::POPEVENT_PREVENTUNUSEDTILES;
|
||||
m_pEditor->m_PopupEventActivated = true;
|
||||
m_pEditor->m_PreventUnusedTilesWasWarned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerFront::Resize(int NewW, int NewH)
|
||||
{
|
||||
// resize tile data
|
||||
CLayerTiles::Resize(NewW, NewH);
|
||||
|
||||
// resize gamelayer too
|
||||
if(m_pEditor->m_Map.m_pGameLayer->m_Width != NewW || m_pEditor->m_Map.m_pGameLayer->m_Height != NewH)
|
||||
m_pEditor->m_Map.m_pGameLayer->Resize(NewW, NewH);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include "editor.h"
|
||||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerGame::CLayerGame(int w, int h) :
|
||||
CLayerTiles(w, h)
|
155
src/game/editor/mapitems/layer_group.cpp
Normal file
155
src/game/editor/mapitems/layer_group.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerGroup::CLayerGroup()
|
||||
{
|
||||
m_vpLayers.clear();
|
||||
m_aName[0] = 0;
|
||||
m_Visible = true;
|
||||
m_Collapse = false;
|
||||
m_GameGroup = false;
|
||||
m_OffsetX = 0;
|
||||
m_OffsetY = 0;
|
||||
m_ParallaxX = 100;
|
||||
m_ParallaxY = 100;
|
||||
m_CustomParallaxZoom = 0;
|
||||
m_ParallaxZoom = 100;
|
||||
|
||||
m_UseClipping = 0;
|
||||
m_ClipX = 0;
|
||||
m_ClipY = 0;
|
||||
m_ClipW = 0;
|
||||
m_ClipH = 0;
|
||||
}
|
||||
|
||||
CLayerGroup::~CLayerGroup()
|
||||
{
|
||||
m_vpLayers.clear();
|
||||
}
|
||||
|
||||
void CLayerGroup::Convert(CUIRect *pRect)
|
||||
{
|
||||
pRect->x += m_OffsetX;
|
||||
pRect->y += m_OffsetY;
|
||||
}
|
||||
|
||||
void CLayerGroup::Mapping(float *pPoints)
|
||||
{
|
||||
float ParallaxZoom = m_pMap->m_pEditor->m_PreviewZoom ? m_ParallaxZoom : 100.0f;
|
||||
|
||||
m_pMap->m_pEditor->RenderTools()->MapScreenToWorld(
|
||||
m_pMap->m_pEditor->MapView()->GetWorldOffset().x, m_pMap->m_pEditor->MapView()->GetWorldOffset().y,
|
||||
m_ParallaxX, m_ParallaxY, ParallaxZoom, m_OffsetX, m_OffsetY,
|
||||
m_pMap->m_pEditor->Graphics()->ScreenAspect(), m_pMap->m_pEditor->MapView()->GetWorldZoom(), pPoints);
|
||||
|
||||
pPoints[0] += m_pMap->m_pEditor->MapView()->GetEditorOffset().x;
|
||||
pPoints[1] += m_pMap->m_pEditor->MapView()->GetEditorOffset().y;
|
||||
pPoints[2] += m_pMap->m_pEditor->MapView()->GetEditorOffset().x;
|
||||
pPoints[3] += m_pMap->m_pEditor->MapView()->GetEditorOffset().y;
|
||||
}
|
||||
|
||||
void CLayerGroup::MapScreen()
|
||||
{
|
||||
float aPoints[4];
|
||||
Mapping(aPoints);
|
||||
m_pMap->m_pEditor->Graphics()->MapScreen(aPoints[0], aPoints[1], aPoints[2], aPoints[3]);
|
||||
}
|
||||
|
||||
void CLayerGroup::Render()
|
||||
{
|
||||
MapScreen();
|
||||
IGraphics *pGraphics = m_pMap->m_pEditor->Graphics();
|
||||
|
||||
if(m_UseClipping)
|
||||
{
|
||||
float aPoints[4];
|
||||
m_pMap->m_pGameGroup->Mapping(aPoints);
|
||||
float x0 = (m_ClipX - aPoints[0]) / (aPoints[2] - aPoints[0]);
|
||||
float y0 = (m_ClipY - aPoints[1]) / (aPoints[3] - aPoints[1]);
|
||||
float x1 = ((m_ClipX + m_ClipW) - aPoints[0]) / (aPoints[2] - aPoints[0]);
|
||||
float y1 = ((m_ClipY + m_ClipH) - aPoints[1]) / (aPoints[3] - aPoints[1]);
|
||||
|
||||
pGraphics->ClipEnable((int)(x0 * pGraphics->ScreenWidth()), (int)(y0 * pGraphics->ScreenHeight()),
|
||||
(int)((x1 - x0) * pGraphics->ScreenWidth()), (int)((y1 - y0) * pGraphics->ScreenHeight()));
|
||||
}
|
||||
|
||||
for(auto &pLayer : m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Visible)
|
||||
{
|
||||
if(pLayer->m_Type == LAYERTYPE_TILES)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
if(pTiles->m_Game || pTiles->m_Front || pTiles->m_Tele || pTiles->m_Speedup || pTiles->m_Tune || pTiles->m_Switch)
|
||||
continue;
|
||||
}
|
||||
if(m_pMap->m_pEditor->m_ShowDetail || !(pLayer->m_Flags & LAYERFLAG_DETAIL))
|
||||
pLayer->Render();
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &pLayer : m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Visible && pLayer->m_Type == LAYERTYPE_TILES && pLayer != m_pMap->m_pGameLayer && pLayer != m_pMap->m_pFrontLayer && pLayer != m_pMap->m_pTeleLayer && pLayer != m_pMap->m_pSpeedupLayer && pLayer != m_pMap->m_pSwitchLayer && pLayer != m_pMap->m_pTuneLayer)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
if(pTiles->m_Game || pTiles->m_Front || pTiles->m_Tele || pTiles->m_Speedup || pTiles->m_Tune || pTiles->m_Switch)
|
||||
{
|
||||
pLayer->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_UseClipping)
|
||||
pGraphics->ClipDisable();
|
||||
}
|
||||
|
||||
void CLayerGroup::AddLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pMap->OnModify();
|
||||
m_vpLayers.push_back(pLayer);
|
||||
}
|
||||
|
||||
void CLayerGroup::DeleteLayer(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpLayers.size())
|
||||
return;
|
||||
m_vpLayers.erase(m_vpLayers.begin() + Index);
|
||||
m_pMap->OnModify();
|
||||
}
|
||||
|
||||
void CLayerGroup::DuplicateLayer(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpLayers.size())
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayer> pDup = m_vpLayers[Index]->Duplicate();
|
||||
m_vpLayers.insert(m_vpLayers.begin() + Index + 1, pDup);
|
||||
|
||||
m_pMap->OnModify();
|
||||
}
|
||||
|
||||
void CLayerGroup::GetSize(float *pWidth, float *pHeight) const
|
||||
{
|
||||
*pWidth = 0;
|
||||
*pHeight = 0;
|
||||
for(const auto &pLayer : m_vpLayers)
|
||||
{
|
||||
float lw, lh;
|
||||
pLayer->GetSize(&lw, &lh);
|
||||
*pWidth = maximum(*pWidth, lw);
|
||||
*pHeight = maximum(*pHeight, lh);
|
||||
}
|
||||
}
|
||||
|
||||
int CLayerGroup::SwapLayers(int Index0, int Index1)
|
||||
{
|
||||
if(Index0 < 0 || Index0 >= (int)m_vpLayers.size())
|
||||
return Index0;
|
||||
if(Index1 < 0 || Index1 >= (int)m_vpLayers.size())
|
||||
return Index0;
|
||||
if(Index0 == Index1)
|
||||
return Index0;
|
||||
m_pMap->OnModify();
|
||||
std::swap(m_vpLayers[Index0], m_vpLayers[Index1]);
|
||||
return Index1;
|
||||
}
|
|
@ -1,11 +1,6 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include <base/math.h>
|
||||
|
||||
#include <engine/graphics.h>
|
||||
|
||||
#include "editor.h"
|
||||
#include <game/client/render.h>
|
||||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerQuads::CLayerQuads()
|
||||
{
|
|
@ -1,8 +1,7 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
#include <game/generated/client_data.h>
|
||||
|
||||
#include "editor.h"
|
||||
|
||||
static const float s_SourceVisualSize = 32.0f;
|
||||
|
||||
CLayerSounds::CLayerSounds()
|
244
src/game/editor/mapitems/layer_speedup.cpp
Normal file
244
src/game/editor/mapitems/layer_speedup.cpp
Normal file
|
@ -0,0 +1,244 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerSpeedup::CLayerSpeedup(int w, int h) :
|
||||
CLayerTiles(w, h)
|
||||
{
|
||||
str_copy(m_aName, "Speedup");
|
||||
m_Speedup = 1;
|
||||
|
||||
m_pSpeedupTile = new CSpeedupTile[w * h];
|
||||
mem_zero(m_pSpeedupTile, (size_t)w * h * sizeof(CSpeedupTile));
|
||||
}
|
||||
|
||||
CLayerSpeedup::~CLayerSpeedup()
|
||||
{
|
||||
delete[] m_pSpeedupTile;
|
||||
}
|
||||
|
||||
void CLayerSpeedup::Resize(int NewW, int NewH)
|
||||
{
|
||||
// resize speedup data
|
||||
CSpeedupTile *pNewSpeedupData = new CSpeedupTile[NewW * NewH];
|
||||
mem_zero(pNewSpeedupData, (size_t)NewW * NewH * sizeof(CSpeedupTile));
|
||||
|
||||
// copy old data
|
||||
for(int y = 0; y < minimum(NewH, m_Height); y++)
|
||||
mem_copy(&pNewSpeedupData[y * NewW], &m_pSpeedupTile[y * m_Width], minimum(m_Width, NewW) * sizeof(CSpeedupTile));
|
||||
|
||||
// replace old
|
||||
delete[] m_pSpeedupTile;
|
||||
m_pSpeedupTile = pNewSpeedupData;
|
||||
|
||||
// resize tile data
|
||||
CLayerTiles::Resize(NewW, NewH);
|
||||
|
||||
// resize gamelayer too
|
||||
if(m_pEditor->m_Map.m_pGameLayer->m_Width != NewW || m_pEditor->m_Map.m_pGameLayer->m_Height != NewH)
|
||||
m_pEditor->m_Map.m_pGameLayer->Resize(NewW, NewH);
|
||||
}
|
||||
|
||||
void CLayerSpeedup::Shift(int Direction)
|
||||
{
|
||||
CLayerTiles::Shift(Direction);
|
||||
ShiftImpl(m_pSpeedupTile, Direction, m_pEditor->m_ShiftBy);
|
||||
}
|
||||
|
||||
bool CLayerSpeedup::IsEmpty(const std::shared_ptr<CLayerTiles> &pLayer)
|
||||
{
|
||||
for(int y = 0; y < pLayer->m_Height; y++)
|
||||
for(int x = 0; x < pLayer->m_Width; x++)
|
||||
if(m_pEditor->m_AllowPlaceUnusedTiles || IsValidSpeedupTile(pLayer->GetTile(x, y).m_Index))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLayerSpeedup::BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy)
|
||||
{
|
||||
if(m_Readonly)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayerSpeedup> pSpeedupLayer = std::static_pointer_cast<CLayerSpeedup>(pBrush);
|
||||
int sx = ConvertX(wx);
|
||||
int sy = ConvertY(wy);
|
||||
if(str_comp(pSpeedupLayer->m_aFileName, m_pEditor->m_aFileName))
|
||||
{
|
||||
m_pEditor->m_SpeedupAngle = pSpeedupLayer->m_SpeedupAngle;
|
||||
m_pEditor->m_SpeedupForce = pSpeedupLayer->m_SpeedupForce;
|
||||
m_pEditor->m_SpeedupMaxSpeed = pSpeedupLayer->m_SpeedupMaxSpeed;
|
||||
}
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || IsEmpty(pSpeedupLayer);
|
||||
|
||||
for(int y = 0; y < pSpeedupLayer->m_Height; y++)
|
||||
for(int x = 0; x < pSpeedupLayer->m_Width; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
if((m_pEditor->m_AllowPlaceUnusedTiles || IsValidSpeedupTile(pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index)) && pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index != TILE_AIR)
|
||||
{
|
||||
if(m_pEditor->m_SpeedupAngle != pSpeedupLayer->m_SpeedupAngle || m_pEditor->m_SpeedupForce != pSpeedupLayer->m_SpeedupForce || m_pEditor->m_SpeedupMaxSpeed != pSpeedupLayer->m_SpeedupMaxSpeed)
|
||||
{
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Force = m_pEditor->m_SpeedupForce;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_MaxSpeed = m_pEditor->m_SpeedupMaxSpeed;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Angle = m_pEditor->m_SpeedupAngle;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Type = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
}
|
||||
else if(pSpeedupLayer->m_pSpeedupTile[y * pSpeedupLayer->m_Width + x].m_Force)
|
||||
{
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Force = pSpeedupLayer->m_pSpeedupTile[y * pSpeedupLayer->m_Width + x].m_Force;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Angle = pSpeedupLayer->m_pSpeedupTile[y * pSpeedupLayer->m_Width + x].m_Angle;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_MaxSpeed = pSpeedupLayer->m_pSpeedupTile[y * pSpeedupLayer->m_Width + x].m_MaxSpeed;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Type = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
}
|
||||
else if(m_pEditor->m_SpeedupForce)
|
||||
{
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Force = m_pEditor->m_SpeedupForce;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_MaxSpeed = m_pEditor->m_SpeedupMaxSpeed;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Angle = m_pEditor->m_SpeedupAngle;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Type = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pSpeedupLayer->m_pTiles[y * pSpeedupLayer->m_Width + x].m_Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Force = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_MaxSpeed = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Angle = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Force = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_MaxSpeed = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Angle = 0;
|
||||
m_pSpeedupTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, pSpeedupLayer->m_Width, pSpeedupLayer->m_Height);
|
||||
}
|
||||
|
||||
void CLayerSpeedup::BrushFlipX()
|
||||
{
|
||||
CLayerTiles::BrushFlipX();
|
||||
BrushFlipXImpl(m_pSpeedupTile);
|
||||
}
|
||||
|
||||
void CLayerSpeedup::BrushFlipY()
|
||||
{
|
||||
CLayerTiles::BrushFlipY();
|
||||
BrushFlipYImpl(m_pSpeedupTile);
|
||||
}
|
||||
|
||||
void CLayerSpeedup::BrushRotate(float Amount)
|
||||
{
|
||||
int Rotation = (round_to_int(360.0f * Amount / (pi * 2)) / 90) % 4; // 0=0°, 1=90°, 2=180°, 3=270°
|
||||
if(Rotation < 0)
|
||||
Rotation += 4;
|
||||
|
||||
if(Rotation == 1 || Rotation == 3)
|
||||
{
|
||||
// 90° rotation
|
||||
CSpeedupTile *pTempData1 = new CSpeedupTile[m_Width * m_Height];
|
||||
CTile *pTempData2 = new CTile[m_Width * m_Height];
|
||||
mem_copy(pTempData1, m_pSpeedupTile, (size_t)m_Width * m_Height * sizeof(CSpeedupTile));
|
||||
mem_copy(pTempData2, m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile));
|
||||
CSpeedupTile *pDst1 = m_pSpeedupTile;
|
||||
CTile *pDst2 = m_pTiles;
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
for(int y = m_Height - 1; y >= 0; --y, ++pDst1, ++pDst2)
|
||||
{
|
||||
*pDst1 = pTempData1[y * m_Width + x];
|
||||
*pDst2 = pTempData2[y * m_Width + x];
|
||||
}
|
||||
|
||||
std::swap(m_Width, m_Height);
|
||||
delete[] pTempData1;
|
||||
delete[] pTempData2;
|
||||
}
|
||||
|
||||
if(Rotation == 2 || Rotation == 3)
|
||||
{
|
||||
BrushFlipX();
|
||||
BrushFlipY();
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerSpeedup::FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect)
|
||||
{
|
||||
if(m_Readonly || (!Empty && pBrush->m_Type != LAYERTYPE_TILES))
|
||||
return;
|
||||
|
||||
Snap(&Rect); // corrects Rect; no need of <=
|
||||
|
||||
Snap(&Rect);
|
||||
|
||||
int sx = ConvertX(Rect.x);
|
||||
int sy = ConvertY(Rect.y);
|
||||
int w = ConvertX(Rect.w);
|
||||
int h = ConvertY(Rect.h);
|
||||
|
||||
std::shared_ptr<CLayerSpeedup> pLt = std::static_pointer_cast<CLayerSpeedup>(pBrush);
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || Empty || IsEmpty(pLt);
|
||||
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
const int SrcIndex = Empty ? 0 : (y * pLt->m_Width + x % pLt->m_Width) % (pLt->m_Width * pLt->m_Height);
|
||||
const int TgtIndex = fy * m_Width + fx;
|
||||
|
||||
if(Empty || (!m_pEditor->m_AllowPlaceUnusedTiles && !IsValidSpeedupTile((pLt->m_pTiles[SrcIndex]).m_Index))) // no speed up tile chosen: reset
|
||||
{
|
||||
m_pTiles[TgtIndex].m_Index = 0;
|
||||
m_pSpeedupTile[TgtIndex].m_Force = 0;
|
||||
m_pSpeedupTile[TgtIndex].m_Angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTiles[TgtIndex] = pLt->m_pTiles[SrcIndex];
|
||||
if(pLt->m_Speedup && m_pTiles[TgtIndex].m_Index > 0)
|
||||
{
|
||||
m_pSpeedupTile[TgtIndex].m_Type = m_pTiles[TgtIndex].m_Index;
|
||||
|
||||
if((pLt->m_pSpeedupTile[SrcIndex].m_Force == 0 && m_pEditor->m_SpeedupForce) || m_pEditor->m_SpeedupForce != pLt->m_SpeedupForce)
|
||||
m_pSpeedupTile[TgtIndex].m_Force = m_pEditor->m_SpeedupForce;
|
||||
else
|
||||
m_pSpeedupTile[TgtIndex].m_Force = pLt->m_pSpeedupTile[SrcIndex].m_Force;
|
||||
|
||||
if((pLt->m_pSpeedupTile[SrcIndex].m_Angle == 0 && m_pEditor->m_SpeedupAngle) || m_pEditor->m_SpeedupAngle != pLt->m_SpeedupAngle)
|
||||
m_pSpeedupTile[TgtIndex].m_Angle = m_pEditor->m_SpeedupAngle;
|
||||
else
|
||||
m_pSpeedupTile[TgtIndex].m_Angle = pLt->m_pSpeedupTile[SrcIndex].m_Angle;
|
||||
|
||||
if((pLt->m_pSpeedupTile[SrcIndex].m_MaxSpeed == 0 && m_pEditor->m_SpeedupMaxSpeed) || m_pEditor->m_SpeedupMaxSpeed != pLt->m_SpeedupMaxSpeed)
|
||||
m_pSpeedupTile[TgtIndex].m_MaxSpeed = m_pEditor->m_SpeedupMaxSpeed;
|
||||
else
|
||||
m_pSpeedupTile[TgtIndex].m_MaxSpeed = pLt->m_pSpeedupTile[SrcIndex].m_MaxSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
270
src/game/editor/mapitems/layer_switch.cpp
Normal file
270
src/game/editor/mapitems/layer_switch.cpp
Normal file
|
@ -0,0 +1,270 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerSwitch::CLayerSwitch(int w, int h) :
|
||||
CLayerTiles(w, h)
|
||||
{
|
||||
str_copy(m_aName, "Switch");
|
||||
m_Switch = 1;
|
||||
|
||||
m_pSwitchTile = new CSwitchTile[w * h];
|
||||
mem_zero(m_pSwitchTile, (size_t)w * h * sizeof(CSwitchTile));
|
||||
}
|
||||
|
||||
CLayerSwitch::~CLayerSwitch()
|
||||
{
|
||||
delete[] m_pSwitchTile;
|
||||
}
|
||||
|
||||
void CLayerSwitch::Resize(int NewW, int NewH)
|
||||
{
|
||||
// resize switch data
|
||||
CSwitchTile *pNewSwitchData = new CSwitchTile[NewW * NewH];
|
||||
mem_zero(pNewSwitchData, (size_t)NewW * NewH * sizeof(CSwitchTile));
|
||||
|
||||
// copy old data
|
||||
for(int y = 0; y < minimum(NewH, m_Height); y++)
|
||||
mem_copy(&pNewSwitchData[y * NewW], &m_pSwitchTile[y * m_Width], minimum(m_Width, NewW) * sizeof(CSwitchTile));
|
||||
|
||||
// replace old
|
||||
delete[] m_pSwitchTile;
|
||||
m_pSwitchTile = pNewSwitchData;
|
||||
|
||||
// resize tile data
|
||||
CLayerTiles::Resize(NewW, NewH);
|
||||
|
||||
// resize gamelayer too
|
||||
if(m_pEditor->m_Map.m_pGameLayer->m_Width != NewW || m_pEditor->m_Map.m_pGameLayer->m_Height != NewH)
|
||||
m_pEditor->m_Map.m_pGameLayer->Resize(NewW, NewH);
|
||||
}
|
||||
|
||||
void CLayerSwitch::Shift(int Direction)
|
||||
{
|
||||
CLayerTiles::Shift(Direction);
|
||||
ShiftImpl(m_pSwitchTile, Direction, m_pEditor->m_ShiftBy);
|
||||
}
|
||||
|
||||
bool CLayerSwitch::IsEmpty(const std::shared_ptr<CLayerTiles> &pLayer)
|
||||
{
|
||||
for(int y = 0; y < pLayer->m_Height; y++)
|
||||
for(int x = 0; x < pLayer->m_Width; x++)
|
||||
if(m_pEditor->m_AllowPlaceUnusedTiles || IsValidSwitchTile(pLayer->GetTile(x, y).m_Index))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLayerSwitch::BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy)
|
||||
{
|
||||
if(m_Readonly)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayerSwitch> pSwitchLayer = std::static_pointer_cast<CLayerSwitch>(pBrush);
|
||||
int sx = ConvertX(wx);
|
||||
int sy = ConvertY(wy);
|
||||
if(str_comp(pSwitchLayer->m_aFileName, m_pEditor->m_aFileName))
|
||||
{
|
||||
m_pEditor->m_SwitchNum = pSwitchLayer->m_SwitchNumber;
|
||||
m_pEditor->m_SwitchDelay = pSwitchLayer->m_SwitchDelay;
|
||||
}
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || IsEmpty(pSwitchLayer);
|
||||
|
||||
for(int y = 0; y < pSwitchLayer->m_Height; y++)
|
||||
for(int x = 0; x < pSwitchLayer->m_Width; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
if((m_pEditor->m_AllowPlaceUnusedTiles || IsValidSwitchTile(pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index)) && pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index != TILE_AIR)
|
||||
{
|
||||
if(m_pEditor->m_SwitchNum != pSwitchLayer->m_SwitchNumber || m_pEditor->m_SwitchDelay != pSwitchLayer->m_SwitchDelay)
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Number = m_pEditor->m_SwitchNum;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Delay = m_pEditor->m_SwitchDelay;
|
||||
}
|
||||
else if(pSwitchLayer->m_pSwitchTile[y * pSwitchLayer->m_Width + x].m_Number)
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Number = pSwitchLayer->m_pSwitchTile[y * pSwitchLayer->m_Width + x].m_Number;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Delay = pSwitchLayer->m_pSwitchTile[y * pSwitchLayer->m_Width + x].m_Delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Number = m_pEditor->m_SwitchNum;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Delay = m_pEditor->m_SwitchDelay;
|
||||
}
|
||||
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Type = pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Flags = pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Flags;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Flags = pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Flags;
|
||||
|
||||
if(!IsSwitchTileFlagsUsed(pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index))
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Flags = 0;
|
||||
}
|
||||
if(!IsSwitchTileNumberUsed(pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index))
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Number = 0;
|
||||
}
|
||||
if(!IsSwitchTileDelayUsed(pSwitchLayer->m_pTiles[y * pSwitchLayer->m_Width + x].m_Index))
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Delay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Number = 0;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Flags = 0;
|
||||
m_pSwitchTile[fy * m_Width + fx].m_Delay = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, pSwitchLayer->m_Width, pSwitchLayer->m_Height);
|
||||
}
|
||||
|
||||
void CLayerSwitch::BrushFlipX()
|
||||
{
|
||||
CLayerTiles::BrushFlipX();
|
||||
BrushFlipXImpl(m_pSwitchTile);
|
||||
}
|
||||
|
||||
void CLayerSwitch::BrushFlipY()
|
||||
{
|
||||
CLayerTiles::BrushFlipY();
|
||||
BrushFlipYImpl(m_pSwitchTile);
|
||||
}
|
||||
|
||||
void CLayerSwitch::BrushRotate(float Amount)
|
||||
{
|
||||
int Rotation = (round_to_int(360.0f * Amount / (pi * 2)) / 90) % 4; // 0=0°, 1=90°, 2=180°, 3=270°
|
||||
if(Rotation < 0)
|
||||
Rotation += 4;
|
||||
|
||||
if(Rotation == 1 || Rotation == 3)
|
||||
{
|
||||
// 90° rotation
|
||||
CSwitchTile *pTempData1 = new CSwitchTile[m_Width * m_Height];
|
||||
CTile *pTempData2 = new CTile[m_Width * m_Height];
|
||||
mem_copy(pTempData1, m_pSwitchTile, (size_t)m_Width * m_Height * sizeof(CSwitchTile));
|
||||
mem_copy(pTempData2, m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile));
|
||||
CSwitchTile *pDst1 = m_pSwitchTile;
|
||||
CTile *pDst2 = m_pTiles;
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
for(int y = m_Height - 1; y >= 0; --y, ++pDst1, ++pDst2)
|
||||
{
|
||||
*pDst1 = pTempData1[y * m_Width + x];
|
||||
*pDst2 = pTempData2[y * m_Width + x];
|
||||
if(IsRotatableTile(pDst2->m_Index))
|
||||
{
|
||||
if(pDst2->m_Flags & TILEFLAG_ROTATE)
|
||||
pDst2->m_Flags ^= (TILEFLAG_YFLIP | TILEFLAG_XFLIP);
|
||||
pDst2->m_Flags ^= TILEFLAG_ROTATE;
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(m_Width, m_Height);
|
||||
delete[] pTempData1;
|
||||
delete[] pTempData2;
|
||||
}
|
||||
|
||||
if(Rotation == 2 || Rotation == 3)
|
||||
{
|
||||
BrushFlipX();
|
||||
BrushFlipY();
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerSwitch::FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect)
|
||||
{
|
||||
if(m_Readonly || (!Empty && pBrush->m_Type != LAYERTYPE_TILES))
|
||||
return;
|
||||
|
||||
Snap(&Rect); // corrects Rect; no need of <=
|
||||
|
||||
Snap(&Rect);
|
||||
|
||||
int sx = ConvertX(Rect.x);
|
||||
int sy = ConvertY(Rect.y);
|
||||
int w = ConvertX(Rect.w);
|
||||
int h = ConvertY(Rect.h);
|
||||
|
||||
std::shared_ptr<CLayerSwitch> pLt = std::static_pointer_cast<CLayerSwitch>(pBrush);
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || Empty || IsEmpty(pLt);
|
||||
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
const int SrcIndex = Empty ? 0 : (y * pLt->m_Width + x % pLt->m_Width) % (pLt->m_Width * pLt->m_Height);
|
||||
const int TgtIndex = fy * m_Width + fx;
|
||||
|
||||
if(Empty || (!m_pEditor->m_AllowPlaceUnusedTiles && !IsValidSwitchTile((pLt->m_pTiles[SrcIndex]).m_Index)))
|
||||
{
|
||||
m_pTiles[TgtIndex].m_Index = 0;
|
||||
m_pSwitchTile[TgtIndex].m_Type = 0;
|
||||
m_pSwitchTile[TgtIndex].m_Number = 0;
|
||||
m_pSwitchTile[TgtIndex].m_Delay = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTiles[TgtIndex] = pLt->m_pTiles[SrcIndex];
|
||||
m_pSwitchTile[TgtIndex].m_Type = m_pTiles[TgtIndex].m_Index;
|
||||
if(pLt->m_Switch && m_pTiles[TgtIndex].m_Index > 0)
|
||||
{
|
||||
if(!IsSwitchTileNumberUsed(m_pSwitchTile[TgtIndex].m_Type))
|
||||
m_pSwitchTile[TgtIndex].m_Number = 0;
|
||||
else if(pLt->m_pSwitchTile[SrcIndex].m_Number == 0 || m_pEditor->m_SwitchNum != pLt->m_SwitchNumber)
|
||||
m_pSwitchTile[TgtIndex].m_Number = m_pEditor->m_SwitchNum;
|
||||
else
|
||||
m_pSwitchTile[TgtIndex].m_Number = pLt->m_pSwitchTile[SrcIndex].m_Number;
|
||||
|
||||
if(!IsSwitchTileDelayUsed(m_pSwitchTile[TgtIndex].m_Type))
|
||||
m_pSwitchTile[TgtIndex].m_Delay = 0;
|
||||
else if(pLt->m_pSwitchTile[SrcIndex].m_Delay == 0 || m_pEditor->m_SwitchDelay != pLt->m_SwitchDelay)
|
||||
m_pSwitchTile[TgtIndex].m_Delay = m_pEditor->m_SwitchDelay;
|
||||
else
|
||||
m_pSwitchTile[TgtIndex].m_Delay = pLt->m_pSwitchTile[SrcIndex].m_Delay;
|
||||
|
||||
if(!IsSwitchTileFlagsUsed(m_pSwitchTile[TgtIndex].m_Type))
|
||||
m_pSwitchTile[TgtIndex].m_Flags = 0;
|
||||
else
|
||||
m_pSwitchTile[TgtIndex].m_Flags = pLt->m_pSwitchTile[SrcIndex].m_Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
bool CLayerSwitch::ContainsElementWithId(int Id)
|
||||
{
|
||||
for(int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
if(IsSwitchTileNumberUsed(m_pSwitchTile[y * m_Width + x].m_Type) && m_pSwitchTile[y * m_Width + x].m_Number == Id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
247
src/game/editor/mapitems/layer_tele.cpp
Normal file
247
src/game/editor/mapitems/layer_tele.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerTele::CLayerTele(int w, int h) :
|
||||
CLayerTiles(w, h)
|
||||
{
|
||||
str_copy(m_aName, "Tele");
|
||||
m_Tele = 1;
|
||||
|
||||
m_pTeleTile = new CTeleTile[w * h];
|
||||
mem_zero(m_pTeleTile, (size_t)w * h * sizeof(CTeleTile));
|
||||
}
|
||||
|
||||
CLayerTele::~CLayerTele()
|
||||
{
|
||||
delete[] m_pTeleTile;
|
||||
}
|
||||
|
||||
void CLayerTele::Resize(int NewW, int NewH)
|
||||
{
|
||||
// resize tele data
|
||||
CTeleTile *pNewTeleData = new CTeleTile[NewW * NewH];
|
||||
mem_zero(pNewTeleData, (size_t)NewW * NewH * sizeof(CTeleTile));
|
||||
|
||||
// copy old data
|
||||
for(int y = 0; y < minimum(NewH, m_Height); y++)
|
||||
mem_copy(&pNewTeleData[y * NewW], &m_pTeleTile[y * m_Width], minimum(m_Width, NewW) * sizeof(CTeleTile));
|
||||
|
||||
// replace old
|
||||
delete[] m_pTeleTile;
|
||||
m_pTeleTile = pNewTeleData;
|
||||
|
||||
// resize tile data
|
||||
CLayerTiles::Resize(NewW, NewH);
|
||||
|
||||
// resize gamelayer too
|
||||
if(m_pEditor->m_Map.m_pGameLayer->m_Width != NewW || m_pEditor->m_Map.m_pGameLayer->m_Height != NewH)
|
||||
m_pEditor->m_Map.m_pGameLayer->Resize(NewW, NewH);
|
||||
}
|
||||
|
||||
void CLayerTele::Shift(int Direction)
|
||||
{
|
||||
CLayerTiles::Shift(Direction);
|
||||
ShiftImpl(m_pTeleTile, Direction, m_pEditor->m_ShiftBy);
|
||||
}
|
||||
|
||||
bool CLayerTele::IsEmpty(const std::shared_ptr<CLayerTiles> &pLayer)
|
||||
{
|
||||
for(int y = 0; y < pLayer->m_Height; y++)
|
||||
for(int x = 0; x < pLayer->m_Width; x++)
|
||||
if(m_pEditor->m_AllowPlaceUnusedTiles || IsValidTeleTile(pLayer->GetTile(x, y).m_Index))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLayerTele::BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy)
|
||||
{
|
||||
if(m_Readonly)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayerTele> pTeleLayer = std::static_pointer_cast<CLayerTele>(pBrush);
|
||||
int sx = ConvertX(wx);
|
||||
int sy = ConvertY(wy);
|
||||
if(str_comp(pTeleLayer->m_aFileName, m_pEditor->m_aFileName))
|
||||
m_pEditor->m_TeleNumber = pTeleLayer->m_TeleNum;
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || IsEmpty(pTeleLayer);
|
||||
|
||||
for(int y = 0; y < pTeleLayer->m_Height; y++)
|
||||
for(int x = 0; x < pTeleLayer->m_Width; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
if((m_pEditor->m_AllowPlaceUnusedTiles || IsValidTeleTile(pTeleLayer->m_pTiles[y * pTeleLayer->m_Width + x].m_Index)) && pTeleLayer->m_pTiles[y * pTeleLayer->m_Width + x].m_Index != TILE_AIR)
|
||||
{
|
||||
if(!IsTeleTileNumberUsed(pTeleLayer->m_pTiles[y * pTeleLayer->m_Width + x].m_Index))
|
||||
{
|
||||
// Tele tile number is unused. Set a known value which is not 0,
|
||||
// as tiles with number 0 would be ignored by previous versions.
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = 255;
|
||||
}
|
||||
else if(m_pEditor->m_TeleNumber != pTeleLayer->m_TeleNum)
|
||||
{
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = m_pEditor->m_TeleNumber;
|
||||
}
|
||||
else if(pTeleLayer->m_pTeleTile[y * pTeleLayer->m_Width + x].m_Number)
|
||||
{
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = pTeleLayer->m_pTeleTile[y * pTeleLayer->m_Width + x].m_Number;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!m_pEditor->m_TeleNumber)
|
||||
{
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = 0;
|
||||
m_pTeleTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = m_pEditor->m_TeleNumber;
|
||||
}
|
||||
|
||||
m_pTeleTile[fy * m_Width + fx].m_Type = pTeleLayer->m_pTiles[y * pTeleLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pTeleLayer->m_pTiles[y * pTeleLayer->m_Width + x].m_Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTeleTile[fy * m_Width + fx].m_Number = 0;
|
||||
m_pTeleTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, pTeleLayer->m_Width, pTeleLayer->m_Height);
|
||||
}
|
||||
|
||||
void CLayerTele::BrushFlipX()
|
||||
{
|
||||
CLayerTiles::BrushFlipX();
|
||||
BrushFlipXImpl(m_pTeleTile);
|
||||
}
|
||||
|
||||
void CLayerTele::BrushFlipY()
|
||||
{
|
||||
CLayerTiles::BrushFlipY();
|
||||
BrushFlipYImpl(m_pTeleTile);
|
||||
}
|
||||
|
||||
void CLayerTele::BrushRotate(float Amount)
|
||||
{
|
||||
int Rotation = (round_to_int(360.0f * Amount / (pi * 2)) / 90) % 4; // 0=0°, 1=90°, 2=180°, 3=270°
|
||||
if(Rotation < 0)
|
||||
Rotation += 4;
|
||||
|
||||
if(Rotation == 1 || Rotation == 3)
|
||||
{
|
||||
// 90° rotation
|
||||
CTeleTile *pTempData1 = new CTeleTile[m_Width * m_Height];
|
||||
CTile *pTempData2 = new CTile[m_Width * m_Height];
|
||||
mem_copy(pTempData1, m_pTeleTile, (size_t)m_Width * m_Height * sizeof(CTeleTile));
|
||||
mem_copy(pTempData2, m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile));
|
||||
CTeleTile *pDst1 = m_pTeleTile;
|
||||
CTile *pDst2 = m_pTiles;
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
for(int y = m_Height - 1; y >= 0; --y, ++pDst1, ++pDst2)
|
||||
{
|
||||
*pDst1 = pTempData1[y * m_Width + x];
|
||||
*pDst2 = pTempData2[y * m_Width + x];
|
||||
}
|
||||
|
||||
std::swap(m_Width, m_Height);
|
||||
delete[] pTempData1;
|
||||
delete[] pTempData2;
|
||||
}
|
||||
|
||||
if(Rotation == 2 || Rotation == 3)
|
||||
{
|
||||
BrushFlipX();
|
||||
BrushFlipY();
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerTele::FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect)
|
||||
{
|
||||
if(m_Readonly || (!Empty && pBrush->m_Type != LAYERTYPE_TILES))
|
||||
return;
|
||||
|
||||
Snap(&Rect); // corrects Rect; no need of <=
|
||||
|
||||
Snap(&Rect);
|
||||
|
||||
int sx = ConvertX(Rect.x);
|
||||
int sy = ConvertY(Rect.y);
|
||||
int w = ConvertX(Rect.w);
|
||||
int h = ConvertY(Rect.h);
|
||||
|
||||
std::shared_ptr<CLayerTele> pLt = std::static_pointer_cast<CLayerTele>(pBrush);
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || Empty || IsEmpty(pLt);
|
||||
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
const int SrcIndex = Empty ? 0 : (y * pLt->m_Width + x % pLt->m_Width) % (pLt->m_Width * pLt->m_Height);
|
||||
const int TgtIndex = fy * m_Width + fx;
|
||||
|
||||
if(Empty || (!m_pEditor->m_AllowPlaceUnusedTiles && !IsValidTeleTile((pLt->m_pTiles[SrcIndex]).m_Index)))
|
||||
{
|
||||
m_pTiles[TgtIndex].m_Index = 0;
|
||||
m_pTeleTile[TgtIndex].m_Type = 0;
|
||||
m_pTeleTile[TgtIndex].m_Number = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTiles[TgtIndex] = pLt->m_pTiles[SrcIndex];
|
||||
if(pLt->m_Tele && m_pTiles[TgtIndex].m_Index > 0)
|
||||
{
|
||||
m_pTeleTile[TgtIndex].m_Type = m_pTiles[TgtIndex].m_Index;
|
||||
|
||||
if(!IsTeleTileNumberUsed(m_pTeleTile[TgtIndex].m_Type))
|
||||
{
|
||||
// Tele tile number is unused. Set a known value which is not 0,
|
||||
// as tiles with number 0 would be ignored by previous versions.
|
||||
m_pTeleTile[TgtIndex].m_Number = 255;
|
||||
}
|
||||
else if((pLt->m_pTeleTile[SrcIndex].m_Number == 0 && m_pEditor->m_TeleNumber) || m_pEditor->m_TeleNumber != pLt->m_TeleNum)
|
||||
m_pTeleTile[TgtIndex].m_Number = m_pEditor->m_TeleNumber;
|
||||
else
|
||||
m_pTeleTile[TgtIndex].m_Number = pLt->m_pTeleTile[SrcIndex].m_Number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
bool CLayerTele::ContainsElementWithId(int Id)
|
||||
{
|
||||
for(int y = 0; y < m_Height; ++y)
|
||||
{
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
{
|
||||
if(IsTeleTileNumberUsed(m_pTeleTile[y * m_Width + x].m_Type) && m_pTeleTile[y * m_Width + x].m_Number == Id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
File diff suppressed because it is too large
Load diff
218
src/game/editor/mapitems/layer_tune.cpp
Normal file
218
src/game/editor/mapitems/layer_tune.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
CLayerTune::CLayerTune(int w, int h) :
|
||||
CLayerTiles(w, h)
|
||||
{
|
||||
str_copy(m_aName, "Tune");
|
||||
m_Tune = 1;
|
||||
|
||||
m_pTuneTile = new CTuneTile[w * h];
|
||||
mem_zero(m_pTuneTile, (size_t)w * h * sizeof(CTuneTile));
|
||||
}
|
||||
|
||||
CLayerTune::~CLayerTune()
|
||||
{
|
||||
delete[] m_pTuneTile;
|
||||
}
|
||||
|
||||
void CLayerTune::Resize(int NewW, int NewH)
|
||||
{
|
||||
// resize Tune data
|
||||
CTuneTile *pNewTuneData = new CTuneTile[NewW * NewH];
|
||||
mem_zero(pNewTuneData, (size_t)NewW * NewH * sizeof(CTuneTile));
|
||||
|
||||
// copy old data
|
||||
for(int y = 0; y < minimum(NewH, m_Height); y++)
|
||||
mem_copy(&pNewTuneData[y * NewW], &m_pTuneTile[y * m_Width], minimum(m_Width, NewW) * sizeof(CTuneTile));
|
||||
|
||||
// replace old
|
||||
delete[] m_pTuneTile;
|
||||
m_pTuneTile = pNewTuneData;
|
||||
|
||||
// resize tile data
|
||||
CLayerTiles::Resize(NewW, NewH);
|
||||
|
||||
// resize gamelayer too
|
||||
if(m_pEditor->m_Map.m_pGameLayer->m_Width != NewW || m_pEditor->m_Map.m_pGameLayer->m_Height != NewH)
|
||||
m_pEditor->m_Map.m_pGameLayer->Resize(NewW, NewH);
|
||||
}
|
||||
|
||||
void CLayerTune::Shift(int Direction)
|
||||
{
|
||||
CLayerTiles::Shift(Direction);
|
||||
ShiftImpl(m_pTuneTile, Direction, m_pEditor->m_ShiftBy);
|
||||
}
|
||||
|
||||
bool CLayerTune::IsEmpty(const std::shared_ptr<CLayerTiles> &pLayer)
|
||||
{
|
||||
for(int y = 0; y < pLayer->m_Height; y++)
|
||||
for(int x = 0; x < pLayer->m_Width; x++)
|
||||
if(m_pEditor->m_AllowPlaceUnusedTiles || IsValidTuneTile(pLayer->GetTile(x, y).m_Index))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CLayerTune::BrushDraw(std::shared_ptr<CLayer> pBrush, float wx, float wy)
|
||||
{
|
||||
if(m_Readonly)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CLayerTune> pTuneLayer = std::static_pointer_cast<CLayerTune>(pBrush);
|
||||
int sx = ConvertX(wx);
|
||||
int sy = ConvertY(wy);
|
||||
if(str_comp(pTuneLayer->m_aFileName, m_pEditor->m_aFileName))
|
||||
{
|
||||
m_pEditor->m_TuningNum = pTuneLayer->m_TuningNumber;
|
||||
}
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || IsEmpty(pTuneLayer);
|
||||
|
||||
for(int y = 0; y < pTuneLayer->m_Height; y++)
|
||||
for(int x = 0; x < pTuneLayer->m_Width; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
if((m_pEditor->m_AllowPlaceUnusedTiles || IsValidTuneTile(pTuneLayer->m_pTiles[y * pTuneLayer->m_Width + x].m_Index)) && pTuneLayer->m_pTiles[y * pTuneLayer->m_Width + x].m_Index != TILE_AIR)
|
||||
{
|
||||
if(m_pEditor->m_TuningNum != pTuneLayer->m_TuningNumber)
|
||||
{
|
||||
m_pTuneTile[fy * m_Width + fx].m_Number = m_pEditor->m_TuningNum;
|
||||
}
|
||||
else if(pTuneLayer->m_pTuneTile[y * pTuneLayer->m_Width + x].m_Number)
|
||||
m_pTuneTile[fy * m_Width + fx].m_Number = pTuneLayer->m_pTuneTile[y * pTuneLayer->m_Width + x].m_Number;
|
||||
else
|
||||
{
|
||||
if(!m_pEditor->m_TuningNum)
|
||||
{
|
||||
m_pTuneTile[fy * m_Width + fx].m_Number = 0;
|
||||
m_pTuneTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
m_pTuneTile[fy * m_Width + fx].m_Number = m_pEditor->m_TuningNum;
|
||||
}
|
||||
|
||||
m_pTuneTile[fy * m_Width + fx].m_Type = pTuneLayer->m_pTiles[y * pTuneLayer->m_Width + x].m_Index;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = pTuneLayer->m_pTiles[y * pTuneLayer->m_Width + x].m_Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTuneTile[fy * m_Width + fx].m_Number = 0;
|
||||
m_pTuneTile[fy * m_Width + fx].m_Type = 0;
|
||||
m_pTiles[fy * m_Width + fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, pTuneLayer->m_Width, pTuneLayer->m_Height);
|
||||
}
|
||||
|
||||
void CLayerTune::BrushFlipX()
|
||||
{
|
||||
CLayerTiles::BrushFlipX();
|
||||
BrushFlipXImpl(m_pTuneTile);
|
||||
}
|
||||
|
||||
void CLayerTune::BrushFlipY()
|
||||
{
|
||||
CLayerTiles::BrushFlipY();
|
||||
BrushFlipYImpl(m_pTuneTile);
|
||||
}
|
||||
|
||||
void CLayerTune::BrushRotate(float Amount)
|
||||
{
|
||||
int Rotation = (round_to_int(360.0f * Amount / (pi * 2)) / 90) % 4; // 0=0°, 1=90°, 2=180°, 3=270°
|
||||
if(Rotation < 0)
|
||||
Rotation += 4;
|
||||
|
||||
if(Rotation == 1 || Rotation == 3)
|
||||
{
|
||||
// 90° rotation
|
||||
CTuneTile *pTempData1 = new CTuneTile[m_Width * m_Height];
|
||||
CTile *pTempData2 = new CTile[m_Width * m_Height];
|
||||
mem_copy(pTempData1, m_pTuneTile, (size_t)m_Width * m_Height * sizeof(CTuneTile));
|
||||
mem_copy(pTempData2, m_pTiles, (size_t)m_Width * m_Height * sizeof(CTile));
|
||||
CTuneTile *pDst1 = m_pTuneTile;
|
||||
CTile *pDst2 = m_pTiles;
|
||||
for(int x = 0; x < m_Width; ++x)
|
||||
for(int y = m_Height - 1; y >= 0; --y, ++pDst1, ++pDst2)
|
||||
{
|
||||
*pDst1 = pTempData1[y * m_Width + x];
|
||||
*pDst2 = pTempData2[y * m_Width + x];
|
||||
}
|
||||
|
||||
std::swap(m_Width, m_Height);
|
||||
delete[] pTempData1;
|
||||
delete[] pTempData2;
|
||||
}
|
||||
|
||||
if(Rotation == 2 || Rotation == 3)
|
||||
{
|
||||
BrushFlipX();
|
||||
BrushFlipY();
|
||||
}
|
||||
}
|
||||
|
||||
void CLayerTune::FillSelection(bool Empty, std::shared_ptr<CLayer> pBrush, CUIRect Rect)
|
||||
{
|
||||
if(m_Readonly || (!Empty && pBrush->m_Type != LAYERTYPE_TILES))
|
||||
return;
|
||||
|
||||
Snap(&Rect); // corrects Rect; no need of <=
|
||||
|
||||
int sx = ConvertX(Rect.x);
|
||||
int sy = ConvertY(Rect.y);
|
||||
int w = ConvertX(Rect.w);
|
||||
int h = ConvertY(Rect.h);
|
||||
|
||||
std::shared_ptr<CLayerTune> pLt = std::static_pointer_cast<CLayerTune>(pBrush);
|
||||
|
||||
bool Destructive = m_pEditor->m_BrushDrawDestructive || Empty || IsEmpty(pLt);
|
||||
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
int fx = x + sx;
|
||||
int fy = y + sy;
|
||||
|
||||
if(fx < 0 || fx >= m_Width || fy < 0 || fy >= m_Height)
|
||||
continue;
|
||||
|
||||
if(!Destructive && GetTile(fx, fy).m_Index)
|
||||
continue;
|
||||
|
||||
const int SrcIndex = Empty ? 0 : (y * pLt->m_Width + x % pLt->m_Width) % (pLt->m_Width * pLt->m_Height);
|
||||
const int TgtIndex = fy * m_Width + fx;
|
||||
|
||||
if(Empty || (!m_pEditor->m_AllowPlaceUnusedTiles && !IsValidTuneTile((pLt->m_pTiles[SrcIndex]).m_Index)))
|
||||
{
|
||||
m_pTiles[TgtIndex].m_Index = 0;
|
||||
m_pTuneTile[TgtIndex].m_Type = 0;
|
||||
m_pTuneTile[TgtIndex].m_Number = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTiles[TgtIndex] = pLt->m_pTiles[SrcIndex];
|
||||
if(pLt->m_Tune && m_pTiles[TgtIndex].m_Index > 0)
|
||||
{
|
||||
m_pTuneTile[TgtIndex].m_Type = m_pTiles[fy * m_Width + fx].m_Index;
|
||||
|
||||
if((pLt->m_pTuneTile[SrcIndex].m_Number == 0 && m_pEditor->m_TuningNum) || m_pEditor->m_TuningNum != pLt->m_TuningNumber)
|
||||
m_pTuneTile[TgtIndex].m_Number = m_pEditor->m_TuningNum;
|
||||
else
|
||||
m_pTuneTile[TgtIndex].m_Number = pLt->m_pTuneTile[SrcIndex].m_Number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
179
src/game/editor/mapitems/map.cpp
Normal file
179
src/game/editor/mapitems/map.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
void CEditorMap::OnModify()
|
||||
{
|
||||
m_Modified = true;
|
||||
m_ModifiedAuto = true;
|
||||
m_LastModifiedTime = m_pEditor->Client()->GlobalTime();
|
||||
}
|
||||
|
||||
void CEditorMap::DeleteEnvelope(int Index)
|
||||
{
|
||||
if(Index < 0 || Index >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
|
||||
OnModify();
|
||||
|
||||
VisitEnvelopeReferences([Index](int &ElementIndex) {
|
||||
if(ElementIndex == Index)
|
||||
ElementIndex = -1;
|
||||
else if(ElementIndex > Index)
|
||||
ElementIndex--;
|
||||
});
|
||||
|
||||
m_vpEnvelopes.erase(m_vpEnvelopes.begin() + Index);
|
||||
}
|
||||
|
||||
void CEditorMap::SwapEnvelopes(int Index0, int Index1)
|
||||
{
|
||||
if(Index0 < 0 || Index0 >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
if(Index1 < 0 || Index1 >= (int)m_vpEnvelopes.size())
|
||||
return;
|
||||
if(Index0 == Index1)
|
||||
return;
|
||||
|
||||
OnModify();
|
||||
|
||||
VisitEnvelopeReferences([Index0, Index1](int &ElementIndex) {
|
||||
if(ElementIndex == Index0)
|
||||
ElementIndex = Index1;
|
||||
else if(ElementIndex == Index1)
|
||||
ElementIndex = Index0;
|
||||
});
|
||||
|
||||
std::swap(m_vpEnvelopes[Index0], m_vpEnvelopes[Index1]);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void CEditorMap::VisitEnvelopeReferences(F &&Visitor)
|
||||
{
|
||||
for(auto &pGroup : m_vpGroups)
|
||||
{
|
||||
for(auto &pLayer : pGroup->m_vpLayers)
|
||||
{
|
||||
if(pLayer->m_Type == LAYERTYPE_QUADS)
|
||||
{
|
||||
std::shared_ptr<CLayerQuads> pLayerQuads = std::static_pointer_cast<CLayerQuads>(pLayer);
|
||||
for(auto &Quad : pLayerQuads->m_vQuads)
|
||||
{
|
||||
Visitor(Quad.m_PosEnv);
|
||||
Visitor(Quad.m_ColorEnv);
|
||||
}
|
||||
}
|
||||
else if(pLayer->m_Type == LAYERTYPE_TILES)
|
||||
{
|
||||
std::shared_ptr<CLayerTiles> pLayerTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||
Visitor(pLayerTiles->m_ColorEnv);
|
||||
}
|
||||
else if(pLayer->m_Type == LAYERTYPE_SOUNDS)
|
||||
{
|
||||
std::shared_ptr<CLayerSounds> pLayerSounds = std::static_pointer_cast<CLayerSounds>(pLayer);
|
||||
for(auto &Source : pLayerSounds->m_vSources)
|
||||
{
|
||||
Visitor(Source.m_PosEnv);
|
||||
Visitor(Source.m_SoundEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEditorMap::MakeGameLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pGameLayer = std::static_pointer_cast<CLayerGame>(pLayer);
|
||||
m_pGameLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeGameGroup(std::shared_ptr<CLayerGroup> pGroup)
|
||||
{
|
||||
m_pGameGroup = std::move(pGroup);
|
||||
m_pGameGroup->m_GameGroup = true;
|
||||
str_copy(m_pGameGroup->m_aName, "Game");
|
||||
}
|
||||
|
||||
void CEditorMap::Clean()
|
||||
{
|
||||
m_vpGroups.clear();
|
||||
m_vpEnvelopes.clear();
|
||||
m_vpImages.clear();
|
||||
m_vpSounds.clear();
|
||||
|
||||
m_MapInfo.Reset();
|
||||
m_MapInfoTmp.Reset();
|
||||
|
||||
m_vSettings.clear();
|
||||
|
||||
m_pGameLayer = nullptr;
|
||||
m_pGameGroup = nullptr;
|
||||
|
||||
m_Modified = false;
|
||||
m_ModifiedAuto = false;
|
||||
|
||||
m_pTeleLayer = nullptr;
|
||||
m_pSpeedupLayer = nullptr;
|
||||
m_pFrontLayer = nullptr;
|
||||
m_pSwitchLayer = nullptr;
|
||||
m_pTuneLayer = nullptr;
|
||||
}
|
||||
|
||||
void CEditorMap::CreateDefault(IGraphics::CTextureHandle EntitiesTexture)
|
||||
{
|
||||
// add background
|
||||
std::shared_ptr<CLayerGroup> pGroup = NewGroup();
|
||||
pGroup->m_ParallaxX = 0;
|
||||
pGroup->m_ParallaxY = 0;
|
||||
pGroup->m_CustomParallaxZoom = 0;
|
||||
pGroup->m_ParallaxZoom = 0;
|
||||
std::shared_ptr<CLayerQuads> pLayer = std::make_shared<CLayerQuads>();
|
||||
pLayer->m_pEditor = m_pEditor;
|
||||
CQuad *pQuad = pLayer->NewQuad(0, 0, 1600, 1200);
|
||||
pQuad->m_aColors[0].r = pQuad->m_aColors[1].r = 94;
|
||||
pQuad->m_aColors[0].g = pQuad->m_aColors[1].g = 132;
|
||||
pQuad->m_aColors[0].b = pQuad->m_aColors[1].b = 174;
|
||||
pQuad->m_aColors[2].r = pQuad->m_aColors[3].r = 204;
|
||||
pQuad->m_aColors[2].g = pQuad->m_aColors[3].g = 232;
|
||||
pQuad->m_aColors[2].b = pQuad->m_aColors[3].b = 255;
|
||||
pGroup->AddLayer(pLayer);
|
||||
|
||||
// add game layer and reset front, tele, speedup, tune and switch layer pointers
|
||||
MakeGameGroup(NewGroup());
|
||||
MakeGameLayer(std::make_shared<CLayerGame>(50, 50));
|
||||
m_pGameGroup->AddLayer(m_pGameLayer);
|
||||
|
||||
m_pFrontLayer = nullptr;
|
||||
m_pTeleLayer = nullptr;
|
||||
m_pSpeedupLayer = nullptr;
|
||||
m_pSwitchLayer = nullptr;
|
||||
m_pTuneLayer = nullptr;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeTeleLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pTeleLayer = std::static_pointer_cast<CLayerTele>(pLayer);
|
||||
m_pTeleLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeSpeedupLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pSpeedupLayer = std::static_pointer_cast<CLayerSpeedup>(pLayer);
|
||||
m_pSpeedupLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeFrontLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pFrontLayer = std::static_pointer_cast<CLayerFront>(pLayer);
|
||||
m_pFrontLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeSwitchLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pSwitchLayer = std::static_pointer_cast<CLayerSwitch>(pLayer);
|
||||
m_pSwitchLayer->m_pEditor = m_pEditor;
|
||||
}
|
||||
|
||||
void CEditorMap::MakeTuneLayer(const std::shared_ptr<CLayer> &pLayer)
|
||||
{
|
||||
m_pTuneLayer = std::static_pointer_cast<CLayerTune>(pLayer);
|
||||
m_pTuneLayer->m_pEditor = m_pEditor;
|
||||
}
|
10
src/game/editor/mapitems/sound.cpp
Normal file
10
src/game/editor/mapitems/sound.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <game/editor/editor.h>
|
||||
|
||||
#include <engine/sound.h>
|
||||
|
||||
CEditorSound::~CEditorSound()
|
||||
{
|
||||
m_pEditor->Sound()->UnloadSample(m_SoundID);
|
||||
free(m_pData);
|
||||
m_pData = nullptr;
|
||||
}
|
Loading…
Reference in a new issue