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. */
2020-09-26 19:41:58 +00:00
# include "editor.h"
2010-10-30 12:06:28 +00:00
# include <engine/client.h>
2010-08-17 22:06:00 +00:00
# include <engine/console.h>
2010-05-29 07:25:38 +00:00
# include <engine/graphics.h>
2010-11-17 12:08:29 +00:00
# include <engine/serverbrowser.h>
2022-05-29 16:33:38 +00:00
# include <engine/shared/datafile.h>
# include <engine/sound.h>
2010-05-29 07:25:38 +00:00
# include <engine/storage.h>
2022-05-29 16:33:38 +00:00
2010-08-06 18:18:53 +00:00
# include <game/gamecore.h>
2018-10-08 20:44:49 +00:00
# include <game/mapitems_ex.h>
2008-01-17 23:09:49 +00:00
template < typename T >
2010-05-29 07:25:38 +00:00
static int MakeVersion ( int i , const T & v )
2020-09-26 19:41:58 +00:00
{
return ( i < < 16 ) + sizeof ( T ) ;
}
2008-01-17 23:09:49 +00:00
2014-12-05 13:38:16 +00:00
// compatibility with old sound layers
struct CSoundSource_DEPRECATED
{
CPoint m_Position ;
int m_Loop ;
int m_TimeDelay ; // in s
int m_FalloffDistance ;
int m_PosEnv ;
int m_PosEnvOffset ;
int m_SoundEnv ;
int m_SoundEnvOffset ;
} ;
2022-11-03 19:17:06 +00:00
bool CEditor : : Save ( const char * pFilename )
2008-03-09 23:29:14 +00:00
{
2023-06-26 18:48:16 +00:00
// Check if file with this name is already being saved at the moment
2023-07-16 17:51:11 +00:00
if ( std : : any_of ( std : : begin ( m_WriterFinishJobs ) , std : : end ( m_WriterFinishJobs ) , [ pFilename ] ( const std : : shared_ptr < CDataFileWriterFinishJob > & Job ) { return str_comp ( pFilename , Job - > GetRealFileName ( ) ) = = 0 ; } ) )
2023-06-26 18:48:16 +00:00
return false ;
2023-06-24 09:00:42 +00:00
return m_Map . Save ( pFilename ) ;
2008-03-09 23:29:14 +00:00
}
2023-06-24 09:00:42 +00:00
bool CEditorMap : : Save ( const char * pFileName )
2008-01-17 23:09:49 +00:00
{
2023-07-16 17:51:11 +00:00
char aFileNameTmp [ IO_MAX_PATH_LENGTH ] ;
str_format ( aFileNameTmp , sizeof ( aFileNameTmp ) , " %s.%d.tmp " , pFileName , pid ( ) ) ;
2023-06-25 08:34:41 +00:00
char aBuf [ IO_MAX_PATH_LENGTH + 64 ] ;
2023-07-16 17:51:11 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " saving to '%s'... " , aFileNameTmp ) ;
2010-08-17 22:06:00 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " editor " , aBuf ) ;
2023-07-16 16:26:20 +00:00
CDataFileWriter Writer ;
2023-07-16 17:51:11 +00:00
if ( ! Writer . Open ( m_pEditor - > Storage ( ) , aFileNameTmp ) )
2008-01-17 23:09:49 +00:00
{
2023-07-16 17:51:11 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " failed to open file '%s'... " , aFileNameTmp ) ;
2010-08-17 22:06:00 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " editor " , aBuf ) ;
2022-11-03 19:17:06 +00:00
return false ;
2008-01-17 23:09:49 +00:00
}
2011-04-13 18:37:12 +00:00
2008-01-17 23:09:49 +00:00
// save version
{
2010-05-29 07:25:38 +00:00
CMapItemVersion Item ;
2013-06-01 13:26:22 +00:00
Item . m_Version = CMapItemVersion : : CURRENT_VERSION ;
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_VERSION , 0 , sizeof ( Item ) , & Item ) ;
2008-01-17 23:09:49 +00:00
}
2011-07-12 21:31:39 +00:00
// save map info
{
2011-07-13 20:38:32 +00:00
CMapItemInfoSettings Item ;
2011-07-12 21:31:39 +00:00
Item . m_Version = 1 ;
if ( m_MapInfo . m_aAuthor [ 0 ] )
2023-07-16 16:26:20 +00:00
Item . m_Author = Writer . AddData ( str_length ( m_MapInfo . m_aAuthor ) + 1 , m_MapInfo . m_aAuthor ) ;
2011-07-12 21:31:39 +00:00
else
Item . m_Author = - 1 ;
if ( m_MapInfo . m_aVersion [ 0 ] )
2023-07-16 16:26:20 +00:00
Item . m_MapVersion = Writer . AddData ( str_length ( m_MapInfo . m_aVersion ) + 1 , m_MapInfo . m_aVersion ) ;
2011-07-12 21:31:39 +00:00
else
Item . m_MapVersion = - 1 ;
if ( m_MapInfo . m_aCredits [ 0 ] )
2023-07-16 16:26:20 +00:00
Item . m_Credits = Writer . AddData ( str_length ( m_MapInfo . m_aCredits ) + 1 , m_MapInfo . m_aCredits ) ;
2011-07-12 21:31:39 +00:00
else
Item . m_Credits = - 1 ;
if ( m_MapInfo . m_aLicense [ 0 ] )
2023-07-16 16:26:20 +00:00
Item . m_License = Writer . AddData ( str_length ( m_MapInfo . m_aLicense ) + 1 , m_MapInfo . m_aLicense ) ;
2011-07-12 21:31:39 +00:00
else
Item . m_License = - 1 ;
2011-07-13 20:38:32 +00:00
Item . m_Settings = - 1 ;
2022-06-11 19:38:18 +00:00
if ( ! m_vSettings . empty ( ) )
2011-07-13 20:38:32 +00:00
{
int Size = 0 ;
2022-06-11 19:38:18 +00:00
for ( const auto & Setting : m_vSettings )
2011-07-13 20:38:32 +00:00
{
2022-05-24 09:24:33 +00:00
Size + = str_length ( Setting . m_aCommand ) + 1 ;
2011-07-13 20:38:32 +00:00
}
2021-03-07 10:14:37 +00:00
char * pSettings = ( char * ) malloc ( maximum ( Size , 1 ) ) ;
2011-07-13 20:38:32 +00:00
char * pNext = pSettings ;
2022-06-11 19:38:18 +00:00
for ( const auto & Setting : m_vSettings )
2011-07-13 20:38:32 +00:00
{
2022-05-24 09:24:33 +00:00
int Length = str_length ( Setting . m_aCommand ) + 1 ;
mem_copy ( pNext , Setting . m_aCommand , Length ) ;
2015-08-27 10:47:13 +00:00
pNext + = Length ;
2011-07-13 20:38:32 +00:00
}
2023-07-16 16:26:20 +00:00
Item . m_Settings = Writer . AddData ( Size , pSettings ) ;
2018-04-09 09:56:39 +00:00
free ( pSettings ) ;
2011-07-13 20:38:32 +00:00
}
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_INFO , 0 , sizeof ( Item ) , & Item ) ;
2011-07-12 21:31:39 +00:00
}
2008-01-17 23:09:49 +00:00
// save images
2022-06-11 19:38:18 +00:00
for ( size_t i = 0 ; i < m_vpImages . size ( ) ; i + + )
2008-01-17 23:09:49 +00:00
{
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CEditorImage > pImg = m_vpImages [ i ] ;
2011-04-13 18:37:12 +00:00
2008-03-29 11:44:03 +00:00
// analyse the image for when saving (should be done when we load the image)
// TODO!
2010-05-29 07:25:38 +00:00
pImg - > AnalyseTileFlags ( ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
CMapItemImage Item ;
2023-04-27 15:13:35 +00:00
Item . m_Version = CMapItemImage : : CURRENT_VERSION ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
Item . m_Width = pImg - > m_Width ;
Item . m_Height = pImg - > m_Height ;
Item . m_External = pImg - > m_External ;
2023-07-16 16:26:20 +00:00
Item . m_ImageName = Writer . AddData ( str_length ( pImg - > m_aName ) + 1 , pImg - > m_aName ) ;
2010-05-29 07:25:38 +00:00
if ( pImg - > m_External )
2023-04-27 15:13:35 +00:00
{
2010-05-29 07:25:38 +00:00
Item . m_ImageData = - 1 ;
2023-04-27 15:13:35 +00:00
}
2008-01-19 14:23:53 +00:00
else
2015-04-04 15:16:20 +00:00
{
if ( pImg - > m_Format = = CImageInfo : : FORMAT_RGB )
2015-04-04 16:07:57 +00:00
{
// Convert to RGBA
2020-10-05 17:03:14 +00:00
unsigned char * pDataRGBA = ( unsigned char * ) malloc ( ( size_t ) Item . m_Width * Item . m_Height * 4 ) ;
2017-03-12 18:52:29 +00:00
unsigned char * pDataRGB = ( unsigned char * ) pImg - > m_pData ;
2022-03-20 11:57:50 +00:00
for ( int j = 0 ; j < Item . m_Width * Item . m_Height ; j + + )
2015-04-04 16:07:57 +00:00
{
2022-03-20 11:57:50 +00:00
pDataRGBA [ j * 4 ] = pDataRGB [ j * 3 ] ;
pDataRGBA [ j * 4 + 1 ] = pDataRGB [ j * 3 + 1 ] ;
pDataRGBA [ j * 4 + 2 ] = pDataRGB [ j * 3 + 2 ] ;
pDataRGBA [ j * 4 + 3 ] = 255 ;
2015-04-04 16:07:57 +00:00
}
2023-07-16 16:26:20 +00:00
Item . m_ImageData = Writer . AddData ( Item . m_Width * Item . m_Height * 4 , pDataRGBA ) ;
2018-04-09 09:56:39 +00:00
free ( pDataRGBA ) ;
2015-04-04 16:07:57 +00:00
}
2015-04-04 15:16:20 +00:00
else
2015-04-04 16:07:57 +00:00
{
2023-07-16 16:26:20 +00:00
Item . m_ImageData = Writer . AddData ( Item . m_Width * Item . m_Height * 4 , pImg - > m_pData ) ;
2015-04-04 16:07:57 +00:00
}
2015-04-04 15:16:20 +00:00
}
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_IMAGE , i , sizeof ( Item ) , & Item ) ;
2008-01-17 23:09:49 +00:00
}
2011-04-13 18:37:12 +00:00
2014-10-11 11:38:45 +00:00
// save sounds
2022-06-11 19:38:18 +00:00
for ( size_t i = 0 ; i < m_vpSounds . size ( ) ; i + + )
2014-10-11 11:38:45 +00:00
{
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CEditorSound > pSound = m_vpSounds [ i ] ;
2014-10-11 11:38:45 +00:00
CMapItemSound Item ;
Item . m_Version = 1 ;
2015-07-09 00:08:14 +00:00
2020-10-17 14:41:00 +00:00
Item . m_External = 0 ;
2023-07-16 16:26:20 +00:00
Item . m_SoundName = Writer . AddData ( str_length ( pSound - > m_aName ) + 1 , pSound - > m_aName ) ;
Item . m_SoundData = Writer . AddData ( pSound - > m_DataSize , pSound - > m_pData ) ;
2020-10-17 14:41:00 +00:00
Item . m_SoundDataSize = pSound - > m_DataSize ;
2015-07-09 00:08:14 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_SOUND , i , sizeof ( Item ) , & Item ) ;
2014-10-11 11:38:45 +00:00
}
2008-01-17 23:09:49 +00:00
// save layers
2010-10-16 16:50:05 +00:00
int LayerCount = 0 , GroupCount = 0 ;
2018-10-08 20:44:49 +00:00
int AutomapperCount = 0 ;
2022-06-11 19:38:18 +00:00
for ( const auto & pGroup : m_vpGroups )
2008-01-17 23:09:49 +00:00
{
2010-05-29 07:25:38 +00:00
CMapItemGroup GItem ;
GItem . m_Version = CMapItemGroup : : CURRENT_VERSION ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
GItem . m_ParallaxX = pGroup - > m_ParallaxX ;
GItem . m_ParallaxY = pGroup - > m_ParallaxY ;
GItem . m_OffsetX = pGroup - > m_OffsetX ;
GItem . m_OffsetY = pGroup - > m_OffsetY ;
GItem . m_UseClipping = pGroup - > m_UseClipping ;
GItem . m_ClipX = pGroup - > m_ClipX ;
GItem . m_ClipY = pGroup - > m_ClipY ;
GItem . m_ClipW = pGroup - > m_ClipW ;
GItem . m_ClipH = pGroup - > m_ClipH ;
GItem . m_StartLayer = LayerCount ;
GItem . m_NumLayers = 0 ;
2011-04-13 18:37:12 +00:00
2011-07-12 01:14:46 +00:00
// save group name
2020-09-26 19:41:58 +00:00
StrToInts ( GItem . m_aName , sizeof ( GItem . m_aName ) / sizeof ( int ) , pGroup - > m_aName ) ;
2011-07-12 01:14:46 +00:00
2022-08-10 01:51:03 +00:00
CMapItemGroupEx GItemEx ;
GItemEx . m_Version = CMapItemGroupEx : : CURRENT_VERSION ;
GItemEx . m_ParallaxZoom = pGroup - > m_ParallaxZoom ;
2022-08-04 23:16:44 +00:00
2023-07-28 11:16:18 +00:00
for ( const std : : shared_ptr < CLayer > & pLayer : pGroup - > m_vpLayers )
2008-01-17 23:09:49 +00:00
{
2022-05-24 09:24:33 +00:00
if ( pLayer - > m_Type = = LAYERTYPE_TILES )
2008-01-17 23:09:49 +00:00
{
2010-08-17 22:06:00 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " editor " , " saving tiles layer " ) ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerTiles > pLayerTiles = std : : static_pointer_cast < CLayerTiles > ( pLayer ) ;
2022-05-24 09:24:33 +00:00
pLayerTiles - > PrepareForSave ( ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
CMapItemLayerTilemap Item ;
2022-08-14 14:02:15 +00:00
Item . m_Version = CMapItemLayerTilemap : : CURRENT_VERSION ;
2011-04-13 18:37:12 +00:00
2020-10-13 07:53:33 +00:00
Item . m_Layer . m_Version = 0 ; // was previously uninitialized, do not rely on it being 0
2022-05-24 09:24:33 +00:00
Item . m_Layer . m_Flags = pLayerTiles - > m_Flags ;
Item . m_Layer . m_Type = pLayerTiles - > m_Type ;
2011-04-13 18:37:12 +00:00
2022-05-24 09:24:33 +00:00
Item . m_Color = pLayerTiles - > m_Color ;
Item . m_ColorEnv = pLayerTiles - > m_ColorEnv ;
Item . m_ColorEnvOffset = pLayerTiles - > m_ColorEnvOffset ;
2011-04-13 18:37:12 +00:00
2022-05-24 09:24:33 +00:00
Item . m_Width = pLayerTiles - > m_Width ;
Item . m_Height = pLayerTiles - > m_Height ;
// Item.m_Flags = pLayerTiles->m_Game ? TILESLAYERFLAG_GAME : 0;
2011-04-09 06:41:31 +00:00
2022-05-24 09:24:33 +00:00
if ( pLayerTiles - > m_Tele )
2011-08-13 00:12:40 +00:00
Item . m_Flags = TILESLAYERFLAG_TELE ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Speedup )
2011-08-13 00:12:40 +00:00
Item . m_Flags = TILESLAYERFLAG_SPEEDUP ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Front )
2011-08-13 00:12:40 +00:00
Item . m_Flags = TILESLAYERFLAG_FRONT ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Switch )
2011-08-13 00:12:40 +00:00
Item . m_Flags = TILESLAYERFLAG_SWITCH ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Tune )
2014-03-12 22:47:11 +00:00
Item . m_Flags = TILESLAYERFLAG_TUNE ;
2010-09-30 21:31:19 +00:00
else
2022-05-24 09:24:33 +00:00
Item . m_Flags = pLayerTiles - > m_Game ? TILESLAYERFLAG_GAME : 0 ;
2011-04-09 06:41:31 +00:00
2022-05-24 09:24:33 +00:00
Item . m_Image = pLayerTiles - > m_Image ;
2016-07-09 19:46:47 +00:00
2020-10-02 15:45:28 +00:00
// the following values were previously uninitialized, do not rely on them being -1 when unused
Item . m_Tele = - 1 ;
Item . m_Speedup = - 1 ;
Item . m_Front = - 1 ;
Item . m_Switch = - 1 ;
Item . m_Tune = - 1 ;
2022-05-24 09:24:33 +00:00
if ( Item . m_Flags & & ! ( pLayerTiles - > m_Game ) )
2014-03-12 22:47:11 +00:00
{
2022-05-24 09:24:33 +00:00
CTile * pEmptyTiles = ( CTile * ) calloc ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height , sizeof ( CTile ) ) ;
mem_zero ( pEmptyTiles , ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTile ) ) ;
2023-07-16 16:26:20 +00:00
Item . m_Data = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTile ) , pEmptyTiles ) ;
2018-04-09 09:56:39 +00:00
free ( pEmptyTiles ) ;
2016-07-09 19:46:47 +00:00
2022-05-24 09:24:33 +00:00
if ( pLayerTiles - > m_Tele )
2023-07-28 11:16:18 +00:00
Item . m_Tele = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTeleTile ) , std : : static_pointer_cast < CLayerTele > ( pLayerTiles ) - > m_pTeleTile ) ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Speedup )
2023-07-28 11:16:18 +00:00
Item . m_Speedup = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CSpeedupTile ) , std : : static_pointer_cast < CLayerSpeedup > ( pLayerTiles ) - > m_pSpeedupTile ) ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Front )
2023-07-16 16:26:20 +00:00
Item . m_Front = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTile ) , pLayerTiles - > m_pTiles ) ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Switch )
2023-07-28 11:16:18 +00:00
Item . m_Switch = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CSwitchTile ) , std : : static_pointer_cast < CLayerSwitch > ( pLayerTiles ) - > m_pSwitchTile ) ;
2022-05-24 09:24:33 +00:00
else if ( pLayerTiles - > m_Tune )
2023-07-28 11:16:18 +00:00
Item . m_Tune = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTuneTile ) , std : : static_pointer_cast < CLayerTune > ( pLayerTiles ) - > m_pTuneTile ) ;
2014-03-12 22:47:11 +00:00
}
2010-09-30 21:31:19 +00:00
else
2023-07-16 16:26:20 +00:00
Item . m_Data = Writer . AddData ( ( size_t ) pLayerTiles - > m_Width * pLayerTiles - > m_Height * sizeof ( CTile ) , pLayerTiles - > m_pTiles ) ;
2011-07-12 01:14:46 +00:00
// save layer name
2022-05-24 09:24:33 +00:00
StrToInts ( Item . m_aName , sizeof ( Item . m_aName ) / sizeof ( int ) , pLayerTiles - > m_aName ) ;
2011-07-12 01:14:46 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_LAYER , LayerCount , sizeof ( Item ) , & Item ) ;
2011-04-13 18:37:12 +00:00
2020-10-05 17:36:29 +00:00
// save auto mapper of each tile layer (not physics layer)
2020-10-05 17:59:48 +00:00
if ( ! Item . m_Flags )
{
2020-10-05 17:36:29 +00:00
CMapItemAutoMapperConfig ItemAutomapper ;
ItemAutomapper . m_Version = CMapItemAutoMapperConfig : : CURRENT_VERSION ;
ItemAutomapper . m_GroupId = GroupCount ;
ItemAutomapper . m_LayerId = GItem . m_NumLayers ;
2022-05-24 09:24:33 +00:00
ItemAutomapper . m_AutomapperConfig = pLayerTiles - > m_AutoMapperConfig ;
ItemAutomapper . m_AutomapperSeed = pLayerTiles - > m_Seed ;
2020-10-05 17:36:29 +00:00
ItemAutomapper . m_Flags = 0 ;
2022-05-24 09:24:33 +00:00
if ( pLayerTiles - > m_AutoAutoMap )
2020-10-05 17:36:29 +00:00
ItemAutomapper . m_Flags | = CMapItemAutoMapperConfig : : FLAG_AUTOMATIC ;
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_AUTOMAPPER_CONFIG , AutomapperCount , sizeof ( ItemAutomapper ) , & ItemAutomapper ) ;
2020-10-05 17:36:29 +00:00
AutomapperCount + + ;
}
2018-10-08 20:44:49 +00:00
2010-05-29 07:25:38 +00:00
GItem . m_NumLayers + + ;
LayerCount + + ;
2008-01-17 23:09:49 +00:00
}
2022-05-24 09:24:33 +00:00
else if ( pLayer - > m_Type = = LAYERTYPE_QUADS )
2008-01-17 23:09:49 +00:00
{
2010-08-17 22:06:00 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " editor " , " saving quads layer " ) ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerQuads > pLayerQuads = std : : static_pointer_cast < CLayerQuads > ( pLayer ) ;
2022-06-11 19:38:18 +00:00
if ( ! pLayerQuads - > m_vQuads . empty ( ) )
2008-01-17 23:09:49 +00:00
{
2010-05-29 07:25:38 +00:00
CMapItemLayerQuads Item ;
2011-07-12 01:14:46 +00:00
Item . m_Version = 2 ;
2020-10-13 07:53:33 +00:00
Item . m_Layer . m_Version = 0 ; // was previously uninitialized, do not rely on it being 0
2022-05-24 09:24:33 +00:00
Item . m_Layer . m_Flags = pLayerQuads - > m_Flags ;
Item . m_Layer . m_Type = pLayerQuads - > m_Type ;
Item . m_Image = pLayerQuads - > m_Image ;
2011-04-13 18:37:12 +00:00
2008-01-17 23:09:49 +00:00
// add the data
2022-06-11 19:38:18 +00:00
Item . m_NumQuads = pLayerQuads - > m_vQuads . size ( ) ;
2023-07-16 16:26:20 +00:00
Item . m_Data = Writer . AddDataSwapped ( pLayerQuads - > m_vQuads . size ( ) * sizeof ( CQuad ) , pLayerQuads - > m_vQuads . data ( ) ) ;
2011-07-12 01:14:46 +00:00
// save layer name
2022-05-24 09:24:33 +00:00
StrToInts ( Item . m_aName , sizeof ( Item . m_aName ) / sizeof ( int ) , pLayerQuads - > m_aName ) ;
2011-07-12 01:14:46 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_LAYER , LayerCount , sizeof ( Item ) , & Item ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
GItem . m_NumLayers + + ;
LayerCount + + ;
2008-01-17 23:09:49 +00:00
}
}
2022-05-24 09:24:33 +00:00
else if ( pLayer - > m_Type = = LAYERTYPE_SOUNDS )
2014-10-09 09:28:02 +00:00
{
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " editor " , " saving sounds layer " ) ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerSounds > pLayerSounds = std : : static_pointer_cast < CLayerSounds > ( pLayer ) ;
2022-06-11 19:38:18 +00:00
if ( ! pLayerSounds - > m_vSources . empty ( ) )
2014-10-09 09:28:02 +00:00
{
CMapItemLayerSounds Item ;
Item . m_Version = CMapItemLayerSounds : : CURRENT_VERSION ;
2020-10-13 07:53:33 +00:00
Item . m_Layer . m_Version = 0 ; // was previously uninitialized, do not rely on it being 0
2022-05-24 09:24:33 +00:00
Item . m_Layer . m_Flags = pLayerSounds - > m_Flags ;
Item . m_Layer . m_Type = pLayerSounds - > m_Type ;
Item . m_Sound = pLayerSounds - > m_Sound ;
2014-10-09 09:28:02 +00:00
2014-10-09 10:44:03 +00:00
// add the data
2022-06-11 19:38:18 +00:00
Item . m_NumSources = pLayerSounds - > m_vSources . size ( ) ;
2023-07-16 16:26:20 +00:00
Item . m_Data = Writer . AddDataSwapped ( pLayerSounds - > m_vSources . size ( ) * sizeof ( CSoundSource ) , pLayerSounds - > m_vSources . data ( ) ) ;
2014-10-09 09:28:02 +00:00
// save layer name
2022-05-24 09:24:33 +00:00
StrToInts ( Item . m_aName , sizeof ( Item . m_aName ) / sizeof ( int ) , pLayerSounds - > m_aName ) ;
2014-10-09 09:28:02 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_LAYER , LayerCount , sizeof ( Item ) , & Item ) ;
2014-10-09 09:28:02 +00:00
GItem . m_NumLayers + + ;
LayerCount + + ;
}
}
2008-01-17 23:09:49 +00:00
}
2011-04-13 18:37:12 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_GROUP , GroupCount , sizeof ( GItem ) , & GItem ) ;
Writer . AddItem ( MAPITEMTYPE_GROUP_EX , GroupCount , sizeof ( GItemEx ) , & GItemEx ) ;
2022-08-10 01:51:03 +00:00
GroupCount + + ;
2008-01-17 23:09:49 +00:00
}
2011-04-13 18:37:12 +00:00
2008-01-17 23:09:49 +00:00
// save envelopes
2023-04-24 21:21:44 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " editor " , " saving envelopes " ) ;
2010-05-29 07:25:38 +00:00
int PointCount = 0 ;
2022-06-11 19:38:18 +00:00
for ( size_t e = 0 ; e < m_vpEnvelopes . size ( ) ; e + + )
2008-01-17 23:09:49 +00:00
{
2010-05-29 07:25:38 +00:00
CMapItemEnvelope Item ;
2011-12-04 13:34:27 +00:00
Item . m_Version = CMapItemEnvelope : : CURRENT_VERSION ;
2023-04-24 21:21:44 +00:00
Item . m_Channels = m_vpEnvelopes [ e ] - > GetChannels ( ) ;
2010-05-29 07:25:38 +00:00
Item . m_StartPoint = PointCount ;
2022-06-11 19:38:18 +00:00
Item . m_NumPoints = m_vpEnvelopes [ e ] - > m_vPoints . size ( ) ;
Item . m_Synchronized = m_vpEnvelopes [ e ] - > m_Synchronized ;
StrToInts ( Item . m_aName , sizeof ( Item . m_aName ) / sizeof ( int ) , m_vpEnvelopes [ e ] - > m_aName ) ;
2011-04-13 18:37:12 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_ENVELOPE , e , sizeof ( Item ) , & Item ) ;
2010-05-29 07:25:38 +00:00
PointCount + = Item . m_NumPoints ;
2008-01-17 23:09:49 +00:00
}
2011-04-13 18:37:12 +00:00
2020-12-08 11:29:10 +00:00
// save points
2023-04-24 21:21:44 +00:00
m_pEditor - > Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_ADDINFO , " editor " , " saving envelope points " ) ;
2023-08-28 14:19:41 +00:00
bool BezierUsed = false ;
2023-04-24 21:21:44 +00:00
for ( const auto & pEnvelope : m_vpEnvelopes )
{
for ( const auto & Point : pEnvelope - > m_vPoints )
{
if ( Point . m_Curvetype = = CURVETYPE_BEZIER )
{
BezierUsed = true ;
break ;
}
}
if ( BezierUsed )
break ;
}
CEnvPoint * pPoints = ( CEnvPoint * ) calloc ( maximum ( PointCount , 1 ) , sizeof ( CEnvPoint ) ) ;
CEnvPointBezier * pPointsBezier = nullptr ;
if ( BezierUsed )
pPointsBezier = ( CEnvPointBezier * ) calloc ( maximum ( PointCount , 1 ) , sizeof ( CEnvPointBezier ) ) ;
2020-12-08 11:29:10 +00:00
PointCount = 0 ;
2020-10-12 14:07:29 +00:00
2022-06-11 19:38:18 +00:00
for ( const auto & pEnvelope : m_vpEnvelopes )
2020-12-08 11:29:10 +00:00
{
2023-04-24 21:21:44 +00:00
const CEnvPoint_runtime * pPrevPoint = nullptr ;
for ( const auto & Point : pEnvelope - > m_vPoints )
{
mem_copy ( & pPoints [ PointCount ] , & Point , sizeof ( CEnvPoint ) ) ;
if ( pPointsBezier ! = nullptr )
{
if ( Point . m_Curvetype = = CURVETYPE_BEZIER )
{
mem_copy ( & pPointsBezier [ PointCount ] . m_aOutTangentDeltaX , & Point . m_Bezier . m_aOutTangentDeltaX , sizeof ( Point . m_Bezier . m_aOutTangentDeltaX ) ) ;
mem_copy ( & pPointsBezier [ PointCount ] . m_aOutTangentDeltaY , & Point . m_Bezier . m_aOutTangentDeltaY , sizeof ( Point . m_Bezier . m_aOutTangentDeltaY ) ) ;
}
if ( pPrevPoint ! = nullptr & & pPrevPoint - > m_Curvetype = = CURVETYPE_BEZIER )
{
mem_copy ( & pPointsBezier [ PointCount ] . m_aInTangentDeltaX , & Point . m_Bezier . m_aInTangentDeltaX , sizeof ( Point . m_Bezier . m_aInTangentDeltaX ) ) ;
mem_copy ( & pPointsBezier [ PointCount ] . m_aInTangentDeltaY , & Point . m_Bezier . m_aInTangentDeltaY , sizeof ( Point . m_Bezier . m_aInTangentDeltaY ) ) ;
}
}
PointCount + + ;
pPrevPoint = & Point ;
}
2020-10-12 14:07:29 +00:00
}
2011-04-13 18:37:12 +00:00
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_ENVPOINTS , 0 , sizeof ( CEnvPoint ) * PointCount , pPoints ) ;
2020-12-08 11:29:10 +00:00
free ( pPoints ) ;
2023-04-24 21:21:44 +00:00
if ( pPointsBezier ! = nullptr )
{
2023-07-16 16:26:20 +00:00
Writer . AddItem ( MAPITEMTYPE_ENVPOINTS_BEZIER , 0 , sizeof ( CEnvPointBezier ) * PointCount , pPointsBezier ) ;
2023-04-24 21:21:44 +00:00
free ( pPointsBezier ) ;
}
2008-01-17 23:09:49 +00:00
// finish the data file
2023-07-16 17:51:11 +00:00
std : : shared_ptr < CDataFileWriterFinishJob > pWriterFinishJob = std : : make_shared < CDataFileWriterFinishJob > ( pFileName , aFileNameTmp , std : : move ( Writer ) ) ;
2023-06-26 18:48:16 +00:00
m_pEditor - > Engine ( ) - > AddJob ( pWriterFinishJob ) ;
2023-06-28 20:14:51 +00:00
m_pEditor - > m_WriterFinishJobs . push_back ( pWriterFinishJob ) ;
2011-04-13 18:37:12 +00:00
2022-11-03 19:17:06 +00:00
return true ;
2008-01-17 23:09:49 +00:00
}
2023-08-26 20:13:13 +00:00
bool CEditor : : HandleMapDrop ( const char * pFileName , int StorageType )
2023-08-26 16:14:13 +00:00
{
2023-08-26 20:13:13 +00:00
return m_Map . HandleMapDrop ( pFileName , IStorage : : TYPE_ALL_OR_ABSOLUTE ) ;
2023-08-26 16:14:13 +00:00
}
2023-08-26 20:13:13 +00:00
bool CEditorMap : : HandleMapDrop ( const char * pFileName , int StorageType )
2023-08-26 17:44:53 +00:00
{
2023-08-26 16:14:13 +00:00
if ( m_pEditor - > HasUnsavedData ( ) )
{
str_copy ( m_pEditor - > m_aFileNamePending , pFileName ) ;
m_pEditor - > m_PopupEventType = CEditor : : POPEVENT_LOADDROP ;
m_pEditor - > m_PopupEventActivated = true ;
2023-08-26 20:13:13 +00:00
return true ;
2023-08-26 16:14:13 +00:00
}
else
{
2023-08-26 20:13:13 +00:00
return m_pEditor - > Load ( pFileName , IStorage : : TYPE_ALL_OR_ABSOLUTE ) ;
2023-08-26 16:14:13 +00:00
}
}
2022-11-03 19:17:06 +00:00
bool CEditor : : Load ( const char * pFileName , int StorageType )
2008-03-05 19:38:47 +00:00
{
2023-07-10 20:36:12 +00:00
const auto & & ErrorHandler = [ this ] ( const char * pErrorMessage ) {
ShowFileDialogError ( " %s " , pErrorMessage ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " editor/load " , pErrorMessage ) ;
} ;
2010-05-29 07:25:38 +00:00
Reset ( ) ;
2023-07-10 20:36:12 +00:00
bool Result = m_Map . Load ( pFileName , StorageType , std : : move ( ErrorHandler ) ) ;
2022-11-03 19:17:06 +00:00
if ( Result )
2016-08-23 01:08:36 +00:00
{
2023-06-13 15:44:30 +00:00
str_copy ( m_aFileName , pFileName ) ;
2016-08-23 01:08:36 +00:00
SortImages ( ) ;
2020-09-21 17:36:26 +00:00
SelectGameLayer ( ) ;
2023-08-14 14:52:17 +00:00
MapView ( ) - > OnMapLoad ( ) ;
2016-08-23 01:08:36 +00:00
}
else
{
m_aFileName [ 0 ] = 0 ;
Reset ( ) ;
}
2022-11-03 19:17:06 +00:00
return Result ;
2008-03-05 19:38:47 +00:00
}
2023-07-10 20:36:12 +00:00
bool CEditorMap : : Load ( const char * pFileName , int StorageType , const std : : function < void ( const char * pErrorMessage ) > & ErrorHandler )
2008-01-17 23:09:49 +00:00
{
2010-05-29 07:25:38 +00:00
CDataFileReader DataFile ;
2023-06-24 09:00:42 +00:00
if ( ! DataFile . Open ( m_pEditor - > Storage ( ) , pFileName , StorageType ) )
2022-11-03 19:17:06 +00:00
return false ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
Clean ( ) ;
2008-01-17 23:09:49 +00:00
// check version
2022-03-20 11:57:50 +00:00
CMapItemVersion * pItemVersion = ( CMapItemVersion * ) DataFile . FindItem ( MAPITEMTYPE_VERSION , 0 ) ;
if ( ! pItemVersion )
2008-01-17 23:09:49 +00:00
{
2022-11-03 19:17:06 +00:00
return false ;
2008-01-17 23:09:49 +00:00
}
2013-06-01 13:26:22 +00:00
else if ( pItemVersion - > m_Version = = CMapItemVersion : : CURRENT_VERSION )
2008-01-17 23:09:49 +00:00
{
2011-07-12 21:31:39 +00:00
// load map info
{
2011-07-13 20:38:32 +00:00
int Start , Num ;
DataFile . GetType ( MAPITEMTYPE_INFO , & Start , & Num ) ;
for ( int i = Start ; i < Start + Num ; i + + )
2011-07-12 21:31:39 +00:00
{
2017-08-28 16:06:19 +00:00
int ItemSize = DataFile . GetItemSize ( Start ) ;
2011-07-13 20:38:32 +00:00
int ItemID ;
2022-06-13 16:28:13 +00:00
CMapItemInfoSettings * pItem = ( CMapItemInfoSettings * ) DataFile . GetItem ( i , nullptr , & ItemID ) ;
2011-07-13 20:38:32 +00:00
if ( ! pItem | | ItemID ! = 0 )
continue ;
2011-07-12 21:31:39 +00:00
if ( pItem - > m_Author > - 1 )
2023-06-13 15:44:30 +00:00
str_copy ( m_MapInfo . m_aAuthor , ( char * ) DataFile . GetData ( pItem - > m_Author ) ) ;
2011-07-12 21:31:39 +00:00
if ( pItem - > m_MapVersion > - 1 )
2023-06-13 15:44:30 +00:00
str_copy ( m_MapInfo . m_aVersion , ( char * ) DataFile . GetData ( pItem - > m_MapVersion ) ) ;
2011-07-12 21:31:39 +00:00
if ( pItem - > m_Credits > - 1 )
2023-06-13 15:44:30 +00:00
str_copy ( m_MapInfo . m_aCredits , ( char * ) DataFile . GetData ( pItem - > m_Credits ) ) ;
2011-07-12 21:31:39 +00:00
if ( pItem - > m_License > - 1 )
2023-06-13 15:44:30 +00:00
str_copy ( m_MapInfo . m_aLicense , ( char * ) DataFile . GetData ( pItem - > m_License ) ) ;
2011-07-13 20:38:32 +00:00
if ( pItem - > m_Version ! = 1 | | ItemSize < ( int ) sizeof ( CMapItemInfoSettings ) )
break ;
if ( ! ( pItem - > m_Settings > - 1 ) )
break ;
2017-08-30 06:36:17 +00:00
const unsigned Size = DataFile . GetDataSize ( pItem - > m_Settings ) ;
2011-07-13 20:38:32 +00:00
char * pSettings = ( char * ) DataFile . GetData ( pItem - > m_Settings ) ;
char * pNext = pSettings ;
while ( pNext < pSettings + Size )
{
int StrSize = str_length ( pNext ) + 1 ;
2023-07-22 14:30:10 +00:00
m_vSettings . emplace_back ( pNext ) ;
2011-07-13 20:38:32 +00:00
pNext + = StrSize ;
}
2011-07-12 21:31:39 +00:00
}
}
2008-01-17 23:09:49 +00:00
// load images
{
2010-05-29 07:25:38 +00:00
int Start , Num ;
2020-09-26 19:41:58 +00:00
DataFile . GetType ( MAPITEMTYPE_IMAGE , & Start , & Num ) ;
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < Num ; i + + )
2008-01-17 23:09:49 +00:00
{
2023-04-27 15:13:35 +00:00
CMapItemImage_v2 * pItem = ( CMapItemImage_v2 * ) DataFile . GetItem ( Start + i ) ;
2010-05-29 07:25:38 +00:00
char * pName = ( char * ) DataFile . GetData ( pItem - > m_ImageName ) ;
2008-01-19 14:23:53 +00:00
2011-04-13 18:37:12 +00:00
// copy base info
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CEditorImage > pImg = std : : make_shared < CEditorImage > ( m_pEditor ) ;
2010-05-29 07:25:38 +00:00
pImg - > m_External = pItem - > m_External ;
2008-01-19 14:23:53 +00:00
2023-04-27 15:13:35 +00:00
const int Format = pItem - > m_Version < CMapItemImage_v2 : : CURRENT_VERSION ? CImageInfo : : FORMAT_RGBA : pItem - > m_Format ;
if ( pImg - > m_External | | ( Format ! = CImageInfo : : FORMAT_RGB & & Format ! = CImageInfo : : FORMAT_RGBA ) )
2008-01-19 14:23:53 +00:00
{
2023-06-25 08:34:41 +00:00
char aBuf [ IO_MAX_PATH_LENGTH ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " mapres/%s.png " , pName ) ;
2011-04-13 18:37:12 +00:00
2008-01-19 14:23:53 +00:00
// load external
2010-05-29 07:25:38 +00:00
CEditorImage ImgInfo ( m_pEditor ) ;
2010-10-06 21:07:35 +00:00
if ( m_pEditor - > Graphics ( ) - > LoadPNG ( & ImgInfo , aBuf , IStorage : : TYPE_ALL ) )
2008-01-19 14:23:53 +00:00
{
2010-05-29 07:25:38 +00:00
* pImg = ImgInfo ;
2020-09-21 03:57:54 +00:00
int TextureLoadFlag = m_pEditor - > Graphics ( ) - > HasTextureArrays ( ) ? IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics : : TEXLOAD_TO_3D_TEXTURE ;
if ( ImgInfo . m_Width % 16 ! = 0 | | ImgInfo . m_Height % 16 ! = 0 )
TextureLoadFlag = 0 ;
pImg - > m_Texture = m_pEditor - > Graphics ( ) - > LoadTextureRaw ( ImgInfo . m_Width , ImgInfo . m_Height , ImgInfo . m_Format , ImgInfo . m_pData , CImageInfo : : FORMAT_AUTO , TextureLoadFlag , aBuf ) ;
2022-06-13 16:28:13 +00:00
ImgInfo . m_pData = nullptr ;
2010-05-29 07:25:38 +00:00
pImg - > m_External = 1 ;
2008-01-19 14:23:53 +00:00
}
}
else
{
2010-05-29 07:25:38 +00:00
pImg - > m_Width = pItem - > m_Width ;
pImg - > m_Height = pItem - > m_Height ;
2023-04-27 15:13:35 +00:00
pImg - > m_Format = Format ;
2011-04-13 18:37:12 +00:00
2008-01-19 14:23:53 +00:00
// copy image data
2010-05-29 07:25:38 +00:00
void * pData = DataFile . GetData ( pItem - > m_ImageData ) ;
2023-02-19 12:45:48 +00:00
const size_t DataSize = ( size_t ) pImg - > m_Width * pImg - > m_Height * 4 ;
pImg - > m_pData = malloc ( DataSize ) ;
mem_copy ( pImg - > m_pData , pData , DataSize ) ;
2020-09-21 03:57:54 +00:00
int TextureLoadFlag = m_pEditor - > Graphics ( ) - > HasTextureArrays ( ) ? IGraphics : : TEXLOAD_TO_2D_ARRAY_TEXTURE : IGraphics : : TEXLOAD_TO_3D_TEXTURE ;
if ( pImg - > m_Width % 16 ! = 0 | | pImg - > m_Height % 16 ! = 0 )
TextureLoadFlag = 0 ;
pImg - > m_Texture = m_pEditor - > Graphics ( ) - > LoadTextureRaw ( pImg - > m_Width , pImg - > m_Height , pImg - > m_Format , pImg - > m_pData , CImageInfo : : FORMAT_AUTO , TextureLoadFlag ) ;
2008-01-19 14:23:53 +00:00
}
// copy image name
2010-05-29 07:25:38 +00:00
if ( pName )
2023-06-13 15:44:30 +00:00
str_copy ( pImg - > m_aName , pName ) ;
2008-01-19 14:23:53 +00:00
2011-07-08 23:09:06 +00:00
// load auto mapper file
pImg - > m_AutoMapper . Load ( pImg - > m_aName ) ;
2022-06-11 19:38:18 +00:00
m_vpImages . push_back ( pImg ) ;
2011-04-13 18:37:12 +00:00
2008-01-17 23:09:49 +00:00
// unload image
2010-05-29 07:25:38 +00:00
DataFile . UnloadData ( pItem - > m_ImageData ) ;
DataFile . UnloadData ( pItem - > m_ImageName ) ;
2008-01-17 23:09:49 +00:00
}
}
2011-04-13 18:37:12 +00:00
2014-10-11 11:38:45 +00:00
// load sounds
{
int Start , Num ;
2020-09-26 19:41:58 +00:00
DataFile . GetType ( MAPITEMTYPE_SOUND , & Start , & Num ) ;
2014-10-11 11:38:45 +00:00
for ( int i = 0 ; i < Num ; i + + )
{
2023-02-20 22:38:54 +00:00
CMapItemSound * pItem = ( CMapItemSound * ) DataFile . GetItem ( Start + i ) ;
2014-10-11 11:38:45 +00:00
char * pName = ( char * ) DataFile . GetData ( pItem - > m_SoundName ) ;
// copy base info
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CEditorSound > pSound = std : : make_shared < CEditorSound > ( m_pEditor ) ;
2014-10-11 11:38:45 +00:00
if ( pItem - > m_External )
{
2023-06-25 08:34:41 +00:00
char aBuf [ IO_MAX_PATH_LENGTH ] ;
2020-09-26 19:41:58 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " mapres/%s.opus " , pName ) ;
2014-10-11 11:38:45 +00:00
// load external
2023-06-24 09:00:42 +00:00
if ( m_pEditor - > Storage ( ) - > ReadFile ( pName , IStorage : : TYPE_ALL , & pSound - > m_pData , & pSound - > m_DataSize ) )
2014-10-11 12:50:16 +00:00
{
2022-06-14 19:13:25 +00:00
pSound - > m_SoundID = m_pEditor - > Sound ( ) - > LoadOpusFromMem ( pSound - > m_pData , pSound - > m_DataSize , true ) ;
2014-10-11 12:50:16 +00:00
}
2014-10-11 11:38:45 +00:00
}
else
{
2014-10-11 12:50:16 +00:00
pSound - > m_DataSize = pItem - > m_SoundDataSize ;
2014-10-11 11:38:45 +00:00
2014-10-11 12:50:16 +00:00
// copy sample data
void * pData = DataFile . GetData ( pItem - > m_SoundData ) ;
2018-04-09 09:56:39 +00:00
pSound - > m_pData = malloc ( pSound - > m_DataSize ) ;
2014-10-11 12:50:16 +00:00
mem_copy ( pSound - > m_pData , pData , pSound - > m_DataSize ) ;
2014-10-27 15:23:53 +00:00
pSound - > m_SoundID = m_pEditor - > Sound ( ) - > LoadOpusFromMem ( pSound - > m_pData , pSound - > m_DataSize , true ) ;
2014-10-11 11:38:45 +00:00
}
// copy image name
if ( pName )
2023-06-13 15:44:30 +00:00
str_copy ( pSound - > m_aName , pName ) ;
2014-10-11 11:38:45 +00:00
2022-06-11 19:38:18 +00:00
m_vpSounds . push_back ( pSound ) ;
2014-10-11 11:38:45 +00:00
// unload image
DataFile . UnloadData ( pItem - > m_SoundData ) ;
DataFile . UnloadData ( pItem - > m_SoundName ) ;
}
}
2008-01-17 23:09:49 +00:00
// load groups
{
2010-05-29 07:25:38 +00:00
int LayersStart , LayersNum ;
DataFile . GetType ( MAPITEMTYPE_LAYER , & LayersStart , & LayersNum ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
int Start , Num ;
DataFile . GetType ( MAPITEMTYPE_GROUP , & Start , & Num ) ;
2022-08-10 01:51:03 +00:00
int StartEx , NumEx ;
DataFile . GetType ( MAPITEMTYPE_GROUP_EX , & StartEx , & NumEx ) ;
2010-05-29 07:25:38 +00:00
for ( int g = 0 ; g < Num ; g + + )
2008-01-17 23:09:49 +00:00
{
2023-02-20 22:38:54 +00:00
CMapItemGroup * pGItem = ( CMapItemGroup * ) DataFile . GetItem ( Start + g ) ;
2022-08-10 01:51:03 +00:00
CMapItemGroupEx * pGItemEx = nullptr ;
if ( NumEx )
2023-02-20 22:38:54 +00:00
pGItemEx = ( CMapItemGroupEx * ) DataFile . GetItem ( StartEx + g ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( pGItem - > m_Version < 1 | | pGItem - > m_Version > CMapItemGroup : : CURRENT_VERSION )
2008-03-29 11:44:03 +00:00
continue ;
2011-04-13 18:37:12 +00:00
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerGroup > pGroup = NewGroup ( ) ;
2010-05-29 07:25:38 +00:00
pGroup - > m_ParallaxX = pGItem - > m_ParallaxX ;
pGroup - > m_ParallaxY = pGItem - > m_ParallaxY ;
pGroup - > m_OffsetX = pGItem - > m_OffsetX ;
pGroup - > m_OffsetY = pGItem - > m_OffsetY ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( pGItem - > m_Version > = 2 )
2008-03-29 11:44:03 +00:00
{
2010-05-29 07:25:38 +00:00
pGroup - > m_UseClipping = pGItem - > m_UseClipping ;
pGroup - > m_ClipX = pGItem - > m_ClipX ;
pGroup - > m_ClipY = pGItem - > m_ClipY ;
pGroup - > m_ClipW = pGItem - > m_ClipW ;
pGroup - > m_ClipH = pGItem - > m_ClipH ;
2008-03-29 11:44:03 +00:00
}
2011-04-13 18:37:12 +00:00
2011-07-12 01:14:46 +00:00
// load group name
if ( pGItem - > m_Version > = 3 )
2020-09-26 19:41:58 +00:00
IntsToStr ( pGItem - > m_aName , sizeof ( pGroup - > m_aName ) / sizeof ( int ) , pGroup - > m_aName ) ;
2011-07-12 01:14:46 +00:00
2022-08-10 01:51:03 +00:00
pGroup - > m_ParallaxZoom = GetParallaxZoom ( pGItem , pGItemEx ) ;
pGroup - > m_CustomParallaxZoom = pGroup - > m_ParallaxZoom ! = GetParallaxZoomDefault ( pGroup - > m_ParallaxX , pGroup - > m_ParallaxY ) ;
2022-08-04 23:16:44 +00:00
2010-05-29 07:25:38 +00:00
for ( int l = 0 ; l < pGItem - > m_NumLayers ; l + + )
2008-01-17 23:09:49 +00:00
{
2023-02-20 22:38:54 +00:00
CMapItemLayer * pLayerItem = ( CMapItemLayer * ) DataFile . GetItem ( LayersStart + pGItem - > m_StartLayer + l ) ;
2010-05-29 07:25:38 +00:00
if ( ! pLayerItem )
2008-01-17 23:09:49 +00:00
continue ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( pLayerItem - > m_Type = = LAYERTYPE_TILES )
2008-01-17 23:09:49 +00:00
{
2010-05-29 07:25:38 +00:00
CMapItemLayerTilemap * pTilemapItem = ( CMapItemLayerTilemap * ) pLayerItem ;
2011-04-13 18:37:12 +00:00
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerTiles > pTiles ;
2020-09-26 19:41:58 +00:00
if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_GAME )
2008-01-17 23:09:49 +00:00
{
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerGame > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-05-29 07:25:38 +00:00
MakeGameLayer ( pTiles ) ;
MakeGameGroup ( pGroup ) ;
2008-01-17 23:09:49 +00:00
}
2020-09-26 19:41:58 +00:00
else if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_TELE )
2010-09-30 21:31:19 +00:00
{
2011-08-13 00:12:40 +00:00
if ( pTilemapItem - > m_Version < = 2 )
2023-07-28 11:16:18 +00:00
pTilemapItem - > m_Tele = * ( ( const int * ) ( pTilemapItem ) + 15 ) ;
2011-08-13 00:12:40 +00:00
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerTele > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-09-30 21:31:19 +00:00
MakeTeleLayer ( pTiles ) ;
}
2020-09-26 19:41:58 +00:00
else if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_SPEEDUP )
2010-09-30 21:31:19 +00:00
{
2011-08-13 00:12:40 +00:00
if ( pTilemapItem - > m_Version < = 2 )
2023-07-28 11:16:18 +00:00
pTilemapItem - > m_Speedup = * ( ( const int * ) ( pTilemapItem ) + 16 ) ;
2011-08-13 00:12:40 +00:00
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerSpeedup > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-09-30 21:31:19 +00:00
MakeSpeedupLayer ( pTiles ) ;
}
2020-09-26 19:41:58 +00:00
else if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_FRONT )
2010-09-30 21:31:19 +00:00
{
2011-08-13 00:12:40 +00:00
if ( pTilemapItem - > m_Version < = 2 )
2023-07-28 11:16:18 +00:00
pTilemapItem - > m_Front = * ( ( const int * ) ( pTilemapItem ) + 17 ) ;
2011-08-13 00:12:40 +00:00
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerFront > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-09-30 21:31:19 +00:00
MakeFrontLayer ( pTiles ) ;
}
2020-09-26 19:41:58 +00:00
else if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_SWITCH )
2010-09-30 21:31:19 +00:00
{
2011-08-13 00:12:40 +00:00
if ( pTilemapItem - > m_Version < = 2 )
2023-07-28 11:16:18 +00:00
pTilemapItem - > m_Switch = * ( ( const int * ) ( pTilemapItem ) + 18 ) ;
2011-08-13 00:12:40 +00:00
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerSwitch > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-09-30 21:31:19 +00:00
MakeSwitchLayer ( pTiles ) ;
}
2020-09-26 19:41:58 +00:00
else if ( pTilemapItem - > m_Flags & TILESLAYERFLAG_TUNE )
2014-03-12 22:47:11 +00:00
{
if ( pTilemapItem - > m_Version < = 2 )
2023-07-28 11:16:18 +00:00
pTilemapItem - > m_Tune = * ( ( const int * ) ( pTilemapItem ) + 19 ) ;
2014-03-12 22:47:11 +00:00
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerTune > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2014-03-12 22:47:11 +00:00
MakeTuneLayer ( pTiles ) ;
}
2008-01-17 23:09:49 +00:00
else
2010-05-29 07:25:38 +00:00
{
2023-07-28 11:16:18 +00:00
pTiles = std : : make_shared < CLayerTiles > ( pTilemapItem - > m_Width , pTilemapItem - > m_Height ) ;
2010-05-29 07:25:38 +00:00
pTiles - > m_pEditor = m_pEditor ;
2011-07-18 10:05:12 +00:00
pTiles - > m_Color = pTilemapItem - > m_Color ;
pTiles - > m_ColorEnv = pTilemapItem - > m_ColorEnv ;
pTiles - > m_ColorEnvOffset = pTilemapItem - > m_ColorEnvOffset ;
2010-05-29 07:25:38 +00:00
}
2008-03-21 17:39:09 +00:00
2023-07-28 11:16:18 +00:00
pTiles - > m_Flags = pLayerItem - > m_Flags ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pGroup - > AddLayer ( pTiles ) ;
pTiles - > m_Image = pTilemapItem - > m_Image ;
2020-09-26 19:41:58 +00:00
pTiles - > m_Game = pTilemapItem - > m_Flags & TILESLAYERFLAG_GAME ;
2011-04-13 18:37:12 +00:00
2011-07-12 01:14:46 +00:00
// load layer name
if ( pTilemapItem - > m_Version > = 3 )
2020-09-26 19:41:58 +00:00
IntsToStr ( pTilemapItem - > m_aName , sizeof ( pTiles - > m_aName ) / sizeof ( int ) , pTiles - > m_aName ) ;
2011-04-13 18:37:12 +00:00
2010-09-30 21:31:19 +00:00
if ( pTiles - > m_Tele )
{
void * pTeleData = DataFile . GetData ( pTilemapItem - > m_Tele ) ;
2017-08-30 06:36:17 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Tele ) ;
2020-10-05 17:03:14 +00:00
if ( Size > = ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CTeleTile ) )
2010-09-30 21:31:19 +00:00
{
2023-07-28 11:16:18 +00:00
CTeleTile * pLayerTeleTiles = std : : static_pointer_cast < CLayerTele > ( pTiles ) - > m_pTeleTile ;
2022-08-14 10:49:13 +00:00
mem_copy ( pLayerTeleTiles , pTeleData , ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CTeleTile ) ) ;
2014-01-10 23:46:32 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < pTiles - > m_Width * pTiles - > m_Height ; i + + )
2014-01-10 23:46:32 +00:00
{
2023-03-03 17:20:08 +00:00
if ( IsValidTeleTile ( pLayerTeleTiles [ i ] . m_Type ) )
pTiles - > m_pTiles [ i ] . m_Index = pLayerTeleTiles [ i ] . m_Type ;
else
pTiles - > m_pTiles [ i ] . m_Index = 0 ;
2014-01-10 23:46:32 +00:00
}
2010-09-30 21:31:19 +00:00
}
DataFile . UnloadData ( pTilemapItem - > m_Tele ) ;
}
else if ( pTiles - > m_Speedup )
{
void * pSpeedupData = DataFile . GetData ( pTilemapItem - > m_Speedup ) ;
2017-08-30 06:36:17 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Speedup ) ;
2011-04-09 06:41:31 +00:00
2020-10-05 17:03:14 +00:00
if ( Size > = ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CSpeedupTile ) )
2010-09-30 21:31:19 +00:00
{
2023-07-28 11:16:18 +00:00
CSpeedupTile * pLayerSpeedupTiles = std : : static_pointer_cast < CLayerSpeedup > ( pTiles ) - > m_pSpeedupTile ;
2022-08-14 10:49:13 +00:00
mem_copy ( pLayerSpeedupTiles , pSpeedupData , ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CSpeedupTile ) ) ;
2014-01-10 23:46:32 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < pTiles - > m_Width * pTiles - > m_Height ; i + + )
2014-01-10 23:46:32 +00:00
{
2023-03-03 17:20:08 +00:00
if ( IsValidSpeedupTile ( pLayerSpeedupTiles [ i ] . m_Type ) & & pLayerSpeedupTiles [ i ] . m_Force > 0 )
pTiles - > m_pTiles [ i ] . m_Index = pLayerSpeedupTiles [ i ] . m_Type ;
2014-01-10 23:46:32 +00:00
else
2016-07-09 19:46:47 +00:00
pTiles - > m_pTiles [ i ] . m_Index = 0 ;
2014-01-10 23:46:32 +00:00
}
2010-09-30 21:31:19 +00:00
}
2011-04-09 06:41:31 +00:00
2010-09-30 21:31:19 +00:00
DataFile . UnloadData ( pTilemapItem - > m_Speedup ) ;
}
else if ( pTiles - > m_Front )
{
void * pFrontData = DataFile . GetData ( pTilemapItem - > m_Front ) ;
2017-08-30 06:36:17 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Front ) ;
2022-08-14 14:02:15 +00:00
pTiles - > ExtractTiles ( pTilemapItem - > m_Version , ( CTile * ) pFrontData , Size ) ;
2010-09-30 21:31:19 +00:00
DataFile . UnloadData ( pTilemapItem - > m_Front ) ;
}
else if ( pTiles - > m_Switch )
{
void * pSwitchData = DataFile . GetData ( pTilemapItem - > m_Switch ) ;
2017-08-30 06:36:17 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Switch ) ;
2020-10-05 17:03:14 +00:00
if ( Size > = ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CSwitchTile ) )
2010-09-30 21:31:19 +00:00
{
2023-07-28 11:16:18 +00:00
CSwitchTile * pLayerSwitchTiles = std : : static_pointer_cast < CLayerSwitch > ( pTiles ) - > m_pSwitchTile ;
2022-08-14 10:49:13 +00:00
mem_copy ( pLayerSwitchTiles , pSwitchData , ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CSwitchTile ) ) ;
2014-01-10 23:46:32 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < pTiles - > m_Width * pTiles - > m_Height ; i + + )
2013-08-23 23:03:45 +00:00
{
2023-03-03 17:20:08 +00:00
if ( ( ( pLayerSwitchTiles [ i ] . m_Type > ( ENTITY_CRAZY_SHOTGUN + ENTITY_OFFSET ) & & pLayerSwitchTiles [ i ] . m_Type < ( ENTITY_DRAGGER_WEAK + ENTITY_OFFSET ) ) | | pLayerSwitchTiles [ i ] . m_Type = = ( ENTITY_LASER_O_FAST + 1 + ENTITY_OFFSET ) ) )
2014-01-10 23:46:32 +00:00
continue ;
2016-07-09 19:46:47 +00:00
else if ( pLayerSwitchTiles [ i ] . m_Type > = ( ENTITY_ARMOR_1 + ENTITY_OFFSET ) & & pLayerSwitchTiles [ i ] . m_Type < = ( ENTITY_DOOR + ENTITY_OFFSET ) )
2014-01-10 23:46:32 +00:00
{
2016-07-09 19:46:47 +00:00
pTiles - > m_pTiles [ i ] . m_Index = pLayerSwitchTiles [ i ] . m_Type ;
pTiles - > m_pTiles [ i ] . m_Flags = pLayerSwitchTiles [ i ] . m_Flags ;
continue ;
2014-02-09 22:31:29 +00:00
}
2016-07-09 19:46:47 +00:00
2023-03-03 17:20:08 +00:00
if ( IsValidSwitchTile ( pLayerSwitchTiles [ i ] . m_Type ) )
2015-03-10 21:57:40 +00:00
{
2023-03-03 17:20:08 +00:00
pTiles - > m_pTiles [ i ] . m_Index = pLayerSwitchTiles [ i ] . m_Type ;
pTiles - > m_pTiles [ i ] . m_Flags = pLayerSwitchTiles [ i ] . m_Flags ;
2015-03-10 21:57:40 +00:00
}
2011-07-25 20:16:20 +00:00
}
2010-09-30 21:31:19 +00:00
}
DataFile . UnloadData ( pTilemapItem - > m_Switch ) ;
}
2014-03-12 22:47:11 +00:00
else if ( pTiles - > m_Tune )
{
void * pTuneData = DataFile . GetData ( pTilemapItem - > m_Tune ) ;
2017-08-30 06:36:17 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Tune ) ;
2020-10-05 17:03:14 +00:00
if ( Size > = ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CTuneTile ) )
2014-03-12 22:47:11 +00:00
{
2023-07-28 11:16:18 +00:00
CTuneTile * pLayerTuneTiles = std : : static_pointer_cast < CLayerTune > ( pTiles ) - > m_pTuneTile ;
2022-08-14 10:49:13 +00:00
mem_copy ( pLayerTuneTiles , pTuneData , ( size_t ) pTiles - > m_Width * pTiles - > m_Height * sizeof ( CTuneTile ) ) ;
2014-03-12 22:47:11 +00:00
2020-09-26 19:41:58 +00:00
for ( int i = 0 ; i < pTiles - > m_Width * pTiles - > m_Height ; i + + )
2014-03-12 22:47:11 +00:00
{
2023-03-03 17:20:08 +00:00
if ( IsValidTuneTile ( pLayerTuneTiles [ i ] . m_Type ) )
pTiles - > m_pTiles [ i ] . m_Index = pLayerTuneTiles [ i ] . m_Type ;
2014-03-12 22:47:11 +00:00
else
2016-07-09 19:46:47 +00:00
pTiles - > m_pTiles [ i ] . m_Index = 0 ;
2014-03-12 22:47:11 +00:00
}
}
DataFile . UnloadData ( pTilemapItem - > m_Tune ) ;
}
2016-05-11 10:13:54 +00:00
else // regular tile layer or game layer
{
2022-08-14 10:38:08 +00:00
void * pData = DataFile . GetData ( pTilemapItem - > m_Data ) ;
2022-03-20 11:57:50 +00:00
unsigned int Size = DataFile . GetDataSize ( pTilemapItem - > m_Data ) ;
2022-08-14 14:02:15 +00:00
pTiles - > ExtractTiles ( pTilemapItem - > m_Version , ( CTile * ) pData , Size ) ;
2016-05-11 10:13:54 +00:00
2017-12-11 08:50:15 +00:00
if ( pTiles - > m_Game & & pTilemapItem - > m_Version = = MakeVersion ( 1 , * pTilemapItem ) )
{
for ( int i = 0 ; i < pTiles - > m_Width * pTiles - > m_Height ; i + + )
2016-05-11 10:13:54 +00:00
{
2017-12-11 08:50:15 +00:00
if ( pTiles - > m_pTiles [ i ] . m_Index )
pTiles - > m_pTiles [ i ] . m_Index + = ENTITY_OFFSET ;
2016-05-11 10:13:54 +00:00
}
}
2022-08-14 10:38:08 +00:00
DataFile . UnloadData ( pTilemapItem - > m_Data ) ;
2016-05-11 10:13:54 +00:00
}
2008-01-17 23:09:49 +00:00
}
2010-05-29 07:25:38 +00:00
else if ( pLayerItem - > m_Type = = LAYERTYPE_QUADS )
2008-01-17 23:09:49 +00:00
{
2023-07-28 11:16:18 +00:00
const CMapItemLayerQuads * pQuadsItem = ( CMapItemLayerQuads * ) pLayerItem ;
std : : shared_ptr < CLayerQuads > pQuads = std : : make_shared < CLayerQuads > ( ) ;
2010-05-29 07:25:38 +00:00
pQuads - > m_pEditor = m_pEditor ;
2023-07-28 11:16:18 +00:00
pQuads - > m_Flags = pLayerItem - > m_Flags ;
2010-05-29 07:25:38 +00:00
pQuads - > m_Image = pQuadsItem - > m_Image ;
2022-06-11 19:38:18 +00:00
if ( pQuads - > m_Image < - 1 | | pQuads - > m_Image > = ( int ) m_vpImages . size ( ) )
2010-05-29 07:25:38 +00:00
pQuads - > m_Image = - 1 ;
2011-07-12 01:14:46 +00:00
// load layer name
if ( pQuadsItem - > m_Version > = 2 )
2020-09-26 19:41:58 +00:00
IntsToStr ( pQuadsItem - > m_aName , sizeof ( pQuads - > m_aName ) / sizeof ( int ) , pQuads - > m_aName ) ;
2011-07-12 01:14:46 +00:00
2010-05-29 07:25:38 +00:00
void * pData = DataFile . GetDataSwapped ( pQuadsItem - > m_Data ) ;
pGroup - > AddLayer ( pQuads ) ;
2022-06-11 19:38:18 +00:00
pQuads - > m_vQuads . resize ( pQuadsItem - > m_NumQuads ) ;
2022-07-10 19:22:50 +00:00
mem_copy ( pQuads - > m_vQuads . data ( ) , pData , sizeof ( CQuad ) * pQuadsItem - > m_NumQuads ) ;
2010-05-29 07:25:38 +00:00
DataFile . UnloadData ( pQuadsItem - > m_Data ) ;
2008-01-17 23:09:49 +00:00
}
2014-10-09 09:28:02 +00:00
else if ( pLayerItem - > m_Type = = LAYERTYPE_SOUNDS )
{
2023-07-28 11:16:18 +00:00
const CMapItemLayerSounds * pSoundsItem = ( CMapItemLayerSounds * ) pLayerItem ;
2014-11-27 15:18:15 +00:00
if ( pSoundsItem - > m_Version < 1 | | pSoundsItem - > m_Version > CMapItemLayerSounds : : CURRENT_VERSION )
continue ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerSounds > pSounds = std : : make_shared < CLayerSounds > ( ) ;
2014-10-09 09:28:02 +00:00
pSounds - > m_pEditor = m_pEditor ;
2023-07-28 11:16:18 +00:00
pSounds - > m_Flags = pLayerItem - > m_Flags ;
2014-10-09 09:28:02 +00:00
pSounds - > m_Sound = pSoundsItem - > m_Sound ;
2014-10-11 18:05:48 +00:00
// validate m_Sound
2022-06-11 19:38:18 +00:00
if ( pSounds - > m_Sound < - 1 | | pSounds - > m_Sound > = ( int ) m_vpSounds . size ( ) )
2014-10-11 18:05:48 +00:00
pSounds - > m_Sound = - 1 ;
2014-10-09 09:28:02 +00:00
// load layer name
2022-10-30 12:52:20 +00:00
IntsToStr ( pSoundsItem - > m_aName , sizeof ( pSounds - > m_aName ) / sizeof ( int ) , pSounds - > m_aName ) ;
2014-10-09 09:28:02 +00:00
2014-10-09 10:44:03 +00:00
// load data
void * pData = DataFile . GetDataSwapped ( pSoundsItem - > m_Data ) ;
2014-10-09 09:28:02 +00:00
pGroup - > AddLayer ( pSounds ) ;
2022-06-11 19:38:18 +00:00
pSounds - > m_vSources . resize ( pSoundsItem - > m_NumSources ) ;
2022-07-10 19:22:50 +00:00
mem_copy ( pSounds - > m_vSources . data ( ) , pData , sizeof ( CSoundSource ) * pSoundsItem - > m_NumSources ) ;
2014-10-09 10:44:03 +00:00
DataFile . UnloadData ( pSoundsItem - > m_Data ) ;
2014-10-09 09:28:02 +00:00
}
2014-12-05 13:38:16 +00:00
else if ( pLayerItem - > m_Type = = LAYERTYPE_SOUNDS_DEPRECATED )
{
// compatibility with old sound layers
2023-07-28 11:16:18 +00:00
const CMapItemLayerSounds * pSoundsItem = ( CMapItemLayerSounds * ) pLayerItem ;
2014-12-05 13:38:16 +00:00
if ( pSoundsItem - > m_Version < 1 | | pSoundsItem - > m_Version > CMapItemLayerSounds : : CURRENT_VERSION )
continue ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerSounds > pSounds = std : : make_shared < CLayerSounds > ( ) ;
2014-12-05 13:38:16 +00:00
pSounds - > m_pEditor = m_pEditor ;
2023-07-28 11:16:18 +00:00
pSounds - > m_Flags = pLayerItem - > m_Flags ;
2014-12-05 13:38:16 +00:00
pSounds - > m_Sound = pSoundsItem - > m_Sound ;
// validate m_Sound
2022-06-11 19:38:18 +00:00
if ( pSounds - > m_Sound < - 1 | | pSounds - > m_Sound > = ( int ) m_vpSounds . size ( ) )
2014-12-05 13:38:16 +00:00
pSounds - > m_Sound = - 1 ;
// load layer name
2022-10-30 12:52:20 +00:00
IntsToStr ( pSoundsItem - > m_aName , sizeof ( pSounds - > m_aName ) / sizeof ( int ) , pSounds - > m_aName ) ;
2014-12-05 13:38:16 +00:00
// load data
CSoundSource_DEPRECATED * pData = ( CSoundSource_DEPRECATED * ) DataFile . GetDataSwapped ( pSoundsItem - > m_Data ) ;
pGroup - > AddLayer ( pSounds ) ;
2022-06-11 19:38:18 +00:00
pSounds - > m_vSources . resize ( pSoundsItem - > m_NumSources ) ;
2014-12-05 13:38:16 +00:00
for ( int i = 0 ; i < pSoundsItem - > m_NumSources ; i + + )
{
CSoundSource_DEPRECATED * pOldSource = & pData [ i ] ;
2022-06-11 19:38:18 +00:00
CSoundSource & Source = pSounds - > m_vSources [ i ] ;
2014-12-05 13:38:16 +00:00
Source . m_Position = pOldSource - > m_Position ;
Source . m_Loop = pOldSource - > m_Loop ;
Source . m_Pan = true ;
Source . m_TimeDelay = pOldSource - > m_TimeDelay ;
Source . m_Falloff = 0 ;
Source . m_PosEnv = pOldSource - > m_PosEnv ;
Source . m_PosEnvOffset = pOldSource - > m_PosEnvOffset ;
Source . m_SoundEnv = pOldSource - > m_SoundEnv ;
Source . m_SoundEnvOffset = pOldSource - > m_SoundEnvOffset ;
Source . m_Shape . m_Type = CSoundShape : : SHAPE_CIRCLE ;
Source . m_Shape . m_Circle . m_Radius = pOldSource - > m_FalloffDistance ;
}
DataFile . UnloadData ( pSoundsItem - > m_Data ) ;
}
2008-01-17 23:09:49 +00:00
}
}
}
2011-04-13 18:37:12 +00:00
2008-01-17 23:09:49 +00:00
// load envelopes
{
2023-04-24 21:21:44 +00:00
const CMapBasedEnvelopePointAccess EnvelopePoints ( & DataFile ) ;
2011-04-13 18:37:12 +00:00
2023-04-24 21:21:44 +00:00
int EnvStart , EnvNum ;
DataFile . GetType ( MAPITEMTYPE_ENVELOPE , & EnvStart , & EnvNum ) ;
for ( int e = 0 ; e < EnvNum ; e + + )
2008-01-17 23:09:49 +00:00
{
2023-04-24 21:21:44 +00:00
CMapItemEnvelope * pItem = ( CMapItemEnvelope * ) DataFile . GetItem ( EnvStart + e ) ;
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CEnvelope > pEnv = std : : make_shared < CEnvelope > ( pItem - > m_Channels ) ;
2022-06-11 19:38:18 +00:00
pEnv - > m_vPoints . resize ( pItem - > m_NumPoints ) ;
2023-04-24 21:21:44 +00:00
for ( int p = 0 ; p < pItem - > m_NumPoints ; p + + )
{
const CEnvPoint * pPoint = EnvelopePoints . GetPoint ( pItem - > m_StartPoint + p ) ;
if ( pPoint ! = nullptr )
mem_copy ( & pEnv - > m_vPoints [ p ] , pPoint , sizeof ( CEnvPoint ) ) ;
const CEnvPointBezier * pPointBezier = EnvelopePoints . GetBezier ( pItem - > m_StartPoint + p ) ;
if ( pPointBezier ! = nullptr )
mem_copy ( & pEnv - > m_vPoints [ p ] . m_Bezier , pPointBezier , sizeof ( CEnvPointBezier ) ) ;
}
2020-09-26 19:41:58 +00:00
if ( pItem - > m_aName [ 0 ] ! = - 1 ) // compatibility with old maps
IntsToStr ( pItem - > m_aName , sizeof ( pItem - > m_aName ) / sizeof ( int ) , pEnv - > m_aName ) ;
2022-06-11 19:38:18 +00:00
m_vpEnvelopes . push_back ( pEnv ) ;
2023-04-24 21:21:44 +00:00
if ( pItem - > m_Version > = CMapItemEnvelope_v2 : : CURRENT_VERSION )
2011-12-04 13:34:27 +00:00
pEnv - > m_Synchronized = pItem - > m_Synchronized ;
2008-01-17 23:09:49 +00:00
}
}
2018-10-08 20:44:49 +00:00
{
2023-04-24 21:21:44 +00:00
int AutomapperConfigStart , AutomapperConfigNum ;
DataFile . GetType ( MAPITEMTYPE_AUTOMAPPER_CONFIG , & AutomapperConfigStart , & AutomapperConfigNum ) ;
for ( int i = 0 ; i < AutomapperConfigNum ; i + + )
2018-10-08 20:44:49 +00:00
{
2023-04-24 21:21:44 +00:00
CMapItemAutoMapperConfig * pItem = ( CMapItemAutoMapperConfig * ) DataFile . GetItem ( AutomapperConfigStart + i ) ;
2020-09-26 19:41:58 +00:00
if ( pItem - > m_Version = = CMapItemAutoMapperConfig : : CURRENT_VERSION )
{
2022-06-11 19:38:18 +00:00
if ( pItem - > m_GroupId > = 0 & & ( size_t ) pItem - > m_GroupId < m_vpGroups . size ( ) & &
pItem - > m_LayerId > = 0 & & ( size_t ) pItem - > m_LayerId < m_vpGroups [ pItem - > m_GroupId ] - > m_vpLayers . size ( ) )
2020-09-26 19:41:58 +00:00
{
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayer > pLayer = m_vpGroups [ pItem - > m_GroupId ] - > m_vpLayers [ pItem - > m_LayerId ] ;
2020-10-05 18:09:19 +00:00
if ( pLayer - > m_Type = = LAYERTYPE_TILES )
2020-10-05 17:59:48 +00:00
{
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerTiles > pTiles = std : : static_pointer_cast < CLayerTiles > ( m_vpGroups [ pItem - > m_GroupId ] - > m_vpLayers [ pItem - > m_LayerId ] ) ;
2020-10-05 17:36:29 +00:00
// only load auto mappers for tile layers (not physics layers)
2022-03-20 11:57:50 +00:00
if ( ! ( pTiles - > m_Game | | pTiles - > m_Tele | | pTiles - > m_Speedup | |
pTiles - > m_Front | | pTiles - > m_Switch | | pTiles - > m_Tune ) )
2020-10-05 17:59:48 +00:00
{
2022-03-20 11:57:50 +00:00
pTiles - > m_AutoMapperConfig = pItem - > m_AutomapperConfig ;
pTiles - > m_Seed = pItem - > m_AutomapperSeed ;
pTiles - > m_AutoAutoMap = ! ! ( pItem - > m_Flags & CMapItemAutoMapperConfig : : FLAG_AUTOMATIC ) ;
2020-10-05 17:36:29 +00:00
}
}
2018-10-08 20:44:49 +00:00
}
}
}
}
2008-01-17 23:09:49 +00:00
}
2013-05-26 08:58:03 +00:00
else
2022-11-03 19:17:06 +00:00
return false ;
2011-04-13 18:37:12 +00:00
2023-07-10 20:36:12 +00:00
PerformSanityChecks ( ErrorHandler ) ;
2020-05-16 06:17:48 +00:00
m_Modified = false ;
Autosave copy of current editor map periodically to `auto` folder
A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below).
Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder.
Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit).
Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave.
This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map.
When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor.
When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map.
When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case.
Closes #6693.
2023-06-23 15:39:05 +00:00
m_ModifiedAuto = false ;
m_LastModifiedTime = - 1.0f ;
m_LastSaveTime = m_pEditor - > Client ( ) - > GlobalTime ( ) ;
2022-11-03 19:17:06 +00:00
return true ;
2008-01-17 23:09:49 +00:00
}
2008-03-05 19:38:47 +00:00
2023-07-10 20:36:12 +00:00
void CEditorMap : : PerformSanityChecks ( const std : : function < void ( const char * pErrorMessage ) > & ErrorHandler )
{
// Check if there are any images with a width or height that is not divisible by 16 which are
// used in tile layers. Reset the image for these layers, to prevent crashes with some drivers.
size_t ImageIndex = 0 ;
2023-07-28 11:16:18 +00:00
for ( const std : : shared_ptr < CEditorImage > & pImage : m_vpImages )
2023-07-10 20:36:12 +00:00
{
if ( pImage - > m_Width % 16 ! = 0 | | pImage - > m_Height % 16 ! = 0 )
{
size_t GroupIndex = 0 ;
2023-07-28 11:16:18 +00:00
for ( const std : : shared_ptr < CLayerGroup > & pGroup : m_vpGroups )
2023-07-10 20:36:12 +00:00
{
size_t LayerIndex = 0 ;
2023-07-28 11:16:18 +00:00
for ( const std : : shared_ptr < CLayer > & pLayer : pGroup - > m_vpLayers )
2023-07-10 20:36:12 +00:00
{
if ( pLayer - > m_Type = = LAYERTYPE_TILES )
{
2023-07-28 11:16:18 +00:00
std : : shared_ptr < CLayerTiles > pLayerTiles = std : : static_pointer_cast < CLayerTiles > ( pLayer ) ;
2023-07-10 20:36:12 +00:00
if ( pLayerTiles - > m_Image > = 0 & & ( size_t ) pLayerTiles - > m_Image = = ImageIndex )
{
pLayerTiles - > m_Image = - 1 ;
char aBuf [ IO_MAX_PATH_LENGTH + 128 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Error: The image '%s' (size %dx%d) has a width or height that is not divisible by 16 and therefore cannot be used for tile layers. The image of layer #% " PRIzu " '%s' in group #% " PRIzu " '%s' has been unset. " , pImage - > m_aName , pImage - > m_Width , pImage - > m_Height , LayerIndex , pLayer - > m_aName , GroupIndex , pGroup - > m_aName ) ;
ErrorHandler ( aBuf ) ;
}
}
+ + LayerIndex ;
}
+ + GroupIndex ;
}
}
+ + ImageIndex ;
}
}
2022-11-03 19:17:06 +00:00
bool CEditor : : Append ( const char * pFileName , int StorageType )
2008-03-05 19:38:47 +00:00
{
2010-05-29 07:25:38 +00:00
CEditorMap NewMap ;
NewMap . m_pEditor = this ;
2023-07-10 20:36:12 +00:00
const auto & & ErrorHandler = [ this ] ( const char * pErrorMessage ) {
ShowFileDialogError ( " %s " , pErrorMessage ) ;
Console ( ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " editor/append " , pErrorMessage ) ;
} ;
if ( ! NewMap . Load ( pFileName , StorageType , std : : move ( ErrorHandler ) ) )
2022-11-03 19:17:06 +00:00
return false ;
2008-03-09 23:29:14 +00:00
2022-10-25 16:51:56 +00:00
// modify indices
2023-07-02 10:15:20 +00:00
static const auto & & s_ModifyAddIndex = [ ] ( int AddAmount ) {
return [ AddAmount ] ( int * pIndex ) {
if ( * pIndex > = 0 )
* pIndex + = AddAmount ;
} ;
} ;
NewMap . ModifyImageIndex ( s_ModifyAddIndex ( m_Map . m_vpImages . size ( ) ) ) ;
NewMap . ModifySoundIndex ( s_ModifyAddIndex ( m_Map . m_vpSounds . size ( ) ) ) ;
NewMap . ModifyEnvelopeIndex ( s_ModifyAddIndex ( m_Map . m_vpEnvelopes . size ( ) ) ) ;
2011-04-13 18:37:12 +00:00
2008-03-09 23:29:14 +00:00
// transfer images
2022-06-11 19:38:18 +00:00
for ( const auto & pImage : NewMap . m_vpImages )
m_Map . m_vpImages . push_back ( pImage ) ;
NewMap . m_vpImages . clear ( ) ;
2011-04-13 18:37:12 +00:00
2022-11-03 19:21:45 +00:00
// transfer sounds
for ( const auto & pSound : NewMap . m_vpSounds )
m_Map . m_vpSounds . push_back ( pSound ) ;
NewMap . m_vpSounds . clear ( ) ;
2008-03-09 23:29:14 +00:00
// transfer envelopes
2022-06-11 19:38:18 +00:00
for ( const auto & pEnvelope : NewMap . m_vpEnvelopes )
m_Map . m_vpEnvelopes . push_back ( pEnvelope ) ;
NewMap . m_vpEnvelopes . clear ( ) ;
2008-03-09 23:29:14 +00:00
// transfer groups
2022-06-11 19:38:18 +00:00
for ( const auto & pGroup : NewMap . m_vpGroups )
2008-03-09 23:29:14 +00:00
{
2023-07-28 11:16:18 +00:00
if ( pGroup ! = NewMap . m_pGameGroup )
2010-05-29 07:25:38 +00:00
{
2022-05-24 09:24:33 +00:00
pGroup - > m_pMap = & m_Map ;
2022-06-11 19:38:18 +00:00
m_Map . m_vpGroups . push_back ( pGroup ) ;
2010-05-29 07:25:38 +00:00
}
2008-03-09 23:29:14 +00:00
}
2022-06-11 19:38:18 +00:00
NewMap . m_vpGroups . clear ( ) ;
2011-04-13 18:37:12 +00:00
2022-11-03 19:17:06 +00:00
SortImages ( ) ;
2008-03-09 23:29:14 +00:00
// all done \o/
2022-11-03 19:17:06 +00:00
return true ;
2008-03-05 19:38:47 +00:00
}