mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
Merge #5766
5766: Added map_create_pixelart tool r=def- a=sctt works as shown in screenshot below: ![mcp_poc](https://user-images.githubusercontent.com/3328841/186209061-2dd0aa21-73a5-4ef8-8fcc-7b5645df9db7.png) Usage: map_create_pixelart <image.png> <img_pixelsize> <input_map> <layergroup_id> <layer_id> <pos_x> <pos_y> <quad_pixelsize> <output_map> [optimize=0|1] [centralize=0|1]" Notes: - use destination layer tiles as a reference for positions and pixels for sizes. - set img_pixelsize to 0 to consider the largest possible size. - set quad_pixelsize to 0 to consider the same value of img_pixelsize. - if image.png has not a perfect pixelart grid, result might be unexpected (manually fix img_pixelsize to get it better or just fix the image, or enable optimize). Options: - optimize tries to reduce the total number of quads, default: 1. (mappers say sometimes this is not useful, as they might want to add different envs/to per pixel) - centralize places all pivots at the same position, default: 0. (mappers say this might be useful for spinning animations) Co-authored-by: “sctt” <“sctt@sctt.it”> Co-authored-by: sctt <scottistefano91@gmail.com>
This commit is contained in:
commit
7375f2c9d7
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -55,6 +55,7 @@ dilate
|
|||
dummy_map
|
||||
fake_server
|
||||
map_convert_07
|
||||
map_create_pixelart
|
||||
map_diff
|
||||
map_extract
|
||||
map_find_env
|
||||
|
|
|
@ -2418,6 +2418,7 @@ if(TOOLS)
|
|||
dilate.cpp
|
||||
dummy_map.cpp
|
||||
map_convert_07.cpp
|
||||
map_create_pixelart.cpp
|
||||
map_diff.cpp
|
||||
map_extract.cpp
|
||||
map_find_env.cpp
|
||||
|
@ -2437,7 +2438,7 @@ if(TOOLS)
|
|||
string(REGEX REPLACE "\\.cpp$" "" TOOL "${T}")
|
||||
set(TOOL_DEPS ${DEPS})
|
||||
set(TOOL_LIBS ${LIBS})
|
||||
if(TOOL MATCHES "^(dilate|map_convert_07|map_optimize|map_extract|map_replace_image)$")
|
||||
if(TOOL MATCHES "^(dilate|map_convert_07|map_create_pixelart|map_optimize|map_extract|map_replace_image)$")
|
||||
list(APPEND TOOL_INCLUDE_DIRS ${PNG_INCLUDE_DIRS})
|
||||
list(APPEND TOOL_DEPS $<TARGET_OBJECTS:engine-gfx>)
|
||||
list(APPEND TOOL_LIBS ${PNG_LIBRARIES})
|
||||
|
|
395
src/tools/map_create_pixelart.cpp
Normal file
395
src/tools/map_create_pixelart.cpp
Normal file
|
@ -0,0 +1,395 @@
|
|||
#include <base/logger.h>
|
||||
#include <base/system.h>
|
||||
#include <engine/gfx/image_loader.h>
|
||||
#include <engine/graphics.h>
|
||||
#include <engine/shared/datafile.h>
|
||||
#include <engine/storage.h>
|
||||
#include <game/mapitems.h>
|
||||
|
||||
bool CreatePixelArt(const char[][64], const int[], const int[], int[], const bool[]);
|
||||
void InsertCurrentQuads(CDataFileReader &, CMapItemLayerQuads *, CQuad *);
|
||||
int InsertPixelArtQuads(CQuad *, int &, const CImageInfo &, const int[], const int[], const bool[]);
|
||||
|
||||
bool LoadPNG(CImageInfo *, const char *);
|
||||
bool OpenMaps(const char[][64], CDataFileReader &, CDataFileWriter &);
|
||||
void SaveOutputMap(CDataFileReader &, CDataFileWriter &, CMapItemLayerQuads *, int, CQuad *, int);
|
||||
|
||||
CMapItemLayerQuads *GetQuadLayer(CDataFileReader &, const int[], int *);
|
||||
CQuad CreateNewQuad(float, float, int, int, const uint8_t[], const int[]);
|
||||
|
||||
bool GetPixelClamped(const CImageInfo &, int, int, uint8_t[]);
|
||||
bool ComparePixel(const uint8_t[], const uint8_t[]);
|
||||
bool IsPixelOptimizable(const CImageInfo &, int, int, const uint8_t[], const bool[]);
|
||||
void SetVisitedPixels(const CImageInfo &, int, int, int, int, bool[]);
|
||||
|
||||
int GetImagePixelSize(const CImageInfo &);
|
||||
int FindSuperPixelSize(const CImageInfo &, const uint8_t[], int, int, int, bool[]);
|
||||
void GetOptimizedQuadSize(const CImageInfo &, int, const uint8_t[], int, int, int &, int &, bool[]);
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
CCmdlineFix CmdlineFix(&argc, &argv);
|
||||
log_set_global_logger_default();
|
||||
|
||||
if(argc < 11 || argc > 12)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "Invalid arguments");
|
||||
dbg_msg("map_create_pixelart", "Usage: %s <image.png> <img_pixelsize> <input_map> <layergroup_id> <layer_id> <pos_x> <pos_y> <quad_pixelsize> <output_map> [optimize=0|1] [centralize=0|1]", argv[0]);
|
||||
dbg_msg("map_create_pixelart", "Note: use destination layer tiles as a reference for positions and pixels for sizes.");
|
||||
dbg_msg("map_create_pixelart", "Note: set img_pixelsize to 0 to consider the largest possible size.");
|
||||
dbg_msg("map_create_pixelart", "Note: set quad_pixelsize to 0 to consider the same value of img_pixelsize.");
|
||||
dbg_msg("map_create_pixelart", "Note: if image.png has not a perfect pixelart grid, result might be unexpected, manually fix img_pixelsize to get it better.");
|
||||
dbg_msg("map_create_pixelart", "Options: optimize tries to reduce the total number of quads (default: 1).");
|
||||
dbg_msg("map_create_pixelart", "Options: centralize places all pivots at the same position (default: 0).");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char aFilenames[3][64];
|
||||
snprintf(aFilenames[0], 64, "%s", argv[3]); //input_map
|
||||
snprintf(aFilenames[1], 64, "%s", argv[9]); //output_map
|
||||
snprintf(aFilenames[2], 64, "%s", argv[1]); //image_file
|
||||
|
||||
int aLayerID[2] = {atoi(argv[4]), atoi(argv[5])}; //layergroup_id, layer_id
|
||||
int aStartingPos[2] = {atoi(argv[6]) * 32, atoi(argv[7]) * 32}; //pos_x, pos_y
|
||||
int aPixelSizes[2] = {atoi(argv[2]), atoi(argv[8])}; //quad_pixelsize, img_pixelsize
|
||||
|
||||
bool aArtOptions[3];
|
||||
aArtOptions[0] = argc >= 10 ? atoi(argv[10]) : true; //optimize
|
||||
aArtOptions[1] = argc >= 11 ? atoi(argv[11]) : false; //centralize
|
||||
|
||||
dbg_msg("map_create_pixelart", "image_file='%s'; image_pixelsize='%dpx'; input_map='%s'; layergroup_id='#%d'; layer_id='#%d'; pos_x='#%dpx'; pos_y='%dpx'; quad_pixelsize='%dpx'; output_map='%s'; optimize='%d'; centralize='%d'",
|
||||
aFilenames[2], aPixelSizes[0], aFilenames[1], aLayerID[0], aLayerID[1], aStartingPos[0], aStartingPos[1], aPixelSizes[1], aFilenames[2], aArtOptions[0], aArtOptions[1]);
|
||||
|
||||
return !CreatePixelArt(aFilenames, aLayerID, aStartingPos, aPixelSizes, aArtOptions);
|
||||
}
|
||||
|
||||
bool CreatePixelArt(const char aFilenames[3][64], const int aLayerID[2], const int aStartingPos[2], int aPixelSizes[2], const bool aArtOptions[2])
|
||||
{
|
||||
CImageInfo Img;
|
||||
if(!LoadPNG(&Img, aFilenames[2]))
|
||||
return false;
|
||||
|
||||
aPixelSizes[0] = aPixelSizes[0] ? aPixelSizes[0] : GetImagePixelSize(Img);
|
||||
aPixelSizes[1] = aPixelSizes[1] ? aPixelSizes[1] : aPixelSizes[0];
|
||||
|
||||
CDataFileReader InputMap;
|
||||
CDataFileWriter OutputMap;
|
||||
if(!OpenMaps(aFilenames, InputMap, OutputMap))
|
||||
return false;
|
||||
|
||||
int ItemNumber = 0;
|
||||
CMapItemLayerQuads *pQuadLayer = GetQuadLayer(InputMap, aLayerID, &ItemNumber);
|
||||
if(!pQuadLayer)
|
||||
return false;
|
||||
|
||||
int MaxNewQuads = ceil((Img.m_Width * Img.m_Height) / aPixelSizes[0]);
|
||||
CQuad *pQuads = new CQuad[pQuadLayer->m_NumQuads + MaxNewQuads];
|
||||
|
||||
InsertCurrentQuads(InputMap, pQuadLayer, pQuads);
|
||||
int QuadsCounter = InsertPixelArtQuads(pQuads, pQuadLayer->m_NumQuads, Img, aStartingPos, aPixelSizes, aArtOptions);
|
||||
SaveOutputMap(InputMap, OutputMap, pQuadLayer, ItemNumber, pQuads, ((int)sizeof(CQuad)) * (pQuadLayer->m_NumQuads + 1));
|
||||
delete[] pQuads;
|
||||
|
||||
dbg_msg("map_create_pixelart", "INFO: sucessfully added %d new pixelart quads.", QuadsCounter);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InsertCurrentQuads(CDataFileReader &InputMap, CMapItemLayerQuads *pQuadLayer, CQuad *pNewQuads)
|
||||
{
|
||||
CQuad *pCurrentQuads = (CQuad *)InputMap.GetDataSwapped(pQuadLayer->m_Data);
|
||||
for(int i = 0; i < pQuadLayer->m_NumQuads; i++)
|
||||
pNewQuads[i] = pCurrentQuads[i];
|
||||
}
|
||||
|
||||
int InsertPixelArtQuads(CQuad *pQuads, int &NumQuads, const CImageInfo &Img, const int aStartingPos[2], const int aPixelSizes[2], const bool aArtOptions[2])
|
||||
{
|
||||
int ImgPixelSize = aPixelSizes[0], QuadPixelSize = aPixelSizes[1], OriginalNumQuads = NumQuads;
|
||||
int aForcedPivot[2] = {std::numeric_limits<int>::max(), std::numeric_limits<int>::max()};
|
||||
bool *aVisitedPixels = new bool[Img.m_Height * Img.m_Width];
|
||||
memset(aVisitedPixels, 0, sizeof(bool) * Img.m_Height * Img.m_Width);
|
||||
|
||||
for(int y = 0; y < Img.m_Height; y += ImgPixelSize)
|
||||
for(int x = 0; x < Img.m_Width; x += ImgPixelSize)
|
||||
{
|
||||
uint8_t aPixel[4];
|
||||
if(aVisitedPixels[x + y * Img.m_Width] || !GetPixelClamped(Img, x, y, aPixel))
|
||||
continue;
|
||||
|
||||
int Width = 1, Height = 1;
|
||||
if(aArtOptions[0])
|
||||
GetOptimizedQuadSize(Img, ImgPixelSize, aPixel, x, y, Width, Height, aVisitedPixels);
|
||||
|
||||
float Posx = aStartingPos[0] + ((x / (float)ImgPixelSize) + (Width / 2.f)) * QuadPixelSize;
|
||||
float Posy = aStartingPos[1] + ((y / (float)ImgPixelSize) + (Height / 2.f)) * QuadPixelSize;
|
||||
if(aArtOptions[1] && aForcedPivot[0] == std::numeric_limits<int>::max())
|
||||
{
|
||||
aForcedPivot[0] = Posx;
|
||||
aForcedPivot[1] = Posy;
|
||||
}
|
||||
|
||||
pQuads[NumQuads] = CreateNewQuad(Posx, Posy, QuadPixelSize * Width, QuadPixelSize * Height, aPixel, aArtOptions[1] ? aForcedPivot : 0x0);
|
||||
NumQuads++;
|
||||
}
|
||||
delete[] aVisitedPixels;
|
||||
|
||||
return NumQuads - OriginalNumQuads;
|
||||
}
|
||||
|
||||
void GetOptimizedQuadSize(const CImageInfo &Img, const int ImgPixelSize, const uint8_t aPixel[4], const int PosX, const int PosY, int &Width, int &Height, bool aVisitedPixels[])
|
||||
{
|
||||
int w = 0, h = 0, OptimizedWidth = 0, OptimizedHeight = 0;
|
||||
|
||||
while(IsPixelOptimizable(Img, PosX + w, PosY + h, aPixel, aVisitedPixels))
|
||||
{
|
||||
while(IsPixelOptimizable(Img, PosX + w, PosY + h, aPixel, aVisitedPixels) && (!OptimizedHeight || h < OptimizedHeight))
|
||||
h += ImgPixelSize;
|
||||
|
||||
if(!OptimizedHeight || h < OptimizedHeight)
|
||||
OptimizedHeight = h;
|
||||
|
||||
h = 0;
|
||||
w += ImgPixelSize;
|
||||
OptimizedWidth = w;
|
||||
}
|
||||
|
||||
SetVisitedPixels(Img, PosX, PosY, OptimizedWidth, OptimizedHeight, aVisitedPixels);
|
||||
Width = OptimizedWidth / ImgPixelSize;
|
||||
Height = OptimizedHeight / ImgPixelSize;
|
||||
}
|
||||
|
||||
int GetImagePixelSize(const CImageInfo &Img)
|
||||
{
|
||||
int ImgPixelSize = std::numeric_limits<int>::max();
|
||||
bool *aVisitedPixels = new bool[Img.m_Height * Img.m_Width];
|
||||
memset(aVisitedPixels, 0, sizeof(bool) * Img.m_Height * Img.m_Width);
|
||||
|
||||
for(int y = 0; y < Img.m_Height && ImgPixelSize > 1; y++)
|
||||
for(int x = 0; x < Img.m_Width && ImgPixelSize > 1; x++)
|
||||
{
|
||||
uint8_t aPixel[4];
|
||||
if(aVisitedPixels[x + y * Img.m_Width])
|
||||
continue;
|
||||
|
||||
GetPixelClamped(Img, x, y, aPixel);
|
||||
int SuperPixelSize = FindSuperPixelSize(Img, aPixel, x, y, 1, aVisitedPixels);
|
||||
if(SuperPixelSize < ImgPixelSize)
|
||||
ImgPixelSize = SuperPixelSize;
|
||||
}
|
||||
delete[] aVisitedPixels;
|
||||
|
||||
dbg_msg("map_create_pixelart", "INFO: automatically detected img_pixelsize of %dpx", ImgPixelSize);
|
||||
return ImgPixelSize;
|
||||
}
|
||||
|
||||
int FindSuperPixelSize(const CImageInfo &Img, const uint8_t aPixel[4], const int PosX, const int PosY, const int CurrentSize, bool aVisitedPixels[])
|
||||
{
|
||||
if(PosX + CurrentSize >= Img.m_Width || PosY + CurrentSize >= Img.m_Height)
|
||||
{
|
||||
SetVisitedPixels(Img, PosX, PosY, CurrentSize, CurrentSize, aVisitedPixels);
|
||||
return CurrentSize;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
for(int j = 0; j < CurrentSize + 1; j++)
|
||||
{
|
||||
uint8_t aCheckPixel[4];
|
||||
int x = PosX, y = PosY;
|
||||
x += i == 0 ? j : CurrentSize;
|
||||
y += i == 0 ? CurrentSize : j;
|
||||
|
||||
GetPixelClamped(Img, x, y, aCheckPixel);
|
||||
if(x >= Img.m_Width || y >= Img.m_Height || !ComparePixel(aPixel, aCheckPixel))
|
||||
{
|
||||
SetVisitedPixels(Img, PosX, PosY, CurrentSize, CurrentSize, aVisitedPixels);
|
||||
return CurrentSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FindSuperPixelSize(Img, aPixel, PosX, PosY, CurrentSize + 1, aVisitedPixels);
|
||||
}
|
||||
|
||||
bool GetPixelClamped(const CImageInfo &Img, int x, int y, uint8_t aPixel[4])
|
||||
{
|
||||
x = clamp<int>(x, 0, (int)Img.m_Width - 1);
|
||||
y = clamp<int>(y, 0, (int)Img.m_Height - 1);
|
||||
memset(aPixel, 255, sizeof(uint8_t[4]));
|
||||
|
||||
int BPP = Img.m_Format == CImageInfo::FORMAT_RGB ? 3 : 4;
|
||||
for(int i = 0; i < BPP; i++)
|
||||
aPixel[i] = ((uint8_t *)Img.m_pData)[x * BPP + (Img.m_Width * BPP * y) + i];
|
||||
|
||||
return aPixel[3];
|
||||
}
|
||||
|
||||
bool ComparePixel(const uint8_t aPixel1[4], const uint8_t aPixel2[4])
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
if(aPixel1[i] != aPixel2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsPixelOptimizable(const CImageInfo &Img, const int PosX, const int PosY, const uint8_t aPixel[4], const bool aVisitedPixels[])
|
||||
{
|
||||
uint8_t aCheckPixel[4];
|
||||
return PosX < Img.m_Width && PosY < Img.m_Height && !aVisitedPixels[PosX + PosY * Img.m_Width] && GetPixelClamped(Img, PosX, PosY, aCheckPixel) && ComparePixel(aPixel, aCheckPixel);
|
||||
}
|
||||
|
||||
void SetVisitedPixels(const CImageInfo &Img, int PosX, int PosY, int Width, int Height, bool aVisitedPixels[])
|
||||
{
|
||||
for(int y = PosY; y < PosY + Height; y++)
|
||||
for(int x = PosX; x < PosX + Width; x++)
|
||||
aVisitedPixels[x + y * Img.m_Width] = true;
|
||||
}
|
||||
|
||||
CMapItemLayerQuads *GetQuadLayer(CDataFileReader &InputMap, const int aLayerID[2], int *pItemNumber)
|
||||
{
|
||||
int Start, Num;
|
||||
InputMap.GetType(MAPITEMTYPE_GROUP, &Start, &Num);
|
||||
|
||||
CMapItemGroup *pGroupItem = aLayerID[0] >= Num ? 0x0 : (CMapItemGroup *)InputMap.GetItem(Start + aLayerID[0], 0, 0);
|
||||
|
||||
if(!pGroupItem)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: unable to find layergroup '#%d'", aLayerID[0]);
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
InputMap.GetType(MAPITEMTYPE_LAYER, &Start, &Num);
|
||||
*pItemNumber = Start + pGroupItem->m_StartLayer + aLayerID[1];
|
||||
|
||||
CMapItemLayer *pLayerItem = aLayerID[1] >= pGroupItem->m_NumLayers ? 0x0 : (CMapItemLayer *)InputMap.GetItem(*pItemNumber, 0, 0);
|
||||
if(!pLayerItem)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: unable to find layer '#%d' in group '#%d'", aLayerID[1], aLayerID[0]);
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
if(pLayerItem->m_Type != LAYERTYPE_QUADS)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: layer '#%d' in group '#%d' is not a quad layer", aLayerID[1], aLayerID[0]);
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return (CMapItemLayerQuads *)pLayerItem;
|
||||
}
|
||||
|
||||
CQuad CreateNewQuad(const float PosX, const float PosY, const int Width, const int Heigth, const uint8_t aColor[4], const int aForcedPivot[2] = 0x0)
|
||||
{
|
||||
CQuad Quad;
|
||||
Quad.m_PosEnv = Quad.m_ColorEnv = -1;
|
||||
Quad.m_PosEnvOffset = Quad.m_ColorEnvOffset = 0;
|
||||
float x = f2fx(PosX), y = f2fx(PosY), w = f2fx(Width / 2.f), h = f2fx(Heigth / 2.f);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
Quad.m_aPoints[i].y = y - h;
|
||||
Quad.m_aPoints[i + 2].y = y + h;
|
||||
Quad.m_aPoints[i * 2].x = x - w;
|
||||
Quad.m_aPoints[i * 2 + 1].x = x + w;
|
||||
}
|
||||
|
||||
for(auto &QuadColor : Quad.m_aColors)
|
||||
{
|
||||
QuadColor.r = aColor[0];
|
||||
QuadColor.g = aColor[1];
|
||||
QuadColor.b = aColor[2];
|
||||
QuadColor.a = aColor[3];
|
||||
}
|
||||
|
||||
Quad.m_aPoints[4].x = aForcedPivot ? f2fx(aForcedPivot[0]) : x;
|
||||
Quad.m_aPoints[4].y = aForcedPivot ? f2fx(aForcedPivot[1]) : y;
|
||||
|
||||
return Quad;
|
||||
}
|
||||
|
||||
bool LoadPNG(CImageInfo *pImg, const char *pFilename)
|
||||
{
|
||||
IOHANDLE File = io_open(pFilename, IOFLAG_READ);
|
||||
if(!File)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: Unable to open file %s", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
io_seek(File, 0, IOSEEK_END);
|
||||
unsigned int FileSize = io_tell(File);
|
||||
io_seek(File, 0, IOSEEK_START);
|
||||
TImageByteBuffer ByteBuffer;
|
||||
SImageByteBuffer ImageByteBuffer(&ByteBuffer);
|
||||
|
||||
ByteBuffer.resize(FileSize);
|
||||
io_read(File, &ByteBuffer.front(), FileSize);
|
||||
io_close(File);
|
||||
|
||||
uint8_t *pImgBuffer = NULL;
|
||||
EImageFormat ImageFormat;
|
||||
int PngliteIncompatible;
|
||||
|
||||
if(!LoadPNG(ImageByteBuffer, pFilename, PngliteIncompatible, pImg->m_Width, pImg->m_Height, pImgBuffer, ImageFormat))
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: Unable to load a valid PNG from file %s", pFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(ImageFormat != IMAGE_FORMAT_RGBA && ImageFormat != IMAGE_FORMAT_RGB)
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: only RGB and RGBA PNG images are supported");
|
||||
free(pImgBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
pImg->m_pData = pImgBuffer;
|
||||
pImg->m_Format = ImageFormat == IMAGE_FORMAT_RGB ? CImageInfo::FORMAT_RGB : CImageInfo::FORMAT_RGBA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenMaps(const char pMapNames[2][64], CDataFileReader &InputMap, CDataFileWriter &OutputMap)
|
||||
{
|
||||
IStorage *pStorage = CreateLocalStorage();
|
||||
|
||||
if(!InputMap.Open(pStorage, pMapNames[0], IStorage::TYPE_ABSOLUTE))
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: unable to open map '%s'", pMapNames[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!OutputMap.Open(pStorage, pMapNames[1], IStorage::TYPE_ABSOLUTE))
|
||||
{
|
||||
dbg_msg("map_create_pixelart", "ERROR: unable to open map '%s'", pMapNames[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap, CMapItemLayerQuads *pNewItem, const int NewItemNumber, CQuad *pNewData, const int NewDataSize)
|
||||
{
|
||||
for(int i = 0; i < InputMap.NumItems(); i++)
|
||||
{
|
||||
int ID, Type;
|
||||
void *pItem = InputMap.GetItem(i, &Type, &ID);
|
||||
|
||||
if(Type == ITEMTYPE_EX)
|
||||
continue;
|
||||
if(i == NewItemNumber)
|
||||
pItem = pNewItem;
|
||||
|
||||
int Size = InputMap.GetItemSize(i);
|
||||
OutputMap.AddItem(Type, ID, Size, pItem);
|
||||
}
|
||||
|
||||
for(int i = 0; i < InputMap.NumData(); i++)
|
||||
{
|
||||
if(i == pNewItem->m_Data)
|
||||
OutputMap.AddData(NewDataSize, pNewData);
|
||||
else
|
||||
OutputMap.AddData(InputMap.GetDataSize(i), InputMap.GetData(i));
|
||||
}
|
||||
|
||||
OutputMap.Finish();
|
||||
}
|
Loading…
Reference in a new issue