| 286 | } |
| 287 | |
| 288 | bool CSkins::LoadSkinData(const char *pName, CSkinLoadData &Data) const |
| 289 | { |
| 290 | if(!Graphics()->CheckImageDivisibility(pName, Data.m_Info, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridy, true)) |
| 291 | { |
| 292 | log_error("skins", "Skin failed image divisibility: %s", pName); |
| 293 | Data.m_Info.Free(); |
| 294 | return false; |
| 295 | } |
| 296 | if(!Graphics()->IsImageFormatRgba(pName, Data.m_Info)) |
| 297 | { |
| 298 | log_error("skins", "Skin format is not RGBA: %s", pName); |
| 299 | Data.m_Info.Free(); |
| 300 | return false; |
| 301 | } |
| 302 | const size_t BodyWidth = g_pData->m_aSprites[SPRITE_TEE_BODY].m_W * (Data.m_Info.m_Width / g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridx); |
| 303 | const size_t BodyHeight = g_pData->m_aSprites[SPRITE_TEE_BODY].m_H * (Data.m_Info.m_Height / g_pData->m_aSprites[SPRITE_TEE_BODY].m_pSet->m_Gridy); |
| 304 | if(BodyWidth > Data.m_Info.m_Width || BodyHeight > Data.m_Info.m_Height) |
| 305 | { |
| 306 | log_error("skins", "Skin size unsupported (w=%" PRIzu ", h=%" PRIzu "): %s", Data.m_Info.m_Width, Data.m_Info.m_Height, pName); |
| 307 | Data.m_Info.Free(); |
| 308 | return false; |
| 309 | } |
| 310 | |
| 311 | int FeetGridPixelsWidth = Data.m_Info.m_Width / g_pData->m_aSprites[SPRITE_TEE_FOOT].m_pSet->m_Gridx; |
| 312 | int FeetGridPixelsHeight = Data.m_Info.m_Height / g_pData->m_aSprites[SPRITE_TEE_FOOT].m_pSet->m_Gridy; |
| 313 | int FeetWidth = g_pData->m_aSprites[SPRITE_TEE_FOOT].m_W * FeetGridPixelsWidth; |
| 314 | int FeetHeight = g_pData->m_aSprites[SPRITE_TEE_FOOT].m_H * FeetGridPixelsHeight; |
| 315 | int FeetOffsetX = g_pData->m_aSprites[SPRITE_TEE_FOOT].m_X * FeetGridPixelsWidth; |
| 316 | int FeetOffsetY = g_pData->m_aSprites[SPRITE_TEE_FOOT].m_Y * FeetGridPixelsHeight; |
| 317 | |
| 318 | int FeetOutlineGridPixelsWidth = Data.m_Info.m_Width / g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_pSet->m_Gridx; |
| 319 | int FeetOutlineGridPixelsHeight = Data.m_Info.m_Height / g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_pSet->m_Gridy; |
| 320 | int FeetOutlineWidth = g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_W * FeetOutlineGridPixelsWidth; |
| 321 | int FeetOutlineHeight = g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_H * FeetOutlineGridPixelsHeight; |
| 322 | int FeetOutlineOffsetX = g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_X * FeetOutlineGridPixelsWidth; |
| 323 | int FeetOutlineOffsetY = g_pData->m_aSprites[SPRITE_TEE_FOOT_OUTLINE].m_Y * FeetOutlineGridPixelsHeight; |
| 324 | |
| 325 | int BodyOutlineGridPixelsWidth = Data.m_Info.m_Width / g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_pSet->m_Gridx; |
| 326 | int BodyOutlineGridPixelsHeight = Data.m_Info.m_Height / g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_pSet->m_Gridy; |
| 327 | int BodyOutlineWidth = g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_W * BodyOutlineGridPixelsWidth; |
| 328 | int BodyOutlineHeight = g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_H * BodyOutlineGridPixelsHeight; |
| 329 | int BodyOutlineOffsetX = g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_X * BodyOutlineGridPixelsWidth; |
| 330 | int BodyOutlineOffsetY = g_pData->m_aSprites[SPRITE_TEE_BODY_OUTLINE].m_Y * BodyOutlineGridPixelsHeight; |
| 331 | |
| 332 | const size_t PixelStep = Data.m_Info.PixelSize(); |
| 333 | const size_t Pitch = Data.m_Info.m_Width * PixelStep; |
| 334 | |
| 335 | // dig out blood color |
| 336 | { |
| 337 | int64_t aColors[3] = {0}; |
| 338 | for(size_t y = 0; y < BodyHeight; y++) |
| 339 | { |
| 340 | for(size_t x = 0; x < BodyWidth; x++) |
| 341 | { |
| 342 | const size_t Offset = y * Pitch + x * PixelStep; |
| 343 | if(Data.m_Info.m_pData[Offset + 3] > 128) |
| 344 | { |
| 345 | for(size_t c = 0; c < 3; c++) |
no test coverage detected