2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
#include <engine/map.h>
|
2010-10-06 21:07:35 +00:00
|
|
|
#include <engine/storage.h>
|
2016-04-29 16:17:06 +00:00
|
|
|
#include <engine/serverbrowser.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/client/component.h>
|
2017-09-12 18:15:37 +00:00
|
|
|
#include <engine/textrender.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/mapitems.h>
|
2008-09-01 05:54:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "mapimages.h"
|
2008-09-01 05:54:00 +00:00
|
|
|
|
2019-05-06 12:19:10 +00:00
|
|
|
CMapImages::CMapImages() : CMapImages(100)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CMapImages::CMapImages(int TextureSize)
|
2008-09-01 05:54:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Count = 0;
|
2019-05-06 12:19:10 +00:00
|
|
|
m_TextureScale = TextureSize;
|
2012-08-12 10:41:50 +00:00
|
|
|
m_EntitiesIsLoaded = false;
|
2020-08-19 05:05:51 +00:00
|
|
|
m_SpeedupArrowIsLoaded = false;
|
2020-08-23 06:25:21 +00:00
|
|
|
|
|
|
|
mem_zero(m_aTextureUsedByTileOrQuadLayerFlag, sizeof(m_aTextureUsedByTileOrQuadLayerFlag));
|
2017-09-12 18:15:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-13 18:33:58 +00:00
|
|
|
void CMapImages::OnInit()
|
|
|
|
{
|
2019-05-06 12:19:10 +00:00
|
|
|
InitOverlayTextures();
|
2008-09-01 05:54:00 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMapImages::OnMapLoad()
|
2008-09-01 05:54:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IMap *pMap = Kernel()->RequestInterface<IMap>();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-01 05:54:00 +00:00
|
|
|
// unload all textures
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_Count; i++)
|
2008-09-01 05:54:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->UnloadTexture(m_aTextures[i]);
|
2012-08-12 10:41:50 +00:00
|
|
|
m_aTextures[i] = IGraphics::CTextureHandle();
|
2020-08-23 06:25:21 +00:00
|
|
|
m_aTextureUsedByTileOrQuadLayerFlag[i] = 0;
|
2008-09-01 05:54:00 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Count = 0;
|
2008-09-01 05:54:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int Start;
|
|
|
|
pMap->GetType(MAPITEMTYPE_IMAGE, &Start, &m_Count);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-08-19 05:05:51 +00:00
|
|
|
CLayers *pLayers = m_pClient->Layers();
|
|
|
|
for(int g = 0; g < pLayers->NumGroups(); g++)
|
2015-08-25 00:11:04 +00:00
|
|
|
{
|
2020-08-19 05:05:51 +00:00
|
|
|
CMapItemGroup *pGroup = pLayers->GetGroup(g);
|
|
|
|
if(!pGroup)
|
2015-08-25 00:11:04 +00:00
|
|
|
{
|
2020-08-19 05:05:51 +00:00
|
|
|
continue;
|
2015-08-25 00:11:04 +00:00
|
|
|
}
|
2020-08-19 05:05:51 +00:00
|
|
|
|
|
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
2015-08-25 00:11:04 +00:00
|
|
|
{
|
2020-08-19 05:05:51 +00:00
|
|
|
CMapItemLayer *pLayer = pLayers->GetLayer(pGroup->m_StartLayer+l);
|
|
|
|
if(pLayer->m_Type == LAYERTYPE_TILES)
|
|
|
|
{
|
|
|
|
CMapItemLayerTilemap *pTLayer = (CMapItemLayerTilemap *)pLayer;
|
|
|
|
if(pTLayer->m_Image != -1 && pTLayer->m_Image < (int)(sizeof(m_aTextures) / sizeof(m_aTextures[0])))
|
|
|
|
{
|
2020-08-23 06:25:21 +00:00
|
|
|
m_aTextureUsedByTileOrQuadLayerFlag[(size_t)pTLayer->m_Image] |= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(pLayer->m_Type == LAYERTYPE_QUADS)
|
|
|
|
{
|
|
|
|
CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer;
|
|
|
|
if(pQLayer->m_Image != -1 && pQLayer->m_Image < (int)(sizeof(m_aTextures) / sizeof(m_aTextures[0])))
|
|
|
|
{
|
|
|
|
m_aTextureUsedByTileOrQuadLayerFlag[(size_t)pQLayer->m_Image] |= 2;
|
2020-08-19 05:05:51 +00:00
|
|
|
}
|
|
|
|
}
|
2015-08-25 00:11:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 05:05:51 +00:00
|
|
|
int TextureLoadFlag = Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
2015-08-25 00:11:04 +00:00
|
|
|
|
|
|
|
// load new textures
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int i = 0; i < m_Count; i++)
|
2008-09-01 05:54:00 +00:00
|
|
|
{
|
2020-08-23 06:25:21 +00:00
|
|
|
int LoadFlag = (((m_aTextureUsedByTileOrQuadLayerFlag[i] & 1) != 0) ? TextureLoadFlag : 0) | (((m_aTextureUsedByTileOrQuadLayerFlag[i] & 2) != 0) ? 0 : (Graphics()->IsTileBufferingEnabled() ? IGraphics::TEXLOAD_NO_2D_TEXTURE : 0));
|
2010-05-29 07:25:38 +00:00
|
|
|
CMapItemImage *pImg = (CMapItemImage *)pMap->GetItem(Start+i, 0, 0);
|
|
|
|
if(pImg->m_External)
|
2008-09-01 05:54:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
char Buf[256];
|
|
|
|
char *pName = (char *)pMap->GetData(pImg->m_ImageName);
|
|
|
|
str_format(Buf, sizeof(Buf), "mapres/%s.png", pName);
|
2020-08-23 06:25:21 +00:00
|
|
|
m_aTextures[i] = Graphics()->LoadTexture(Buf, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, LoadFlag);
|
2008-09-01 05:54:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
void *pData = pMap->GetData(pImg->m_ImageData);
|
2020-08-23 06:25:21 +00:00
|
|
|
m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, CImageInfo::FORMAT_RGBA, pData, CImageInfo::FORMAT_RGBA, LoadFlag);
|
2010-05-29 07:25:38 +00:00
|
|
|
pMap->UnloadData(pImg->m_ImageData);
|
2008-09-01 05:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 05:05:51 +00:00
|
|
|
void CMapImages::LoadBackground(class IMap *pMap)
|
|
|
|
{
|
|
|
|
CMapImages::OnMapLoad();
|
|
|
|
}
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::GetEntities()
|
2011-03-16 12:48:16 +00:00
|
|
|
{
|
2019-06-03 19:52:14 +00:00
|
|
|
// DDNet default to prevent delay in seeing entities
|
|
|
|
const char *pEntities = "ddnet";
|
|
|
|
if(GameClient()->m_GameInfo.m_EntitiesDDNet)
|
|
|
|
pEntities = "ddnet";
|
|
|
|
else if(GameClient()->m_GameInfo.m_EntitiesDDRace)
|
|
|
|
pEntities = "ddrace";
|
|
|
|
else if(GameClient()->m_GameInfo.m_EntitiesRace)
|
|
|
|
pEntities = "race";
|
2020-05-19 15:13:34 +00:00
|
|
|
else if (GameClient()->m_GameInfo.m_EntitiesBW)
|
|
|
|
pEntities = "blockworlds";
|
2019-06-03 19:52:14 +00:00
|
|
|
else if(GameClient()->m_GameInfo.m_EntitiesFNG)
|
|
|
|
pEntities = "fng";
|
|
|
|
else if(GameClient()->m_GameInfo.m_EntitiesVanilla)
|
|
|
|
pEntities = "vanilla";
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
if(!m_EntitiesIsLoaded || m_pEntitiesGameType != pEntities)
|
2011-03-16 12:48:16 +00:00
|
|
|
{
|
2019-06-03 19:52:14 +00:00
|
|
|
char aPath[64];
|
|
|
|
str_format(aPath, sizeof(aPath), "editor/entities_clear/%s.png", pEntities);
|
|
|
|
|
2017-03-02 08:27:03 +00:00
|
|
|
if(m_EntitiesTextures >= 0)
|
|
|
|
Graphics()->UnloadTexture(m_EntitiesTextures);
|
2020-08-19 05:05:51 +00:00
|
|
|
int TextureLoadFlag = Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE;
|
|
|
|
m_EntitiesTextures = Graphics()->LoadTexture(aPath, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, TextureLoadFlag);
|
2012-08-12 10:41:50 +00:00
|
|
|
m_EntitiesIsLoaded = true;
|
2019-06-03 19:52:14 +00:00
|
|
|
m_pEntitiesGameType = pEntities;
|
2011-03-16 12:48:16 +00:00
|
|
|
}
|
|
|
|
return m_EntitiesTextures;
|
|
|
|
}
|
2017-09-12 18:15:37 +00:00
|
|
|
|
2020-08-19 05:05:51 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::GetSpeedupArrow()
|
|
|
|
{
|
|
|
|
if(!m_SpeedupArrowIsLoaded)
|
|
|
|
{
|
2020-08-23 06:25:21 +00:00
|
|
|
int TextureLoadFlag = (Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE_SINGLE_LAYER : IGraphics::TEXLOAD_TO_3D_TEXTURE_SINGLE_LAYER) | IGraphics::TEXLOAD_NO_2D_TEXTURE;
|
2020-08-19 05:05:51 +00:00
|
|
|
m_SpeedupArrowTexture = Graphics()->LoadTexture(g_pData->m_aImages[IMAGE_SPEEDUP_ARROW].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, TextureLoadFlag);
|
|
|
|
|
|
|
|
m_SpeedupArrowIsLoaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_SpeedupArrowTexture;
|
|
|
|
}
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::GetOverlayBottom()
|
2017-09-13 18:33:58 +00:00
|
|
|
{
|
2017-09-12 18:15:37 +00:00
|
|
|
return m_OverlayBottomTexture;
|
|
|
|
}
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::GetOverlayTop()
|
2017-09-13 18:33:58 +00:00
|
|
|
{
|
2017-09-12 18:15:37 +00:00
|
|
|
return m_OverlayTopTexture;
|
|
|
|
}
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::GetOverlayCenter()
|
2017-09-13 18:33:58 +00:00
|
|
|
{
|
2017-09-12 18:15:37 +00:00
|
|
|
return m_OverlayCenterTexture;
|
|
|
|
}
|
2019-05-06 12:19:10 +00:00
|
|
|
|
|
|
|
void CMapImages::SetTextureScale(int Scale)
|
|
|
|
{
|
|
|
|
if(m_TextureScale == Scale)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_TextureScale = Scale;
|
|
|
|
|
|
|
|
if(Graphics() && m_OverlayCenterTexture != -1) // check if component was initialized
|
|
|
|
{
|
|
|
|
// reinitialize component
|
|
|
|
Graphics()->UnloadTexture(m_OverlayBottomTexture);
|
|
|
|
Graphics()->UnloadTexture(m_OverlayTopTexture);
|
|
|
|
Graphics()->UnloadTexture(m_OverlayCenterTexture);
|
|
|
|
|
|
|
|
InitOverlayTextures();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CMapImages::GetTextureScale()
|
|
|
|
{
|
|
|
|
return m_TextureScale;
|
|
|
|
}
|
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
IGraphics::CTextureHandle CMapImages::UploadEntityLayerText(int TextureSize, int YOffset)
|
2019-05-06 12:19:10 +00:00
|
|
|
{
|
2020-08-22 06:09:10 +00:00
|
|
|
void *pMem = calloc(1024 * 1024 * 4, 1);
|
2019-05-06 12:19:10 +00:00
|
|
|
|
2020-08-22 06:09:10 +00:00
|
|
|
UpdateEntityLayerText(pMem, 4, 1024, 1024, TextureSize, YOffset, 0);
|
|
|
|
UpdateEntityLayerText(pMem, 4, 1024, 1024, TextureSize, YOffset, 1);
|
|
|
|
UpdateEntityLayerText(pMem, 4, 1024, 1024, TextureSize, YOffset, 2, 255);
|
2020-08-19 05:05:51 +00:00
|
|
|
|
2020-08-23 06:25:21 +00:00
|
|
|
int TextureLoadFlag = (Graphics()->HasTextureArrays() ? IGraphics::TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics::TEXLOAD_TO_3D_TEXTURE) | IGraphics::TEXLOAD_NO_2D_TEXTURE;
|
2020-08-22 06:09:10 +00:00
|
|
|
IGraphics::CTextureHandle Texture = Graphics()->LoadTextureRaw(1024, 1024, CImageInfo::FORMAT_RGBA, pMem, CImageInfo::FORMAT_RGBA, TextureLoadFlag);
|
2020-08-19 05:05:51 +00:00
|
|
|
free(pMem);
|
2019-08-17 00:42:54 +00:00
|
|
|
|
2012-08-12 10:41:50 +00:00
|
|
|
return Texture;
|
2019-08-17 00:42:54 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 06:09:10 +00:00
|
|
|
void CMapImages::UpdateEntityLayerText(void* pTexBuffer, int ImageColorChannelCount, int TexWidth, int TexHeight, int TextureSize, int YOffset, int NumbersPower, int MaxNumber)
|
2019-08-17 00:42:54 +00:00
|
|
|
{
|
2019-05-06 12:19:10 +00:00
|
|
|
char aBuf[4];
|
2019-08-17 00:42:54 +00:00
|
|
|
int DigitsCount = NumbersPower+1;
|
2019-05-06 12:19:10 +00:00
|
|
|
|
2019-08-17 00:42:54 +00:00
|
|
|
int CurrentNumber = pow(10, NumbersPower);
|
|
|
|
|
|
|
|
if (MaxNumber == -1)
|
|
|
|
MaxNumber = CurrentNumber*10-1;
|
|
|
|
|
|
|
|
str_format(aBuf, 4, "%d", CurrentNumber);
|
|
|
|
|
|
|
|
int CurrentNumberSuitableFontSize = TextRender()->AdjustFontSize(aBuf, DigitsCount, TextureSize);
|
|
|
|
int UniversalSuitableFontSize = CurrentNumberSuitableFontSize*0.9; // should be smoothed enough to fit any digits combination
|
2019-05-11 15:59:47 +00:00
|
|
|
|
2019-08-17 00:42:54 +00:00
|
|
|
int ApproximateTextWidth = TextRender()->CalculateTextWidth(aBuf, DigitsCount, 0, UniversalSuitableFontSize);
|
|
|
|
int XOffSet = (64-ApproximateTextWidth)/2;
|
|
|
|
YOffset += ((TextureSize - UniversalSuitableFontSize)/2);
|
2019-05-06 12:19:10 +00:00
|
|
|
|
2019-08-17 00:42:54 +00:00
|
|
|
for (; CurrentNumber <= MaxNumber; ++CurrentNumber)
|
2019-05-06 12:19:10 +00:00
|
|
|
{
|
2019-08-17 00:42:54 +00:00
|
|
|
str_format(aBuf, 4, "%d", CurrentNumber);
|
2019-05-06 12:19:10 +00:00
|
|
|
|
2019-08-17 00:42:54 +00:00
|
|
|
float x = (CurrentNumber%16)*64;
|
|
|
|
float y = (CurrentNumber/16)*64;
|
2019-05-06 12:19:10 +00:00
|
|
|
|
2020-08-22 06:09:10 +00:00
|
|
|
TextRender()->UploadEntityLayerText(pTexBuffer, ImageColorChannelCount, TexWidth, TexHeight, aBuf, DigitsCount, x+XOffSet, y+YOffset, UniversalSuitableFontSize);
|
2019-08-17 00:42:54 +00:00
|
|
|
}
|
2019-05-06 12:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMapImages::InitOverlayTextures()
|
|
|
|
{
|
|
|
|
int TextureSize = 64*m_TextureScale/100;
|
|
|
|
int TextureToVerticalCenterOffset = (64-TextureSize)/2; // should be used to move texture to the center of 64 pixels area
|
|
|
|
|
|
|
|
if(m_OverlayBottomTexture == -1)
|
|
|
|
{
|
|
|
|
m_OverlayBottomTexture = UploadEntityLayerText(TextureSize/2, 32+TextureToVerticalCenterOffset/2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_OverlayTopTexture == -1)
|
|
|
|
{
|
|
|
|
m_OverlayTopTexture = UploadEntityLayerText(TextureSize/2, TextureToVerticalCenterOffset/2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_OverlayCenterTexture == -1)
|
|
|
|
{
|
|
|
|
m_OverlayCenterTexture = UploadEntityLayerText(TextureSize, TextureToVerticalCenterOffset);
|
|
|
|
}
|
|
|
|
}
|