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. */
2023-10-31 19:56:14 +00:00
# include "mapimages.h"
2023-08-13 09:50:35 +00:00
# include <base/log.h>
2010-05-29 07:25:38 +00:00
# include <engine/graphics.h>
# include <engine/map.h>
2020-09-26 19:41:58 +00:00
# include <engine/storage.h>
2017-09-12 18:15:37 +00:00
# include <engine/textrender.h>
2008-09-01 05:54:00 +00:00
2023-08-13 09:50:35 +00:00
# include <game/client/gameclient.h>
# include <game/generated/client_data.h>
2021-07-12 09:29:59 +00:00
# include <game/layers.h>
2023-10-31 19:56:14 +00:00
# include <game/localization.h>
2023-08-13 09:50:35 +00:00
# include <game/mapitems.h>
2021-07-12 09:29:59 +00:00
2023-10-31 19:56:14 +00:00
# include <chrono>
using namespace std : : chrono_literals ;
2008-09-01 05:54:00 +00:00
2022-06-30 22:36:32 +00:00
const char * const gs_apModEntitiesNames [ ] = {
2022-03-21 08:01:56 +00:00
" ddnet " ,
" ddrace " ,
" race " ,
" blockworlds " ,
" fng " ,
" vanilla " ,
" f-ddrace " ,
} ;
2020-09-26 19:41:58 +00:00
CMapImages : : CMapImages ( ) :
CMapImages ( 100 )
2019-05-06 12:19:10 +00:00
{
}
2020-09-26 19:41:58 +00:00
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 ;
2022-06-30 22:36:32 +00:00
mem_zero ( m_aEntitiesIsLoaded , sizeof ( m_aEntitiesIsLoaded ) ) ;
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 ) ) ;
2020-09-26 07:37:35 +00:00
2022-07-09 16:14:56 +00:00
str_copy ( m_aEntitiesPath , " editor/entities_clear " ) ;
2020-09-26 07:37:35 +00:00
2022-06-30 22:36:32 +00:00
static_assert ( std : : size ( gs_apModEntitiesNames ) = = MAP_IMAGE_MOD_TYPE_COUNT , " Mod name string count is not equal to mod type count " ) ;
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 ( ) ;
2020-09-26 07:37:35 +00:00
2023-08-29 18:26:59 +00:00
if ( str_comp ( g_Config . m_ClAssetsEntities , " default " ) = = 0 )
2022-07-09 16:14:56 +00:00
str_copy ( m_aEntitiesPath , " editor/entities_clear " ) ;
2020-09-26 07:37:35 +00:00
else
{
2023-08-29 18:26:59 +00:00
str_format ( m_aEntitiesPath , sizeof ( m_aEntitiesPath ) , " assets/entities/%s " , g_Config . m_ClAssetsEntities ) ;
2020-09-26 07:37:35 +00:00
}
2008-09-01 05:54:00 +00:00
}
2020-08-26 13:06:51 +00:00
void CMapImages : : OnMapLoadImpl ( class CLayers * pLayers , IMap * pMap )
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
{
2016-07-02 08:33:37 +00:00
Graphics ( ) - > UnloadTexture ( & ( m_aTextures [ i ] ) ) ;
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
2023-10-28 15:36:28 +00:00
m_Count = clamp < int > ( m_Count , 0 , MAX_MAPIMAGES ) ;
2020-09-19 18:52:28 +00:00
2020-08-19 05:05:51 +00:00
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-09-26 19:41:58 +00:00
CMapItemLayer * pLayer = pLayers - > GetLayer ( pGroup - > m_StartLayer + l ) ;
2020-08-19 05:05:51 +00:00
if ( pLayer - > m_Type = = LAYERTYPE_TILES )
{
CMapItemLayerTilemap * pTLayer = ( CMapItemLayerTilemap * ) pLayer ;
2023-10-28 15:36:28 +00:00
if ( pTLayer - > m_Image > = 0 & & pTLayer - > m_Image < m_Count )
2020-08-19 05:05:51 +00:00
{
2020-09-10 22:42:42 +00:00
m_aTextureUsedByTileOrQuadLayerFlag [ pTLayer - > m_Image ] | = 1 ;
2020-08-23 06:25:21 +00:00
}
}
else if ( pLayer - > m_Type = = LAYERTYPE_QUADS )
{
CMapItemLayerQuads * pQLayer = ( CMapItemLayerQuads * ) pLayer ;
2023-10-28 15:36:28 +00:00
if ( pQLayer - > m_Image > = 0 & & pQLayer - > m_Image < m_Count )
2020-08-23 06:25:21 +00:00
{
2020-09-10 22:42:42 +00:00
m_aTextureUsedByTileOrQuadLayerFlag [ pQLayer - > m_Image ] | = 2 ;
2020-08-19 05:05:51 +00:00
}
}
2015-08-25 00:11:04 +00:00
}
}
2023-08-13 09:50:35 +00:00
const 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
2023-10-31 19:56:14 +00:00
bool ShowWarning = false ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < m_Count ; i + + )
2008-09-01 05:54:00 +00:00
{
2023-08-13 09:50:35 +00:00
const int LoadFlag = ( ( ( m_aTextureUsedByTileOrQuadLayerFlag [ i ] & 1 ) ! = 0 ) ? TextureLoadFlag : 0 ) | ( ( ( m_aTextureUsedByTileOrQuadLayerFlag [ i ] & 2 ) ! = 0 ) ? 0 : ( Graphics ( ) - > IsTileBufferingEnabled ( ) ? IGraphics : : TEXLOAD_NO_2D_TEXTURE : 0 ) ) ;
2023-04-27 15:13:35 +00:00
const CMapItemImage_v2 * pImg = ( CMapItemImage_v2 * ) pMap - > GetItem ( Start + i ) ;
2023-04-27 15:15:48 +00:00
const CImageInfo : : EImageFormat Format = pImg - > m_Version < CMapItemImage_v2 : : CURRENT_VERSION ? CImageInfo : : FORMAT_RGBA : CImageInfo : : ImageFormatFromInt ( pImg - > m_Format ) ;
2023-08-13 09:50:35 +00:00
const char * pName = pMap - > GetDataString ( pImg - > m_ImageName ) ;
if ( pName = = nullptr | | pName [ 0 ] = = ' \0 ' )
{
2023-10-31 19:34:32 +00:00
if ( pImg - > m_External )
{
log_error ( " mapimages " , " Failed to load map image %d: failed to load name. " , i ) ;
2023-10-31 19:56:14 +00:00
ShowWarning = true ;
2023-10-31 19:34:32 +00:00
continue ;
}
pName = " (error) " ;
2023-08-13 09:50:35 +00:00
}
2023-07-16 13:26:00 +00:00
if ( pImg - > m_External )
2008-09-01 05:54:00 +00:00
{
2021-09-13 08:06:34 +00:00
char aPath [ IO_MAX_PATH_LENGTH ] ;
str_format ( aPath , sizeof ( aPath ) , " mapres/%s.png " , pName ) ;
2023-04-27 15:15:48 +00:00
m_aTextures [ i ] = Graphics ( ) - > LoadTexture ( aPath , IStorage : : TYPE_ALL , LoadFlag ) ;
2023-07-16 13:26:00 +00:00
}
2023-08-13 09:50:35 +00:00
else if ( Format = = CImageInfo : : FORMAT_RGBA )
2008-09-01 05:54:00 +00:00
{
2010-05-29 07:25:38 +00:00
void * pData = pMap - > GetData ( pImg - > m_ImageData ) ;
2023-08-13 09:50:35 +00:00
char aTexName [ IO_MAX_PATH_LENGTH ] ;
str_format ( aTexName , sizeof ( aTexName ) , " embedded: %s " , pName ) ;
2023-04-27 15:15:48 +00:00
m_aTextures [ i ] = Graphics ( ) - > LoadTextureRaw ( pImg - > m_Width , pImg - > m_Height , Format , pData , LoadFlag , aTexName ) ;
2010-05-29 07:25:38 +00:00
pMap - > UnloadData ( pImg - > m_ImageData ) ;
2008-09-01 05:54:00 +00:00
}
2023-08-13 09:50:35 +00:00
pMap - > UnloadData ( pImg - > m_ImageName ) ;
2023-10-31 19:56:14 +00:00
ShowWarning = ShowWarning | | m_aTextures [ i ] . Id ( ) = = Graphics ( ) - > InvalidTexture ( ) . Id ( ) ;
}
if ( ShowWarning )
{
m_pClient - > m_Menus . PopupWarning ( Localize ( " Warning " ) , Localize ( " Some map images could not be loaded. Check the local console for details. " ) , Localize ( " Ok " ) , 10 s ) ;
2008-09-01 05:54:00 +00:00
}
}
2020-08-26 13:06:51 +00:00
void CMapImages : : OnMapLoad ( )
{
IMap * pMap = Kernel ( ) - > RequestInterface < IMap > ( ) ;
CLayers * pLayers = m_pClient - > Layers ( ) ;
OnMapLoadImpl ( pLayers , pMap ) ;
}
void CMapImages : : LoadBackground ( class CLayers * pLayers , class IMap * pMap )
2020-08-19 05:05:51 +00:00
{
2020-08-26 13:06:51 +00:00
OnMapLoadImpl ( pLayers , pMap ) ;
2020-08-19 05:05:51 +00:00
}
2020-09-22 00:01:22 +00:00
bool CMapImages : : HasFrontLayer ( EMapImageModType ModType )
2020-09-08 13:11:32 +00:00
{
2020-09-22 00:01:22 +00:00
return ModType = = MAP_IMAGE_MOD_TYPE_DDNET | | ModType = = MAP_IMAGE_MOD_TYPE_DDRACE ;
2020-09-08 13:11:32 +00:00
}
2020-09-22 00:01:22 +00:00
bool CMapImages : : HasSpeedupLayer ( EMapImageModType ModType )
2020-09-08 13:11:32 +00:00
{
2020-09-22 00:01:22 +00:00
return ModType = = MAP_IMAGE_MOD_TYPE_DDNET | | ModType = = MAP_IMAGE_MOD_TYPE_DDRACE ;
2020-09-08 13:11:32 +00:00
}
2020-09-22 00:01:22 +00:00
bool CMapImages : : HasSwitchLayer ( EMapImageModType ModType )
2020-09-08 13:11:32 +00:00
{
2020-09-22 00:01:22 +00:00
return ModType = = MAP_IMAGE_MOD_TYPE_DDNET | | ModType = = MAP_IMAGE_MOD_TYPE_DDRACE ;
2020-09-08 13:11:32 +00:00
}
2020-09-22 00:01:22 +00:00
bool CMapImages : : HasTeleLayer ( EMapImageModType ModType )
2020-09-08 13:11:32 +00:00
{
2020-09-22 00:01:22 +00:00
return ModType = = MAP_IMAGE_MOD_TYPE_DDNET | | ModType = = MAP_IMAGE_MOD_TYPE_DDRACE ;
2020-09-08 13:11:32 +00:00
}
2020-09-22 00:01:22 +00:00
bool CMapImages : : HasTuneLayer ( EMapImageModType ModType )
2020-09-08 13:11:32 +00:00
{
2020-09-22 00:01:22 +00:00
return ModType = = MAP_IMAGE_MOD_TYPE_DDNET | | ModType = = MAP_IMAGE_MOD_TYPE_DDRACE ;
2020-09-08 13:11:32 +00:00
}
IGraphics : : CTextureHandle CMapImages : : GetEntities ( EMapImageEntityLayerType EntityLayerType )
2011-03-16 12:48:16 +00:00
{
2020-09-19 12:43:47 +00:00
EMapImageModType EntitiesModType = MAP_IMAGE_MOD_TYPE_DDNET ;
2022-06-30 17:45:10 +00:00
bool EntitiesAreMasked = ! GameClient ( ) - > m_GameInfo . m_DontMaskEntities ;
2020-09-08 13:11:32 +00:00
2020-12-21 15:45:19 +00:00
if ( GameClient ( ) - > m_GameInfo . m_EntitiesFDDrace )
EntitiesModType = MAP_IMAGE_MOD_TYPE_FDDRACE ;
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesDDNet )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_DDNET ;
2020-09-19 12:43:47 +00:00
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesDDRace )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_DDRACE ;
2019-06-03 19:52:14 +00:00
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesRace )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_RACE ;
2020-09-10 22:42:42 +00:00
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesBW )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_BLOCKWORLDS ;
2019-06-03 19:52:14 +00:00
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesFNG )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_FNG ;
2019-06-03 19:52:14 +00:00
else if ( GameClient ( ) - > m_GameInfo . m_EntitiesVanilla )
2020-09-08 13:11:32 +00:00
EntitiesModType = MAP_IMAGE_MOD_TYPE_VANILLA ;
2019-06-03 19:52:14 +00:00
2022-06-30 22:36:32 +00:00
if ( ! m_aEntitiesIsLoaded [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] )
2011-03-16 12:48:16 +00:00
{
2022-06-30 22:36:32 +00:00
m_aEntitiesIsLoaded [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] = true ;
2020-09-10 22:42:42 +00:00
2020-09-19 12:43:47 +00:00
// any mod that does not mask, will get all layers unmasked
2022-06-30 17:45:10 +00:00
bool WasUnknown = ! EntitiesAreMasked ;
2020-09-08 13:11:32 +00:00
2019-06-03 19:52:14 +00:00
char aPath [ 64 ] ;
2022-06-30 22:36:32 +00:00
str_format ( aPath , sizeof ( aPath ) , " %s/%s.png " , m_aEntitiesPath , gs_apModEntitiesNames [ EntitiesModType ] ) ;
2019-06-03 19:52:14 +00:00
2022-06-30 17:44:29 +00:00
bool GameTypeHasFrontLayer = HasFrontLayer ( EntitiesModType ) | | WasUnknown ;
bool GameTypeHasSpeedupLayer = HasSpeedupLayer ( EntitiesModType ) | | WasUnknown ;
bool GameTypeHasSwitchLayer = HasSwitchLayer ( EntitiesModType ) | | WasUnknown ;
bool GameTypeHasTeleLayer = HasTeleLayer ( EntitiesModType ) | | WasUnknown ;
bool GameTypeHasTuneLayer = HasTuneLayer ( EntitiesModType ) | | WasUnknown ;
2020-09-08 13:11:32 +00:00
2022-02-11 10:10:03 +00:00
int TextureLoadFlag = 0 ;
if ( Graphics ( ) - > IsTileBufferingEnabled ( ) )
TextureLoadFlag = ( Graphics ( ) - > HasTextureArrays ( ) ? IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics : : TEXLOAD_TO_3D_TEXTURE ) | IGraphics : : TEXLOAD_NO_2D_TEXTURE ;
2020-09-08 13:11:32 +00:00
CImageInfo ImgInfo ;
2020-09-26 07:37:35 +00:00
bool ImagePNGLoaded = false ;
if ( Graphics ( ) - > LoadPNG ( & ImgInfo , aPath , IStorage : : TYPE_ALL ) )
ImagePNGLoaded = true ;
else
{
bool TryDefault = true ;
// try as single ddnet replacement
if ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDNET )
{
str_format ( aPath , sizeof ( aPath ) , " %s.png " , m_aEntitiesPath ) ;
if ( Graphics ( ) - > LoadPNG ( & ImgInfo , aPath , IStorage : : TYPE_ALL ) )
{
ImagePNGLoaded = true ;
TryDefault = false ;
}
}
if ( ! ImagePNGLoaded & & TryDefault )
{
// try default
2022-06-30 22:36:32 +00:00
str_format ( aPath , sizeof ( aPath ) , " editor/entities_clear/%s.png " , gs_apModEntitiesNames [ EntitiesModType ] ) ;
2020-09-26 07:37:35 +00:00
if ( Graphics ( ) - > LoadPNG ( & ImgInfo , aPath , IStorage : : TYPE_ALL ) )
{
ImagePNGLoaded = true ;
}
}
}
if ( ImagePNGLoaded & & ImgInfo . m_Width > 0 & & ImgInfo . m_Height > 0 )
2020-09-08 13:11:32 +00:00
{
2023-04-27 15:15:48 +00:00
const size_t PixelSize = ImgInfo . PixelSize ( ) ;
const size_t BuildImageSize = ( size_t ) ImgInfo . m_Width * ImgInfo . m_Height * PixelSize ;
2020-09-10 22:42:42 +00:00
uint8_t * pTmpImgData = ( uint8_t * ) ImgInfo . m_pData ;
uint8_t * pBuildImgData = ( uint8_t * ) malloc ( BuildImageSize ) ;
2020-09-08 13:11:32 +00:00
// build game layer
2020-09-10 22:42:42 +00:00
for ( int n = 0 ; n < MAP_IMAGE_ENTITY_LAYER_TYPE_COUNT ; + + n )
2020-09-08 13:11:32 +00:00
{
bool BuildThisLayer = true ;
2023-01-13 14:25:38 +00:00
if ( n = = MAP_IMAGE_ENTITY_LAYER_TYPE_ALL_EXCEPT_SWITCH & & ! GameTypeHasFrontLayer & &
! GameTypeHasSpeedupLayer & & ! GameTypeHasTeleLayer & & ! GameTypeHasTuneLayer )
2020-09-08 13:11:32 +00:00
BuildThisLayer = false ;
2020-09-10 22:42:42 +00:00
else if ( n = = MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH & & ! GameTypeHasSwitchLayer )
2020-09-08 13:11:32 +00:00
BuildThisLayer = false ;
2022-06-30 22:36:32 +00:00
dbg_assert ( ! m_aaEntitiesTextures [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] [ n ] . IsValid ( ) , " entities texture already loaded when it should not be " ) ;
2020-09-08 13:11:32 +00:00
if ( BuildThisLayer )
{
// set everything transparent
mem_zero ( pBuildImgData , BuildImageSize ) ;
2020-09-10 22:42:42 +00:00
for ( int i = 0 ; i < 256 ; + + i )
2020-09-08 13:11:32 +00:00
{
bool ValidTile = i ! = 0 ;
2020-09-10 22:42:42 +00:00
int TileIndex = i ;
2022-06-30 17:45:10 +00:00
if ( EntitiesAreMasked )
2020-09-08 13:11:32 +00:00
{
2020-09-19 12:43:47 +00:00
if ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDNET | | EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDRACE )
2020-09-08 13:11:32 +00:00
{
2020-09-19 12:43:47 +00:00
if ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDNET | | TileIndex ! = TILE_BOOST )
2020-09-08 13:11:32 +00:00
{
2023-01-13 14:25:38 +00:00
if ( n = = MAP_IMAGE_ENTITY_LAYER_TYPE_ALL_EXCEPT_SWITCH & & ! IsValidGameTile ( ( int ) TileIndex ) & & ! IsValidFrontTile ( ( int ) TileIndex ) & & ! IsValidSpeedupTile ( ( int ) TileIndex ) & &
! IsValidTeleTile ( ( int ) TileIndex ) & & ! IsValidTuneTile ( ( int ) TileIndex ) )
2020-09-08 13:11:32 +00:00
ValidTile = false ;
2020-09-19 12:43:47 +00:00
else if ( n = = MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH )
2020-09-08 13:11:32 +00:00
{
2020-09-19 12:43:47 +00:00
if ( ! IsValidSwitchTile ( ( int ) TileIndex ) )
ValidTile = false ;
2020-09-10 22:42:42 +00:00
}
2020-09-08 13:11:32 +00:00
}
}
2020-09-19 12:43:47 +00:00
else if ( ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_RACE ) & & IsCreditsTile ( ( int ) TileIndex ) )
{
ValidTile = false ;
}
else if ( ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_FNG ) & & IsCreditsTile ( ( int ) TileIndex ) )
{
ValidTile = false ;
}
else if ( ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_VANILLA ) & & IsCreditsTile ( ( int ) TileIndex ) )
{
ValidTile = false ;
}
2020-09-08 13:11:32 +00:00
}
2020-09-19 12:43:47 +00:00
if ( EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDNET | | EntitiesModType = = MAP_IMAGE_MOD_TYPE_DDRACE )
2020-09-08 13:11:32 +00:00
{
2020-09-19 12:43:47 +00:00
if ( n = = MAP_IMAGE_ENTITY_LAYER_TYPE_SWITCH & & TileIndex = = TILE_SWITCHTIMEDOPEN )
TileIndex = 8 ;
2020-09-08 13:11:32 +00:00
}
2020-09-10 22:42:42 +00:00
int X = TileIndex % 16 ;
int Y = TileIndex / 16 ;
2020-09-08 13:11:32 +00:00
2020-09-10 22:42:42 +00:00
int CopyWidth = ImgInfo . m_Width / 16 ;
int CopyHeight = ImgInfo . m_Height / 16 ;
2020-09-08 13:11:32 +00:00
if ( ValidTile )
{
2023-04-27 15:15:48 +00:00
Graphics ( ) - > CopyTextureBufferSub ( pBuildImgData , pTmpImgData , ImgInfo . m_Width , ImgInfo . m_Height , PixelSize , ( size_t ) X * CopyWidth , ( size_t ) Y * CopyHeight , CopyWidth , CopyHeight ) ;
2020-09-08 13:11:32 +00:00
}
}
2023-04-27 15:15:48 +00:00
m_aaEntitiesTextures [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] [ n ] = Graphics ( ) - > LoadTextureRaw ( ImgInfo . m_Width , ImgInfo . m_Height , ImgInfo . m_Format , pBuildImgData , TextureLoadFlag , aPath ) ;
2020-09-08 13:11:32 +00:00
}
else
{
2012-08-12 12:02:50 +00:00
if ( ! m_TransparentTexture . IsValid ( ) )
2020-09-08 13:11:32 +00:00
{
// set everything transparent
mem_zero ( pBuildImgData , BuildImageSize ) ;
2023-04-27 15:15:48 +00:00
m_TransparentTexture = Graphics ( ) - > LoadTextureRaw ( ImgInfo . m_Width , ImgInfo . m_Height , ImgInfo . m_Format , pBuildImgData , TextureLoadFlag , aPath ) ;
2020-09-08 13:11:32 +00:00
}
2022-06-30 22:36:32 +00:00
m_aaEntitiesTextures [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] [ n ] = m_TransparentTexture ;
2020-09-10 22:42:42 +00:00
}
2020-09-08 13:11:32 +00:00
}
free ( pBuildImgData ) ;
2020-11-25 12:05:53 +00:00
Graphics ( ) - > FreePNG ( & ImgInfo ) ;
2020-09-08 13:11:32 +00:00
}
2011-03-16 12:48:16 +00:00
}
2020-09-08 13:11:32 +00:00
2022-06-30 22:36:32 +00:00
return m_aaEntitiesTextures [ ( EntitiesModType * 2 ) + ( int ) EntitiesAreMasked ] [ EntityLayerType ] ;
2011-03-16 12:48:16 +00:00
}
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 ;
2023-04-27 15:15:48 +00:00
m_SpeedupArrowTexture = Graphics ( ) - > LoadTexture ( g_pData - > m_aImages [ IMAGE_SPEEDUP_ARROW ] . m_pFilename , IStorage : : TYPE_ALL , TextureLoadFlag ) ;
2020-08-19 05:05:51 +00:00
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
2020-09-26 07:37:35 +00:00
void CMapImages : : ChangeEntitiesPath ( const char * pPath )
{
if ( str_comp ( pPath , " default " ) = = 0 )
2022-07-09 16:14:56 +00:00
str_copy ( m_aEntitiesPath , " editor/entities_clear " ) ;
2020-09-26 07:37:35 +00:00
else
{
str_format ( m_aEntitiesPath , sizeof ( m_aEntitiesPath ) , " assets/entities/%s " , pPath ) ;
}
for ( int i = 0 ; i < MAP_IMAGE_MOD_TYPE_COUNT * 2 ; + + i )
{
2022-06-30 22:36:32 +00:00
if ( m_aEntitiesIsLoaded [ i ] )
2020-09-26 07:37:35 +00:00
{
for ( int n = 0 ; n < MAP_IMAGE_ENTITY_LAYER_TYPE_COUNT ; + + n )
{
2022-06-30 22:36:32 +00:00
if ( m_aaEntitiesTextures [ i ] [ n ] . IsValid ( ) )
Graphics ( ) - > UnloadTexture ( & ( m_aaEntitiesTextures [ i ] [ n ] ) ) ;
m_aaEntitiesTextures [ i ] [ n ] = IGraphics : : CTextureHandle ( ) ;
2020-09-26 07:37:35 +00:00
}
2022-06-30 22:36:32 +00:00
m_aEntitiesIsLoaded [ i ] = false ;
2020-09-26 07:37:35 +00:00
}
}
}
2019-05-06 12:19:10 +00:00
void CMapImages : : SetTextureScale ( int Scale )
{
if ( m_TextureScale = = Scale )
return ;
m_TextureScale = Scale ;
2012-08-12 12:02:50 +00:00
if ( Graphics ( ) & & m_OverlayCenterTexture . IsValid ( ) ) // check if component was initialized
2019-05-06 12:19:10 +00:00
{
// reinitialize component
2016-07-02 08:33:37 +00:00
Graphics ( ) - > UnloadTexture ( & m_OverlayBottomTexture ) ;
Graphics ( ) - > UnloadTexture ( & m_OverlayTopTexture ) ;
Graphics ( ) - > UnloadTexture ( & m_OverlayCenterTexture ) ;
2019-05-06 12:19:10 +00:00
2020-09-01 07:13:47 +00:00
m_OverlayBottomTexture = IGraphics : : CTextureHandle ( ) ;
m_OverlayTopTexture = IGraphics : : CTextureHandle ( ) ;
m_OverlayCenterTexture = IGraphics : : CTextureHandle ( ) ;
2019-05-06 12:19:10 +00:00
InitOverlayTextures ( ) ;
}
}
int CMapImages : : GetTextureScale ( )
{
return m_TextureScale ;
}
2020-08-26 13:56:23 +00:00
IGraphics : : CTextureHandle CMapImages : : UploadEntityLayerText ( int TextureSize , int MaxWidth , int YOffset )
2020-09-26 19:41:58 +00:00
{
2023-04-27 15:15:48 +00:00
const size_t Width = 1024 ;
const size_t Height = 1024 ;
const size_t PixelSize = CImageInfo : : PixelSize ( CImageInfo : : FORMAT_RGBA ) ;
void * pMem = calloc ( Width * Height * PixelSize , 1 ) ;
2019-05-06 12:19:10 +00:00
2023-04-27 15:15:48 +00:00
UpdateEntityLayerText ( pMem , PixelSize , Width , Height , TextureSize , MaxWidth , YOffset , 0 ) ;
UpdateEntityLayerText ( pMem , PixelSize , Width , Height , TextureSize , MaxWidth , YOffset , 1 ) ;
UpdateEntityLayerText ( pMem , PixelSize , Width , Height , TextureSize , MaxWidth , YOffset , 2 , 255 ) ;
2020-08-19 05:05:51 +00:00
2023-04-27 15:15:48 +00:00
const int TextureLoadFlag = ( Graphics ( ) - > HasTextureArrays ( ) ? IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics : : TEXLOAD_TO_3D_TEXTURE ) | IGraphics : : TEXLOAD_NO_2D_TEXTURE ;
IGraphics : : CTextureHandle Texture = Graphics ( ) - > LoadTextureRaw ( Width , Height , CImageInfo : : FORMAT_RGBA , pMem , 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
}
2023-04-27 15:15:48 +00:00
void CMapImages : : UpdateEntityLayerText ( void * pTexBuffer , size_t PixelSize , size_t TexWidth , size_t TexHeight , int TextureSize , int MaxWidth , 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 ] ;
2020-09-26 19:41:58 +00:00
int DigitsCount = NumbersPower + 1 ;
2019-05-06 12:19:10 +00:00
2023-02-28 20:31:40 +00:00
int CurrentNumber = std : : pow ( 10 , NumbersPower ) ;
2020-09-14 14:39:05 +00:00
if ( MaxNumber = = - 1 )
MaxNumber = CurrentNumber * 10 - 1 ;
2023-08-20 11:03:01 +00:00
str_from_int ( CurrentNumber , aBuf ) ;
2020-09-14 14:39:05 +00:00
2020-08-26 13:56:23 +00:00
int CurrentNumberSuitableFontSize = TextRender ( ) - > AdjustFontSize ( aBuf , DigitsCount , TextureSize , MaxWidth ) ;
2020-09-14 14:39:05 +00:00
int UniversalSuitableFontSize = CurrentNumberSuitableFontSize * 0.92f ; // should be smoothed enough to fit any digits combination
2019-05-11 15:59:47 +00:00
2020-09-14 14:39:05 +00:00
YOffset + = ( ( TextureSize - UniversalSuitableFontSize ) / 2 ) ;
2019-05-06 12:19:10 +00:00
2020-09-26 19:41:58 +00:00
for ( ; CurrentNumber < = MaxNumber ; + + CurrentNumber )
2019-05-06 12:19:10 +00:00
{
2023-08-20 11:03:01 +00:00
str_from_int ( CurrentNumber , aBuf ) ;
2019-05-06 12:19:10 +00:00
2020-09-26 19:41:58 +00:00
float x = ( CurrentNumber % 16 ) * 64 ;
float y = ( CurrentNumber / 16 ) * 64 ;
2019-05-06 12:19:10 +00:00
2020-09-14 14:39:05 +00:00
int ApproximateTextWidth = TextRender ( ) - > CalculateTextWidth ( aBuf , DigitsCount , 0 , UniversalSuitableFontSize ) ;
int XOffSet = ( MaxWidth - clamp ( ApproximateTextWidth , 0 , MaxWidth ) ) / 2 ;
2023-04-27 15:15:48 +00:00
TextRender ( ) - > UploadEntityLayerText ( pTexBuffer , PixelSize , TexWidth , TexHeight , ( TexWidth / 16 ) - XOffSet , ( TexHeight / 16 ) - YOffset , 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 ( )
{
2020-09-26 19:41:58 +00:00
int TextureSize = 64 * m_TextureScale / 100 ;
2020-10-19 12:18:23 +00:00
TextureSize = clamp ( TextureSize , 2 , 64 ) ;
2020-09-26 19:41:58 +00:00
int TextureToVerticalCenterOffset = ( 64 - TextureSize ) / 2 ; // should be used to move texture to the center of 64 pixels area
2012-08-12 12:02:50 +00:00
if ( ! m_OverlayBottomTexture . IsValid ( ) )
2019-05-06 12:19:10 +00:00
{
2020-09-26 19:41:58 +00:00
m_OverlayBottomTexture = UploadEntityLayerText ( TextureSize / 2 , 64 , 32 + TextureToVerticalCenterOffset / 2 ) ;
2019-05-06 12:19:10 +00:00
}
2012-08-12 12:02:50 +00:00
if ( ! m_OverlayTopTexture . IsValid ( ) )
2019-05-06 12:19:10 +00:00
{
2020-09-26 19:41:58 +00:00
m_OverlayTopTexture = UploadEntityLayerText ( TextureSize / 2 , 64 , TextureToVerticalCenterOffset / 2 ) ;
2019-05-06 12:19:10 +00:00
}
2012-08-12 12:02:50 +00:00
if ( ! m_OverlayCenterTexture . IsValid ( ) )
2019-05-06 12:19:10 +00:00
{
2020-08-26 13:56:23 +00:00
m_OverlayCenterTexture = UploadEntityLayerText ( TextureSize , 64 , TextureToVerticalCenterOffset ) ;
2019-05-06 12:19:10 +00:00
}
}