mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge pull request #1321 from bojidar-bg/x-add-auto-automapper
Add option to automatically run the automapper
This commit is contained in:
commit
045533cef7
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h> // sscanf
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <engine/console.h>
|
||||
#include <engine/storage.h>
|
||||
|
@ -7,6 +8,35 @@
|
|||
#include "auto_map.h"
|
||||
#include "editor.h"
|
||||
|
||||
// Based on triple32inc from https://github.com/skeeto/hash-prospector/tree/79a6074062a84907df6e45b756134b74e2956760
|
||||
static uint32_t HashUInt32(uint32_t Num)
|
||||
{
|
||||
Num++;
|
||||
Num ^= Num >> 17;
|
||||
Num *= 0xed5ad4bbu;
|
||||
Num ^= Num >> 11;
|
||||
Num *= 0xac4c1b51u;
|
||||
Num ^= Num >> 15;
|
||||
Num *= 0x31848babu;
|
||||
Num ^= Num >> 14;
|
||||
return Num;
|
||||
}
|
||||
|
||||
#define HASH_MAX 65536
|
||||
|
||||
static int HashLocation(uint32_t Seed, uint32_t Run, uint32_t Rule, uint32_t X, uint32_t Y)
|
||||
{
|
||||
const uint32_t Prime = 31;
|
||||
uint32_t Hash = 1;
|
||||
Hash = Hash * Prime + HashUInt32(Seed);
|
||||
Hash = Hash * Prime + HashUInt32(Run);
|
||||
Hash = Hash * Prime + HashUInt32(Rule);
|
||||
Hash = Hash * Prime + HashUInt32(X);
|
||||
Hash = Hash * Prime + HashUInt32(Y);
|
||||
Hash = HashUInt32(Hash * Prime); // Just to double-check that values are well-distributed
|
||||
return Hash % HASH_MAX;
|
||||
}
|
||||
|
||||
CAutoMapper::CAutoMapper(CEditor *pEditor)
|
||||
{
|
||||
m_pEditor = pEditor;
|
||||
|
@ -42,6 +72,10 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
// new configuration, get the name
|
||||
pLine++;
|
||||
CConfiguration NewConf;
|
||||
NewConf.m_StartX = 0;
|
||||
NewConf.m_StartY = 0;
|
||||
NewConf.m_EndX = 0;
|
||||
NewConf.m_EndY = 0;
|
||||
int ConfigurationID = m_lConfigs.add(NewConf);
|
||||
pCurrentConf = &m_lConfigs[ConfigurationID];
|
||||
str_copy(pCurrentConf->m_aName, pLine, str_length(pLine));
|
||||
|
@ -224,6 +258,11 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
CPosRule NewPosRule = {x, y, Value, NewIndexList};
|
||||
pCurrentIndex->m_aRules.add(NewPosRule);
|
||||
|
||||
pCurrentConf->m_StartX = min(pCurrentConf->m_StartX, NewPosRule.m_X);
|
||||
pCurrentConf->m_StartY = min(pCurrentConf->m_StartY, NewPosRule.m_Y);
|
||||
pCurrentConf->m_EndX = max(pCurrentConf->m_EndX, NewPosRule.m_X);
|
||||
pCurrentConf->m_EndY = max(pCurrentConf->m_EndY, NewPosRule.m_Y);
|
||||
|
||||
if(x == 0 && y == 0) {
|
||||
for(int i = 0; i < NewIndexList.size(); ++i)
|
||||
{
|
||||
|
@ -313,11 +352,70 @@ const char* CAutoMapper::GetConfigName(int Index)
|
|||
return m_lConfigs[Index].m_aName;
|
||||
}
|
||||
|
||||
void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID)
|
||||
void CAutoMapper::ProceedLocalized(CLayerTiles *pLayer, int ConfigID, int Seed, int X, int Y, int Width, int Height)
|
||||
{
|
||||
if(!m_FileLoaded || pLayer->m_Readonly || ConfigID < 0 || ConfigID >= m_lConfigs.size())
|
||||
return;
|
||||
|
||||
if(Width < 0)
|
||||
Width = pLayer->m_Width;
|
||||
|
||||
if(Height < 0)
|
||||
Height = pLayer->m_Height;
|
||||
|
||||
CConfiguration *pConf = &m_lConfigs[ConfigID];
|
||||
|
||||
int CommitFromX = max(X + pConf->m_StartX, 0);
|
||||
int CommitFromY = max(Y + pConf->m_StartY, 0);
|
||||
int CommitToX = min(X + Width + pConf->m_EndX, pLayer->m_Width);
|
||||
int CommitToY = min(Y + Height + pConf->m_EndY, pLayer->m_Height);
|
||||
|
||||
int UpdateFromX = max(X + 3 * pConf->m_StartX, 0);
|
||||
int UpdateFromY = max(Y + 3 * pConf->m_StartY, 0);
|
||||
int UpdateToX = min(X + Width + 3 * pConf->m_EndX, pLayer->m_Width);
|
||||
int UpdateToY = min(Y + Height + 3 * pConf->m_EndY, pLayer->m_Height);
|
||||
|
||||
CLayerTiles *pUpdateLayer;
|
||||
if (UpdateFromX != 0 || UpdateFromY != 0 || UpdateToX != pLayer->m_Width || UpdateToY != pLayer->m_Width)
|
||||
{ // Needs a layer to work on
|
||||
pUpdateLayer = new CLayerTiles(UpdateToX - UpdateFromX, UpdateToY - UpdateFromY);
|
||||
|
||||
for(int y = UpdateFromY; y < UpdateToY; y++) {
|
||||
for(int x = UpdateFromX; x < UpdateToX; x++)
|
||||
{
|
||||
CTile *in = &pLayer->m_pTiles[y*pLayer->m_Width+x];
|
||||
CTile *out = &pUpdateLayer->m_pTiles[(y-UpdateFromY)*pUpdateLayer->m_Width+x-UpdateFromX];
|
||||
out->m_Index = in->m_Index;
|
||||
out->m_Flags = in->m_Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pUpdateLayer = pLayer;
|
||||
}
|
||||
|
||||
Proceed(pUpdateLayer, ConfigID, Seed, UpdateFromX, UpdateFromY);
|
||||
|
||||
for(int y = CommitFromY; y < CommitToY; y++) {
|
||||
for(int x = CommitFromX; x < CommitToX; x++)
|
||||
{
|
||||
CTile *in = &pUpdateLayer->m_pTiles[(y-UpdateFromY)*pUpdateLayer->m_Width+x-UpdateFromX];
|
||||
CTile *out = &pLayer->m_pTiles[y*pLayer->m_Width+x];
|
||||
out->m_Index = in->m_Index;
|
||||
out->m_Flags = in->m_Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID, int Seed, int SeedOffsetX, int SeedOffsetY)
|
||||
{
|
||||
if(!m_FileLoaded || pLayer->m_Readonly || ConfigID < 0 || ConfigID >= m_lConfigs.size())
|
||||
return;
|
||||
|
||||
if(Seed == 0)
|
||||
Seed = rand();
|
||||
|
||||
CConfiguration *pConf = &m_lConfigs[ConfigID];
|
||||
|
||||
// for every run: copy tiles, automap, overwrite tiles
|
||||
|
@ -326,18 +424,10 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID)
|
|||
|
||||
// don't make copy if it's requested
|
||||
CLayerTiles *pReadLayer;
|
||||
if(pRun->m_AutomapCopy)
|
||||
if(pRun->m_AutomapCopy)
|
||||
{
|
||||
pReadLayer = new CLayerTiles(pLayer->m_Width, pLayer->m_Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
pReadLayer = pLayer;
|
||||
}
|
||||
|
||||
// copy tiles
|
||||
if(pRun->m_AutomapCopy)
|
||||
{
|
||||
for(int y = 0; y < pLayer->m_Height; y++) {
|
||||
for(int x = 0; x < pLayer->m_Width; x++)
|
||||
{
|
||||
|
@ -348,6 +438,10 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pReadLayer = pLayer;
|
||||
}
|
||||
|
||||
// auto map
|
||||
for(int y = 0; y < pLayer->m_Height; y++) {
|
||||
|
@ -405,7 +499,7 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID)
|
|||
}
|
||||
|
||||
if(RespectRules &&
|
||||
(pIndexRule->m_RandomProbability >= 1.0 || (float)rand() / ((float)RAND_MAX + 1) < pIndexRule->m_RandomProbability))
|
||||
(pIndexRule->m_RandomProbability >= 1.0 || HashLocation(Seed, h, i, x + SeedOffsetX, y + SeedOffsetY) < HASH_MAX * pIndexRule->m_RandomProbability))
|
||||
{
|
||||
pTile->m_Index = pIndexRule->m_ID;
|
||||
pTile->m_Flags = pIndexRule->m_Flag;
|
||||
|
|
|
@ -48,13 +48,19 @@ class CAutoMapper
|
|||
{
|
||||
array<CRun> m_aRuns;
|
||||
char m_aName[128];
|
||||
int m_StartX;
|
||||
int m_StartY;
|
||||
int m_EndX;
|
||||
int m_EndY;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
CAutoMapper(class CEditor *pEditor);
|
||||
|
||||
void Load(const char* pTileName);
|
||||
void Proceed(class CLayerTiles *pLayer, int ConfigID);
|
||||
void ProceedLocalized(class CLayerTiles *pLayer, int ConfigID, int Seed=0, int X=0, int Y=0, int Width=-1, int Height=-1);
|
||||
void Proceed(class CLayerTiles *pLayer, int ConfigID, int Seed=0, int SeedOffsetX=0, int SeedOffsetY=0);
|
||||
|
||||
int ConfigNamesNum() const { return m_lConfigs.size(); }
|
||||
const char* GetConfigName(int Index);
|
||||
|
|
|
@ -3163,6 +3163,24 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int *
|
|||
Change = i;
|
||||
}
|
||||
}
|
||||
else if(pProps[i].m_Type == PROPTYPE_AUTOMAPPER)
|
||||
{
|
||||
char aBuf[64];
|
||||
if(pProps[i].m_Value < 0 || pProps[i].m_Min < 0 || pProps[i].m_Min >= m_Map.m_lImages.size())
|
||||
str_copy(aBuf, "None", sizeof(aBuf));
|
||||
else
|
||||
str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Min]->m_AutoMapper.GetConfigName(pProps[i].m_Value));
|
||||
|
||||
if(DoButton_Editor(&pIDs[i], aBuf, 0, &Shifter, 0, 0))
|
||||
PopupSelectConfigAutoMapInvoke(pProps[i].m_Value, UI()->MouseX(), UI()->MouseY());
|
||||
|
||||
int r = PopupSelectConfigAutoMapResult();
|
||||
if(r >= -1)
|
||||
{
|
||||
*pNewVal = r;
|
||||
Change = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Change;
|
||||
|
@ -3346,7 +3364,7 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect View)
|
|||
}
|
||||
static int s_LayerPopupID = 0;
|
||||
if(Result == 2)
|
||||
UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 280, PopupLayer);
|
||||
UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 300, PopupLayer);
|
||||
}
|
||||
|
||||
LayerCur += 14.0f;
|
||||
|
|
|
@ -505,6 +505,7 @@ enum
|
|||
PROPTYPE_ENVELOPE,
|
||||
PROPTYPE_SHIFT,
|
||||
PROPTYPE_SOUND,
|
||||
PROPTYPE_AUTOMAPPER,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -551,6 +552,8 @@ public:
|
|||
void PrepareForSave();
|
||||
|
||||
void GetSize(float *w, float *h) { *w = m_Width*32.0f; *h = m_Height*32.0f; }
|
||||
|
||||
void FlagModified(int x, int y, int w, int h);
|
||||
|
||||
int m_TexID;
|
||||
int m_Game;
|
||||
|
@ -564,6 +567,9 @@ public:
|
|||
|
||||
// DDRace
|
||||
|
||||
int m_AutoMapperConfig;
|
||||
int m_Seed;
|
||||
bool m_AutoAutoMap;
|
||||
int m_Tele;
|
||||
int m_Speedup;
|
||||
int m_Front;
|
||||
|
@ -993,7 +999,7 @@ public:
|
|||
void PopupSelectGametileOpInvoke(float x, float y);
|
||||
int PopupSelectGameTileOpResult();
|
||||
|
||||
void PopupSelectConfigAutoMapInvoke(float x, float y);
|
||||
void PopupSelectConfigAutoMapInvoke(int Current, float x, float y);
|
||||
int PopupSelectConfigAutoMapResult();
|
||||
|
||||
void PopupSelectSoundInvoke(int Current, float x, float y);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <engine/serverbrowser.h>
|
||||
#include <engine/storage.h>
|
||||
#include <game/gamecore.h>
|
||||
#include <game/mapitems_ex.h>
|
||||
#include "editor.h"
|
||||
|
||||
template<typename T>
|
||||
|
@ -352,6 +353,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
|
|||
|
||||
// save layers
|
||||
int LayerCount = 0, GroupCount = 0;
|
||||
int AutomapperCount = 0;
|
||||
for(int g = 0; g < m_lGroups.size(); g++)
|
||||
{
|
||||
CLayerGroup *pGroup = m_lGroups[g];
|
||||
|
@ -442,6 +444,17 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
|
|||
|
||||
df.AddItem(MAPITEMTYPE_LAYER, LayerCount, sizeof(Item), &Item);
|
||||
|
||||
CMapItemAutoMapperConfig ItemAutomapper;
|
||||
ItemAutomapper.m_GroupId = GroupCount;
|
||||
ItemAutomapper.m_LayerId = GItem.m_NumLayers;
|
||||
ItemAutomapper.m_AutomapperConfig = pLayer->m_AutoMapperConfig;
|
||||
ItemAutomapper.m_AutomapperSeed = pLayer->m_Seed;
|
||||
ItemAutomapper.m_Flags = 0;
|
||||
if (pLayer->m_AutoAutoMap) ItemAutomapper.m_Flags |= CMapItemAutoMapperConfig::FLAG_AUTOMATIC;
|
||||
|
||||
df.AddItem(MAPITEMTYPE_AUTOMAPPER_CONFIG, AutomapperCount, sizeof(ItemAutomapper), &ItemAutomapper);
|
||||
AutomapperCount++;
|
||||
|
||||
GItem.m_NumLayers++;
|
||||
LayerCount++;
|
||||
}
|
||||
|
@ -1263,6 +1276,26 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
|
|||
pEnv->m_Synchronized = pItem->m_Synchronized;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int Start, Num;
|
||||
DataFile.GetType(MAPITEMTYPE_AUTOMAPPER_CONFIG, &Start, &Num);
|
||||
for(int i = 0; i < Num; i++)
|
||||
{
|
||||
CMapItemAutoMapperConfig *pItem = (CMapItemAutoMapperConfig *)DataFile.GetItem(Start+i, 0, 0);
|
||||
if (pItem->m_Version == CMapItemAutoMapperConfig::CURRENT_VERSION) {
|
||||
if (pItem->m_GroupId >= 0 && pItem->m_GroupId < m_lGroups.size() &&
|
||||
pItem->m_LayerId >= 0 && pItem->m_LayerId < m_lGroups[pItem->m_GroupId]->m_lLayers.size() &&
|
||||
m_lGroups[pItem->m_GroupId]->m_lLayers[pItem->m_LayerId]->m_Type == LAYERTYPE_TILES) {
|
||||
|
||||
CLayerTiles *pLayer = (CLayerTiles *)m_lGroups[pItem->m_GroupId]->m_lLayers[pItem->m_LayerId];
|
||||
pLayer->m_AutoMapperConfig = pItem->m_AutomapperConfig;
|
||||
pLayer->m_Seed = pItem->m_AutomapperSeed;
|
||||
pLayer->m_AutoAutoMap = !!(pItem->m_Flags & CMapItemAutoMapperConfig::FLAG_AUTOMATIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
|
|
@ -36,6 +36,9 @@ CLayerTiles::CLayerTiles(int w, int h)
|
|||
m_Front = 0;
|
||||
m_Switch = 0;
|
||||
m_Tune = 0;
|
||||
m_AutoMapperConfig = -1;
|
||||
m_Seed = 0;
|
||||
m_AutoAutoMap = false;
|
||||
|
||||
m_pTiles = new CTile[m_Width*m_Height];
|
||||
mem_zero(m_pTiles, m_Width*m_Height*sizeof(CTile));
|
||||
|
@ -406,7 +409,7 @@ void CLayerTiles::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
|||
SetTile(fx, fy, pLt->m_pTiles[(y*pLt->m_Width + x%pLt->m_Width) % (pLt->m_Width*pLt->m_Height)]);
|
||||
}
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy)
|
||||
|
@ -429,7 +432,7 @@ void CLayerTiles::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
|
||||
SetTile(fx, fy, l->m_pTiles[y*l->m_Width+x]);
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
void CLayerTiles::BrushFlipX()
|
||||
|
@ -620,29 +623,11 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
CUIRect Button;
|
||||
|
||||
bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty();
|
||||
if(m_pEditor->m_Map.m_pGameLayer != this)
|
||||
{
|
||||
if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size() && m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.IsLoaded())
|
||||
{
|
||||
static int s_AutoMapperButton = 0;
|
||||
pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
|
||||
if(m_pEditor->DoButton_Editor(&s_AutoMapperButton, "Auto map", 0, &Button, 0, ""))
|
||||
m_pEditor->PopupSelectConfigAutoMapInvoke(m_pEditor->UI()->MouseX(), m_pEditor->UI()->MouseY());
|
||||
|
||||
int Result = m_pEditor->PopupSelectConfigAutoMapResult();
|
||||
if(Result > -1)
|
||||
{
|
||||
m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.Proceed(this, Result);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(m_pEditor->m_Map.m_pGameLayer == this || m_pEditor->m_Map.m_pTeleLayer == this || m_pEditor->m_Map.m_pSpeedupLayer == this || m_pEditor->m_Map.m_pFrontLayer == this || m_pEditor->m_Map.m_pSwitchLayer == this || m_pEditor->m_Map.m_pTuneLayer == this)
|
||||
if(m_pEditor->m_Map.m_pGameLayer == this || m_pEditor->m_Map.m_pTeleLayer == this || m_pEditor->m_Map.m_pSpeedupLayer == this || m_pEditor->m_Map.m_pFrontLayer == this || m_pEditor->m_Map.m_pSwitchLayer == this || m_pEditor->m_Map.m_pTuneLayer == this)
|
||||
InGameGroup = false;
|
||||
|
||||
if(InGameGroup)
|
||||
{
|
||||
pToolBox->HSplitBottom(2.0f, pToolBox, 0);
|
||||
pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
|
||||
static int s_ColclButton = 0;
|
||||
if(m_pEditor->DoButton_Editor(&s_ColclButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer"))
|
||||
|
@ -708,6 +693,33 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pEditor->m_Map.m_pGameLayer != this)
|
||||
{
|
||||
if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size() && m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.IsLoaded() &&
|
||||
m_AutoMapperConfig != -1)
|
||||
{
|
||||
static int s_AutoMapperButton = 0;
|
||||
static int s_AutoMapperButtonAuto = 0;
|
||||
pToolBox->HSplitBottom(2.0f, pToolBox, 0);
|
||||
pToolBox->HSplitBottom(12.0f, pToolBox, &Button);
|
||||
if(m_Seed != 0) {
|
||||
CUIRect ButtonAuto;
|
||||
Button.VSplitRight(16.0f, &Button, &ButtonAuto);
|
||||
Button.VSplitRight(2.0f, &Button, 0);
|
||||
if(m_pEditor->DoButton_Editor(&s_AutoMapperButtonAuto, "A", m_AutoAutoMap, &ButtonAuto, 0, "Automatically run automap after modifications."))
|
||||
{
|
||||
m_AutoAutoMap = !m_AutoAutoMap;
|
||||
FlagModified(0, 0, m_Width, m_Height);
|
||||
}
|
||||
}
|
||||
if(m_pEditor->DoButton_Editor(&s_AutoMapperButton, "Automap", 0, &Button, 0, "Run the automapper"))
|
||||
{
|
||||
m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.Proceed(this, m_AutoMapperConfig, m_Seed);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -719,6 +731,8 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
PROP_COLOR,
|
||||
PROP_COLOR_ENV,
|
||||
PROP_COLOR_ENV_OFFSET,
|
||||
PROP_AUTOMAPPER,
|
||||
PROP_SEED,
|
||||
NUM_PROPS,
|
||||
};
|
||||
|
||||
|
@ -737,20 +751,26 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
{"Color", Color, PROPTYPE_COLOR, 0, 0},
|
||||
{"Color Env", m_ColorEnv+1, PROPTYPE_INT_STEP, 0, m_pEditor->m_Map.m_lEnvelopes.size()+1},
|
||||
{"Color TO", m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
|
||||
{"Auto Rule", m_AutoMapperConfig, PROPTYPE_AUTOMAPPER, m_Image, 0},
|
||||
{"Seed", m_Seed, PROPTYPE_INT_SCROLL, 0, 1000000000},
|
||||
{0},
|
||||
};
|
||||
|
||||
if(m_pEditor->m_Map.m_pGameLayer == this || m_pEditor->m_Map.m_pTeleLayer == this || m_pEditor->m_Map.m_pSpeedupLayer == this || m_pEditor->m_Map.m_pFrontLayer == this || m_pEditor->m_Map.m_pSwitchLayer == this || m_pEditor->m_Map.m_pTuneLayer == this) // remove the image and color properties if this is the game/tele/speedup/front/switch layer
|
||||
{
|
||||
aProps[4].m_pName = 0;
|
||||
aProps[5].m_pName = 0;
|
||||
aProps[PROP_IMAGE].m_pName = 0;
|
||||
aProps[PROP_COLOR].m_pName = 0;
|
||||
aProps[PROP_AUTOMAPPER].m_pName = 0;
|
||||
}
|
||||
if(m_Image == -1)
|
||||
{
|
||||
aProps[PROP_AUTOMAPPER].m_pName = 0;
|
||||
aProps[PROP_SEED].m_pName = 0;
|
||||
}
|
||||
|
||||
static int s_aIds[NUM_PROPS] = {0};
|
||||
int NewVal = 0;
|
||||
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
|
||||
if(Prop != -1)
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
|
||||
if(Prop == PROP_WIDTH && NewVal > 1)
|
||||
{
|
||||
|
@ -784,7 +804,10 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
m_Image = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Image = NewVal%m_pEditor->m_Map.m_lImages.size();
|
||||
m_AutoMapperConfig = -1;
|
||||
}
|
||||
}
|
||||
else if(Prop == PROP_COLOR)
|
||||
{
|
||||
|
@ -809,10 +832,29 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
|
|||
}
|
||||
if(Prop == PROP_COLOR_ENV_OFFSET)
|
||||
m_ColorEnvOffset = NewVal;
|
||||
else if(Prop == PROP_SEED)
|
||||
m_Seed = NewVal;
|
||||
else if(Prop == PROP_AUTOMAPPER)
|
||||
{
|
||||
if (m_Image >= 0 && m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.ConfigNamesNum() > 0 && NewVal >= 0)
|
||||
m_AutoMapperConfig = NewVal%m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.ConfigNamesNum();
|
||||
else
|
||||
m_AutoMapperConfig = -1;
|
||||
}
|
||||
if(Prop != -1) {
|
||||
FlagModified(0, 0, m_Width, m_Height);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CLayerTiles::FlagModified(int x, int y, int w, int h) {
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
if (m_Seed != 0 && m_AutoMapperConfig != -1 && m_AutoAutoMap) {
|
||||
m_pEditor->m_Map.m_lImages[m_Image]->m_AutoMapper.ProceedLocalized(this, m_AutoMapperConfig, m_Seed, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLayerTiles::ModifyImageIndex(INDEX_MODIFY_FUNC Func)
|
||||
{
|
||||
|
@ -960,7 +1002,7 @@ void CLayerTele::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
m_pTiles[fy*m_Width+fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
void CLayerTele::BrushFlipX()
|
||||
|
@ -1071,6 +1113,7 @@ void CLayerTele::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
|||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
CLayerSpeedup::CLayerSpeedup(int w, int h)
|
||||
|
@ -1225,7 +1268,7 @@ void CLayerSpeedup::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
m_pTiles[fy*m_Width+fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
void CLayerSpeedup::BrushFlipX()
|
||||
|
@ -1344,6 +1387,7 @@ void CLayerSpeedup::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
|||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
CLayerFront::CLayerFront(int w, int h)
|
||||
|
@ -1411,7 +1455,7 @@ void CLayerFront::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
|
||||
SetTile(fx, fy, l->m_pTiles[y*l->m_Width+x]);
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
CLayerSwitch::CLayerSwitch(int w, int h)
|
||||
|
@ -1578,7 +1622,7 @@ void CLayerSwitch::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
m_pSwitchTile[fy*m_Width+fx].m_Delay = 0;
|
||||
}
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
void CLayerSwitch::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
||||
|
@ -1633,6 +1677,7 @@ void CLayerSwitch::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
|||
}
|
||||
}
|
||||
}
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
@ -1776,7 +1821,7 @@ void CLayerTune::BrushDraw(CLayer *pBrush, float wx, float wy)
|
|||
m_pTiles[fy*m_Width+fx].m_Index = 0;
|
||||
}
|
||||
}
|
||||
m_pEditor->m_Map.m_Modified = true;
|
||||
FlagModified(sx, sy, l->m_Width, l->m_Height);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1887,4 +1932,6 @@ void CLayerTune::FillSelection(bool Empty, CLayer *pBrush, CUIRect Rect)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlagModified(sx, sy, w, h);
|
||||
}
|
||||
|
|
|
@ -1352,7 +1352,8 @@ int CEditor::PopupSelectGameTileOpResult()
|
|||
return Result;
|
||||
}
|
||||
|
||||
static int s_AutoMapConfigSelected = -1;
|
||||
static int s_AutoMapConfigSelected = -100;
|
||||
static int s_AutoMapConfigCurrent = -100;
|
||||
|
||||
int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View)
|
||||
{
|
||||
|
@ -1361,35 +1362,34 @@ int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View)
|
|||
static int s_AutoMapperConfigButtons[256];
|
||||
CAutoMapper *pAutoMapper = &pEditor->m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper;
|
||||
|
||||
for(int i = 0; i < pAutoMapper->ConfigNamesNum(); ++i)
|
||||
for(int i = -1; i < pAutoMapper->ConfigNamesNum(); ++i)
|
||||
{
|
||||
View.HSplitTop(2.0f, 0, &View);
|
||||
View.HSplitTop(12.0f, &Button, &View);
|
||||
if(pEditor->DoButton_Editor(&s_AutoMapperConfigButtons[i], pAutoMapper->GetConfigName(i), 0, &Button, 0, 0))
|
||||
if(pEditor->DoButton_MenuItem(&s_AutoMapperConfigButtons[i], i == -1 ? "None" : pAutoMapper->GetConfigName(i), i == s_AutoMapConfigCurrent, &Button, 0, 0))
|
||||
s_AutoMapConfigSelected = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CEditor::PopupSelectConfigAutoMapInvoke(float x, float y)
|
||||
void CEditor::PopupSelectConfigAutoMapInvoke(int Current, float x, float y)
|
||||
{
|
||||
static int s_AutoMapConfigSelectID = 0;
|
||||
s_AutoMapConfigSelected = -1;
|
||||
s_AutoMapConfigSelected = -100;
|
||||
s_AutoMapConfigCurrent = Current;
|
||||
CLayerTiles *pLayer = static_cast<CLayerTiles*>(GetSelectedLayer(0));
|
||||
if(pLayer && pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size() &&
|
||||
m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum())
|
||||
UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f, 12.0f+14.0f*m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum(), PopupSelectConfigAutoMap);
|
||||
UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f, 26.0f+14.0f*m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper.ConfigNamesNum(), PopupSelectConfigAutoMap);
|
||||
}
|
||||
|
||||
int CEditor::PopupSelectConfigAutoMapResult()
|
||||
{
|
||||
if(s_AutoMapConfigSelected < 0)
|
||||
return -1;
|
||||
if(s_AutoMapConfigSelected == -100)
|
||||
return -100;
|
||||
|
||||
int Result = s_AutoMapConfigSelected;
|
||||
s_AutoMapConfigSelected = -1;
|
||||
return Result;
|
||||
s_AutoMapConfigCurrent = s_AutoMapConfigSelected;
|
||||
s_AutoMapConfigSelected = -100;
|
||||
return s_AutoMapConfigCurrent;
|
||||
}
|
||||
|
||||
// DDRace
|
||||
|
|
|
@ -21,6 +21,20 @@ struct CMapItemTest
|
|||
int m_Field4;
|
||||
} ;
|
||||
|
||||
struct CMapItemAutoMapperConfig
|
||||
{
|
||||
enum { CURRENT_VERSION=1 };
|
||||
enum { FLAG_AUTOMATIC=1 };
|
||||
|
||||
int m_Version;
|
||||
int m_GroupId;
|
||||
int m_LayerId;
|
||||
int m_AutomapperConfig;
|
||||
int m_AutomapperSeed;
|
||||
int m_Flags;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
void RegisterMapItemTypeUuids(class CUuidManager *pManager);
|
||||
#endif // GAME_MAPITEMS_EX_H
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// This file can be included several times.
|
||||
|
||||
UUID(MAPITEMTYPE_TEST, "mapitemtype-test@ddnet.tw")
|
||||
UUID(MAPITEMTYPE_TEST, "mapitemtype-test@ddnet.tw")
|
||||
UUID(MAPITEMTYPE_AUTOMAPPER_CONFIG, "mapitemtype-automapper-config@ddnet.tw")
|
||||
|
|
Loading…
Reference in a new issue