2301: map_convert_07: Check image width for divisibility by 16 r=heinrich5991 a=def-

As noticed on Sunny Land.

> [5:31 PM] redix: in theory it should be enough if width and height are divisible by 16

Now running this over our maps and fixing them manually.

Co-authored-by: def <dennis@felsin9.de>
This commit is contained in:
bors[bot] 2020-06-23 23:30:34 +00:00 committed by GitHub
commit de328c1360
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 4 deletions

View file

@ -809,7 +809,8 @@ public:
POPEVENT_NEW,
POPEVENT_SAVE,
POPEVENT_LARGELAYER,
POPEVENT_PREVENTUNUSEDTILES
POPEVENT_PREVENTUNUSEDTILES,
POPEVENT_IMAGEDIV16
};
int m_PopupEventType;

View file

@ -931,6 +931,12 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
{
m_Image = NewVal%m_pEditor->m_Map.m_lImages.size();
m_AutoMapperConfig = -1;
if(m_pEditor->m_Map.m_lImages[m_Image]->m_Width % 16 != 0)
{
m_pEditor->m_PopupEventType = m_pEditor->POPEVENT_IMAGEDIV16;
m_pEditor->m_PopupEventActivated = true;
}
}
}
else if(Prop == PROP_COLOR)

View file

@ -1091,6 +1091,8 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View, void *pContext)
pEditor->UI()->DoLabel(&Label, "Large layer", 20.0f, 0);
else if(pEditor->m_PopupEventType == POPEVENT_PREVENTUNUSEDTILES)
pEditor->UI()->DoLabel(&Label, "Unused tiles disabled", 20.0f, 0);
else if(pEditor->m_PopupEventType == POPEVENT_IMAGEDIV16)
pEditor->UI()->DoLabel(&Label, "Image width", 20.0f, 0);
View.HSplitBottom(10.0f, &View, 0);
View.HSplitBottom(20.0f, &View, &ButtonBar);
@ -1112,6 +1114,8 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View, void *pContext)
pEditor->UI()->DoLabel(&Label, "You are trying to set the height or width of a layer to more than 1000 tiles. This is actually possible, but only rarely necessary. It may cause the editor to work slower, larger file size as well as higher memory usage for client and server.", 10.0f, -1, Label.w-10.0f);
else if(pEditor->m_PopupEventType == POPEVENT_PREVENTUNUSEDTILES)
pEditor->UI()->DoLabel(&Label, "Unused tiles can't be placed by default because they could get a use later and then destroy your map.\nActivate the 'Unused' switch to be able to place every tile.", 10.0f, -1, Label.w-10.0f);
else if(pEditor->m_PopupEventType == POPEVENT_IMAGEDIV16)
pEditor->UI()->DoLabel(&Label, "The width of this image is not divisible by 16. This is required for images used in tile layers for Teeworlds 0.7 compatibility.", 10.0f, -1, Label.w-10.0f);
// button bar
ButtonBar.VSplitLeft(30.0f, 0, &ButtonBar);
@ -1137,7 +1141,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View, void *pContext)
}
ButtonBar.VSplitRight(30.0f, &ButtonBar, 0);
ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label);
if(pEditor->m_PopupEventType != POPEVENT_LARGELAYER && pEditor->m_PopupEventType != POPEVENT_PREVENTUNUSEDTILES)
if(pEditor->m_PopupEventType != POPEVENT_LARGELAYER && pEditor->m_PopupEventType != POPEVENT_PREVENTUNUSEDTILES && pEditor->m_PopupEventType != POPEVENT_IMAGEDIV16)
{
static int s_AbortButton = 0;
if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0))

View file

@ -23,6 +23,8 @@ void *g_pNewData[64];
int g_Index = 0;
int g_NextDataItemID = -1;
int g_aImageIDs[64];
int LoadPNG(CImageInfo *pImg, const char *pFilename)
{
unsigned char *pBuffer;
@ -58,6 +60,53 @@ int LoadPNG(CImageInfo *pImg, const char *pFilename)
return 1;
}
inline void IntsToStr(const int *pInts, int Num, char *pStr)
{
while(Num)
{
pStr[0] = (((*pInts)>>24)&0xff)-128;
pStr[1] = (((*pInts)>>16)&0xff)-128;
pStr[2] = (((*pInts)>>8)&0xff)-128;
pStr[3] = ((*pInts)&0xff)-128;
pStr += 4;
pInts++;
Num--;
}
// null terminate
pStr[-1] = 0;
}
bool CheckImageDimensions(void *pItem, int Type, const char *pFilename)
{
if(Type != MAPITEMTYPE_LAYER)
return true;
CMapItemLayer *pImgLayer = (CMapItemLayer *)pItem;
if(pImgLayer->m_Type != LAYERTYPE_TILES)
return true;
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pImgLayer;
if(pTMap->m_Image == -1)
return true;
int TypeImg = 0;
int ID = 0;
void *pItem2 = g_DataReader.GetItem(g_aImageIDs[pTMap->m_Image], &TypeImg, &ID);
if(TypeImg != MAPITEMTYPE_IMAGE)
return true;
CMapItemImage *pImgItem = (CMapItemImage *)pItem2;
if(pImgItem->m_Width % 16 == 0)
return true;
char aTileLayerName[12];
IntsToStr(pTMap->m_aName, sizeof(pTMap->m_aName)/sizeof(int), aTileLayerName);
char *pName = (char *)g_DataReader.GetData(pImgItem->m_ImageName);
dbg_msg("map_convert_07", "%s: Tile layer \"%s\" uses image \"%s\" with width %d, which is not divisible by 16. This is not supported in Teeworlds 0.7. Please scale the image and replace it manually.", pFilename, aTileLayerName, pName, pImgItem->m_Width);
return false;
}
void *ReplaceImageItem(void *pItem, int Type, CMapItemImage *pNewImgItem)
{
if(Type != MAPITEMTYPE_IMAGE)
@ -80,7 +129,7 @@ void *ReplaceImageItem(void *pItem, int Type, CMapItemImage *pNewImgItem)
*pNewImgItem = *pImgItem;
pNewImgItem->m_Width = ImgInfo.m_Width;
pNewImgItem->m_Width = ImgInfo.m_Width;
pNewImgItem->m_Height = ImgInfo.m_Height;
pNewImgItem->m_External = false;
int PixelSize = ImgInfo.m_Format == CImageInfo::FORMAT_RGB ? 3 : 4;
@ -137,12 +186,25 @@ int main(int argc, const char **argv)
g_NextDataItemID = g_DataReader.NumData();
int i = 0;
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
{
pItem = g_DataReader.GetItem(Index, &Type, &ID);
if(Type == MAPITEMTYPE_IMAGE)
g_aImageIDs[i++] = Index;
}
bool Success = true;
// add all items
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
{
CMapItemImage NewImageItem;
pItem = g_DataReader.GetItem(Index, &Type, &ID);
Size = g_DataReader.GetItemSize(Index);
Success &= CheckImageDimensions(pItem, Type, pSourceFileName);
pItem = ReplaceImageItem(pItem, Type, &NewImageItem);
if(!pItem)
return -1;
@ -166,5 +228,5 @@ int main(int argc, const char **argv)
g_DataReader.Close();
g_DataWriter.Finish();
return 0;
return Success ? 0 : -1;
}