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.
This commit is contained in:
Robert Müller 2023-06-23 17:39:05 +02:00
parent 58156c12b9
commit 1810d972f4
10 changed files with 160 additions and 56 deletions

View file

@ -68,6 +68,7 @@ public:
CreateFolder("screenshots/auto", TYPE_SAVE);
CreateFolder("screenshots/auto/stats", TYPE_SAVE);
CreateFolder("maps", TYPE_SAVE);
CreateFolder("maps/auto", TYPE_SAVE);
CreateFolder("mapres", TYPE_SAVE);
CreateFolder("downloadedmaps", TYPE_SAVE);
CreateFolder("skins", TYPE_SAVE);

View file

@ -470,7 +470,7 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID, int Seed, int SeedO
for(int x = 0; x < pLayer->m_Width; x++)
{
CTile *pTile = &(pLayer->m_pTiles[y * pLayer->m_Width + x]);
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
for(size_t i = 0; i < pRun->m_vIndexRules.size(); ++i)
{

View file

@ -17,6 +17,7 @@
#include <engine/input.h>
#include <engine/keys.h>
#include <engine/shared/config.h>
#include <engine/shared/filecollection.h>
#include <engine/storage.h>
#include <engine/textrender.h>
@ -207,7 +208,7 @@ void CLayerGroup::Render()
void CLayerGroup::AddLayer(CLayer *pLayer)
{
m_pMap->m_Modified = true;
m_pMap->OnModify();
m_vpLayers.push_back(pLayer);
}
@ -217,7 +218,7 @@ void CLayerGroup::DeleteLayer(int Index)
return;
delete m_vpLayers[Index];
m_vpLayers.erase(m_vpLayers.begin() + Index);
m_pMap->m_Modified = true;
m_pMap->OnModify();
}
void CLayerGroup::DuplicateLayer(int Index)
@ -228,7 +229,7 @@ void CLayerGroup::DuplicateLayer(int Index)
auto *pDup = m_vpLayers[Index]->Duplicate();
m_vpLayers.insert(m_vpLayers.begin() + Index + 1, pDup);
m_pMap->m_Modified = true;
m_pMap->OnModify();
}
void CLayerGroup::GetSize(float *pWidth, float *pHeight) const
@ -252,7 +253,7 @@ int CLayerGroup::SwapLayers(int Index0, int Index1)
return Index0;
if(Index0 == Index1)
return Index0;
m_pMap->m_Modified = true;
m_pMap->OnModify();
std::swap(m_vpLayers[Index0], m_vpLayers[Index1]);
return Index1;
}
@ -828,7 +829,7 @@ bool CEditor::CallbackAppendMap(const char *pFileName, int StorageType, void *pU
bool CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUser)
{
CEditor *pEditor = static_cast<CEditor *>(pUser);
char aBuf[1024];
char aBuf[IO_MAX_PATH_LENGTH];
// add map extension
if(!str_endswith(pFileName, ".map"))
{
@ -836,25 +837,35 @@ bool CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUse
pFileName = aBuf;
}
// Save map to specified file
if(pEditor->Save(pFileName))
{
str_copy(pEditor->m_aFileName, pFileName);
pEditor->m_ValidSaveFilename = StorageType == IStorage::TYPE_SAVE && pEditor->m_pFileDialogPath == pEditor->m_aFileDialogCurrentFolder;
pEditor->m_Map.m_Modified = false;
pEditor->m_Dialog = DIALOG_NONE;
return true;
}
else
{
pEditor->ShowFileDialogError("Failed to save map to file '%s'.", pFileName);
return false;
}
// Also update autosave if it's older than half the configured autosave interval, so we also have periodic backups.
const float Time = pEditor->Client()->GlobalTime();
if(g_Config.m_EdAutosaveInterval > 0 && pEditor->m_Map.m_LastSaveTime < Time && Time - pEditor->m_Map.m_LastSaveTime > 30 * g_Config.m_EdAutosaveInterval)
{
if(!pEditor->PerformAutosave())
return false;
}
pEditor->m_Dialog = DIALOG_NONE;
return true;
}
bool CEditor::CallbackSaveCopyMap(const char *pFileName, int StorageType, void *pUser)
{
CEditor *pEditor = static_cast<CEditor *>(pUser);
char aBuf[1024];
char aBuf[IO_MAX_PATH_LENGTH];
// add map extension
if(!str_endswith(pFileName, ".map"))
{
@ -864,7 +875,6 @@ bool CEditor::CallbackSaveCopyMap(const char *pFileName, int StorageType, void *
if(pEditor->Save(pFileName))
{
pEditor->m_Map.m_Modified = false;
pEditor->m_Dialog = DIALOG_NONE;
return true;
}
@ -1524,7 +1534,7 @@ void CEditor::DoQuad(CQuad *pQuad, int Index)
if(m_vSelectedLayers.size() == 1)
{
UI()->DisableMouseLock();
m_Map.m_Modified = true;
m_Map.OnModify();
DeleteSelectedQuads();
}
s_Operation = OP_NONE;
@ -3817,7 +3827,7 @@ void CEditor::RenderLayers(CUIRect LayersBox)
m_SelectedGroup = GroupAfterDraggedLayer - 1;
m_vSelectedLayers.clear();
m_vSelectedQuads.clear();
m_Map.m_Modified = true;
m_Map.OnModify();
}
}
@ -3834,7 +3844,7 @@ void CEditor::RenderLayers(CUIRect LayersBox)
m_Map.m_vpGroups.insert(InsertPosition, pSelectedGroup);
m_SelectedGroup = InsertPosition - m_Map.m_vpGroups.begin();
m_Map.m_Modified = true;
m_Map.OnModify();
}
if(MoveLayers || MoveGroup)
@ -5344,7 +5354,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
static int s_NewSoundButton = 0;
if(DoButton_Editor(&s_NewSoundButton, "Sound+", 0, &Button, 0, "Creates a new sound envelope"))
{
m_Map.m_Modified = true;
m_Map.OnModify();
pNewEnv = m_Map.NewEnvelope(1);
}
@ -5353,7 +5363,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
static int s_New4dButton = 0;
if(DoButton_Editor(&s_New4dButton, "Color+", 0, &Button, 0, "Creates a new color envelope"))
{
m_Map.m_Modified = true;
m_Map.OnModify();
pNewEnv = m_Map.NewEnvelope(4);
}
@ -5362,7 +5372,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
static int s_New2dButton = 0;
if(DoButton_Editor(&s_New2dButton, "Pos.+", 0, &Button, 0, "Creates a new position envelope"))
{
m_Map.m_Modified = true;
m_Map.OnModify();
pNewEnv = m_Map.NewEnvelope(3);
}
@ -5473,7 +5483,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
s_NameInput.SetBuffer(pEnvelope->m_aName, sizeof(pEnvelope->m_aName));
if(DoEditBox(&s_NameInput, &Button, 10.0f, IGraphics::CORNER_ALL, "The name of the selected envelope"))
{
m_Map.m_Modified = true;
m_Map.OnModify();
}
}
}
@ -5578,7 +5588,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
pEnvelope->AddPoint(Time,
f2fx(Channels.r), f2fx(Channels.g),
f2fx(Channels.b), f2fx(Channels.a));
m_Map.m_Modified = true;
m_Map.OnModify();
}
m_ShowEnvelopePreview = SHOWENV_SELECTED;
@ -5757,7 +5767,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
m_SelectedQuadEnvelope = m_SelectedEnvelope;
m_ShowEnvelopePreview = SHOWENV_SELECTED;
m_SelectedEnvelopePoint = i;
m_Map.m_Modified = true;
m_Map.OnModify();
}
ColorMod = 100.0f;
@ -5787,7 +5797,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
}
pEnvelope->m_vPoints.erase(pEnvelope->m_vPoints.begin() + i);
m_Map.m_Modified = true;
m_Map.OnModify();
}
m_ShowEnvelopePreview = SHOWENV_SELECTED;
@ -6507,6 +6517,10 @@ void CEditor::Reset(bool CreateDefault)
m_MouseDeltaWy = 0;
m_Map.m_Modified = false;
m_Map.m_ModifiedAuto = false;
m_Map.m_LastModifiedTime = -1.0f;
m_Map.m_LastSaveTime = Client()->GlobalTime();
m_Map.m_LastAutosaveUpdateTime = -1.0f;
m_ShowEnvelopePreview = SHOWENV_NONE;
m_ShiftBy = 1;
@ -6625,12 +6639,19 @@ void CEditor::Goto(float X, float Y)
m_WorldOffsetY = Y * 32;
}
void CEditorMap::OnModify()
{
m_Modified = true;
m_ModifiedAuto = true;
m_LastModifiedTime = m_pEditor->Client()->GlobalTime();
}
void CEditorMap::DeleteEnvelope(int Index)
{
if(Index < 0 || Index >= (int)m_vpEnvelopes.size())
return;
m_Modified = true;
OnModify();
VisitEnvelopeReferences([Index](int &ElementIndex) {
if(ElementIndex == Index)
@ -6651,7 +6672,7 @@ void CEditorMap::SwapEnvelopes(int Index0, int Index1)
if(Index0 == Index1)
return;
m_Modified = true;
OnModify();
VisitEnvelopeReferences([Index0, Index1](int &ElementIndex) {
if(ElementIndex == Index0)
@ -6731,6 +6752,7 @@ void CEditorMap::Clean()
m_pGameGroup = nullptr;
m_Modified = false;
m_ModifiedAuto = false;
m_pTeleLayer = nullptr;
m_pSpeedupLayer = nullptr;
@ -6856,7 +6878,6 @@ void CEditor::Init()
m_Brush.m_pMap = &m_Map;
Reset(false);
m_Map.m_Modified = false;
ResetMenuBackgroundPositions();
m_vpMenuBackgroundPositionNames.resize(CMenuBackground::NUM_POS);
@ -6966,6 +6987,74 @@ void CEditor::HandleCursorMovement()
}
}
void CEditor::HandleAutosave()
{
const float Time = Client()->GlobalTime();
const float LastAutosaveUpdateTime = m_Map.m_LastAutosaveUpdateTime;
m_Map.m_LastAutosaveUpdateTime = Time;
if(g_Config.m_EdAutosaveInterval == 0)
return; // autosave disabled
if(!m_Map.m_ModifiedAuto || m_Map.m_LastModifiedTime < 0.0f)
return; // no unsaved changes
// Add time to autosave timer if the editor was disabled for more than 10 seconds,
// to prevent autosave from immediately activating when the editor is activated
// after being deactivated for some time.
if(LastAutosaveUpdateTime >= 0.0f && Time - LastAutosaveUpdateTime > 10.0f)
{
m_Map.m_LastSaveTime += Time - LastAutosaveUpdateTime;
}
// Check if autosave timer has expired.
if(m_Map.m_LastSaveTime >= Time || Time - m_Map.m_LastSaveTime < 60 * g_Config.m_EdAutosaveInterval)
return;
// Wait for 5 seconds of no modification before saving, to prevent autosave
// from immediately activating when a map is first modified or while user is
// modifying the map, but don't delay the autosave for more than 1 minute.
if(Time - m_Map.m_LastModifiedTime < 5.0f && Time - m_Map.m_LastSaveTime < 60 * (g_Config.m_EdAutosaveInterval + 1))
return;
PerformAutosave();
}
bool CEditor::PerformAutosave()
{
char aDate[20];
char aAutosavePath[IO_MAX_PATH_LENGTH];
str_timestamp(aDate, sizeof(aDate));
char aFileNameNoExt[IO_MAX_PATH_LENGTH];
if(m_aFileName[0] == '\0')
{
str_copy(aFileNameNoExt, "unnamed");
}
else
{
const char *pFileName = fs_filename(m_aFileName);
str_truncate(aFileNameNoExt, sizeof(aFileNameNoExt), pFileName, str_length(pFileName) - str_length(".map"));
}
str_format(aAutosavePath, sizeof(aAutosavePath), "maps/auto/%s_%s.map", aFileNameNoExt, aDate);
m_Map.m_LastSaveTime = Client()->GlobalTime();
if(Save(aAutosavePath))
{
m_Map.m_ModifiedAuto = false;
// Clean up autosaves
if(g_Config.m_EdAutosaveMax)
{
CFileCollection AutosavedMaps;
AutosavedMaps.Init(Storage(), "maps/auto", aFileNameNoExt, ".map", g_Config.m_EdAutosaveMax);
}
return true;
}
else
{
ShowFileDialogError("Failed to automatically save map to file '%s'.", aAutosavePath);
return false;
}
}
void CEditor::OnUpdate()
{
CUIElementBase::Init(UI()); // update static pointer because game and editor use separate UI
@ -6977,6 +7066,7 @@ void CEditor::OnUpdate()
}
HandleCursorMovement();
HandleAutosave();
}
void CEditor::OnRender()

View file

@ -315,7 +315,6 @@ class CEditorMap
public:
CEditor *m_pEditor;
bool m_Modified;
CEditorMap()
{
@ -327,6 +326,13 @@ public:
Clean();
}
bool m_Modified; // unsaved changes in manual save
bool m_ModifiedAuto; // unsaved changes in autosave
float m_LastModifiedTime;
float m_LastSaveTime;
float m_LastAutosaveUpdateTime;
void OnModify();
std::vector<CLayerGroup *> m_vpGroups;
std::vector<CEditorImage *> m_vpImages;
std::vector<CEnvelope *> m_vpEnvelopes;
@ -370,7 +376,7 @@ public:
CEnvelope *NewEnvelope(int Channels)
{
m_Modified = true;
OnModify();
CEnvelope *pEnv = new CEnvelope(Channels);
m_vpEnvelopes.push_back(pEnv);
return pEnv;
@ -383,7 +389,7 @@ public:
CLayerGroup *NewGroup()
{
m_Modified = true;
OnModify();
CLayerGroup *pGroup = new CLayerGroup;
pGroup->m_pMap = this;
m_vpGroups.push_back(pGroup);
@ -398,7 +404,7 @@ public:
return Index0;
if(Index0 == Index1)
return Index0;
m_Modified = true;
OnModify();
std::swap(m_vpGroups[Index0], m_vpGroups[Index1]);
return Index1;
}
@ -407,28 +413,28 @@ public:
{
if(Index < 0 || Index >= (int)m_vpGroups.size())
return;
m_Modified = true;
OnModify();
delete m_vpGroups[Index];
m_vpGroups.erase(m_vpGroups.begin() + Index);
}
void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc)
{
m_Modified = true;
OnModify();
for(auto &pGroup : m_vpGroups)
pGroup->ModifyImageIndex(pfnFunc);
}
void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc)
{
m_Modified = true;
OnModify();
for(auto &pGroup : m_vpGroups)
pGroup->ModifyEnvelopeIndex(pfnFunc);
}
void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc)
{
m_Modified = true;
OnModify();
for(auto &pGroup : m_vpGroups)
pGroup->ModifySoundIndex(pfnFunc);
}
@ -850,6 +856,8 @@ public:
void ResetMentions() override { m_Mentions = 0; }
void HandleCursorMovement();
void HandleAutosave();
bool PerformAutosave();
CLayerGroup *m_apSavedBrushes[10];

View file

@ -976,6 +976,9 @@ bool CEditorMap::Load(const char *pFileName, int StorageType)
return false;
m_Modified = false;
m_ModifiedAuto = false;
m_LastModifiedTime = -1.0f;
m_LastSaveTime = m_pEditor->Client()->GlobalTime();
return true;
}

View file

@ -37,7 +37,7 @@ void CLayerQuads::Render(bool QuadPicker)
CQuad *CLayerQuads::NewQuad(int x, int y, int Width, int Height)
{
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
m_vQuads.emplace_back();
CQuad *pQuad = &m_vQuads[m_vQuads.size() - 1];
@ -153,7 +153,7 @@ void CLayerQuads::BrushPlace(CLayer *pBrush, float wx, float wy)
m_vQuads.push_back(n);
}
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
void CLayerQuads::BrushFlipX()
@ -163,7 +163,7 @@ void CLayerQuads::BrushFlipX()
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[1]);
std::swap(Quad.m_aPoints[2], Quad.m_aPoints[3]);
}
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
void CLayerQuads::BrushFlipY()
@ -173,7 +173,7 @@ void CLayerQuads::BrushFlipY()
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[2]);
std::swap(Quad.m_aPoints[1], Quad.m_aPoints[3]);
}
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
void Rotate(vec2 *pCenter, vec2 *pPoint, float Rotation)
@ -236,7 +236,7 @@ CUI::EPopupMenuFunctionResult CLayerQuads::RenderProperties(CUIRect *pToolBox)
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
if(Prop == PROP_IMAGE)
@ -277,7 +277,7 @@ int CLayerQuads::SwapQuads(int Index0, int Index1)
return Index0;
if(Index0 == Index1)
return Index0;
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
std::swap(m_vQuads[Index0], m_vQuads[Index1]);
return Index1;
}

View file

@ -101,7 +101,7 @@ void CLayerSounds::Render(bool Tileset)
CSoundSource *CLayerSounds::NewSource(int x, int y)
{
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
m_vSources.emplace_back();
CSoundSource *pSource = &m_vSources[m_vSources.size() - 1];
@ -179,7 +179,7 @@ void CLayerSounds::BrushPlace(CLayer *pBrush, float wx, float wy)
m_vSources.push_back(n);
}
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
CUI::EPopupMenuFunctionResult CLayerSounds::RenderProperties(CUIRect *pToolBox)
@ -200,7 +200,7 @@ CUI::EPopupMenuFunctionResult CLayerSounds::RenderProperties(CUIRect *pToolBox)
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
}
if(Prop == PROP_SOUND)

View file

@ -1079,7 +1079,7 @@ CUI::EPopupMenuFunctionResult CLayerTiles::RenderCommonProperties(SCommonPropSta
void CLayerTiles::FlagModified(int x, int y, int w, int h)
{
m_pEditor->m_Map.m_Modified = true;
m_pEditor->m_Map.OnModify();
if(m_Seed != 0 && m_AutoMapperConfig != -1 && m_AutoAutoMap && m_Image >= 0)
{
m_pEditor->m_Map.m_vpImages[m_Image]->m_AutoMapper.ProceedLocalized(this, m_AutoMapperConfig, m_Seed, x, y, w, h);

View file

@ -366,7 +366,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupGroup(void *pContext, CUIRect View,
if(!Found)
{
pGameLayer->m_pTiles[y * pGameLayer->m_Width + x].m_Index = TILE_AIR;
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
}
}
@ -512,7 +512,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupGroup(void *pContext, CUIRect View,
static CLineInput s_NameInput;
s_NameInput.SetBuffer(pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->m_aName, sizeof(pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->m_aName));
if(pEditor->DoEditBox(&s_NameInput, &Button, 10.0f))
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
enum
@ -557,7 +557,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupGroup(void *pContext, CUIRect View,
int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
if(Prop == PROP_ORDER)
@ -683,7 +683,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupLayer(void *pContext, CUIRect View,
static CLineInput s_NameInput;
s_NameInput.SetBuffer(pCurrentLayer->m_aName, sizeof(pCurrentLayer->m_aName));
if(pEditor->DoEditBox(&s_NameInput, &EditBox, 10.0f))
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
// spacing if any button was rendered
@ -717,7 +717,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupLayer(void *pContext, CUIRect View,
int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
if(Prop == PROP_ORDER)
@ -762,7 +762,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupQuad(void *pContext, CUIRect View, b
{
if(pLayer)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
pEditor->DeleteSelectedQuads();
}
return CUI::POPUP_CLOSE_CURRENT;
@ -802,7 +802,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupQuad(void *pContext, CUIRect View, b
pQuad->m_aPoints[2].y = Top + Height;
pQuad->m_aPoints[3].x = Right;
pQuad->m_aPoints[3].y = Top + Height;
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
return CUI::POPUP_CLOSE_CURRENT;
}
@ -821,7 +821,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupQuad(void *pContext, CUIRect View, b
pQuad->m_aPoints[k].x = 1000.0f * (pQuad->m_aPoints[k].x / 1000);
pQuad->m_aPoints[k].y = 1000.0f * (pQuad->m_aPoints[k].y / 1000);
}
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
return CUI::POPUP_CLOSE_CURRENT;
}
@ -859,7 +859,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupQuad(void *pContext, CUIRect View, b
pQuad->m_aPoints[2].y = Bottom;
pQuad->m_aPoints[3].x = Right;
pQuad->m_aPoints[3].y = Bottom;
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
return CUI::POPUP_CLOSE_CURRENT;
}
@ -904,7 +904,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupQuad(void *pContext, CUIRect View, b
int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
const float OffsetX = i2fx(NewVal) - pCurrentQuad->m_aPoints[4].x;
@ -988,7 +988,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupSource(void *pContext, CUIRect View,
CLayerSounds *pLayer = (CLayerSounds *)pEditor->GetSelectedLayerType(0, LAYERTYPE_SOUNDS);
if(pLayer)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
pLayer->m_vSources.erase(pLayer->m_vSources.begin() + pEditor->m_SelectedSource);
pEditor->m_SelectedSource--;
}
@ -1062,7 +1062,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupSource(void *pContext, CUIRect View,
int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
if(Prop == PROP_POS_X)
@ -1145,7 +1145,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupSource(void *pContext, CUIRect View,
Prop = pEditor->DoProperties(&View, aCircleProps, s_aCircleIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
if(Prop == PROP_CIRCLE_RADIUS)
@ -1176,7 +1176,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupSource(void *pContext, CUIRect View,
Prop = pEditor->DoProperties(&View, aRectangleProps, s_aRectangleIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
if(Prop == PROP_RECTANGLE_WIDTH)
@ -1236,7 +1236,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupPoint(void *pContext, CUIRect View,
int Prop = pEditor->DoProperties(&View, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
pEditor->m_Map.m_Modified = true;
pEditor->m_Map.OnModify();
}
for(auto &pQuad : vpQuads)

View file

@ -90,6 +90,8 @@ MACRO_CONFIG_INT(ClDyncamFollowFactor, cl_dyncam_follow_factor, 60, 0, 200, CFGF
MACRO_CONFIG_INT(ClDyncamSmoothness, cl_dyncam_smoothness, 0, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_INSENSITIVE, "Transition amount of the camera movement, 0=instant, 100=slow and smooth")
MACRO_CONFIG_INT(ClDyncamStabilizing, cl_dyncam_stabilizing, 0, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_INSENSITIVE, "Amount of camera slowdown during fast cursor movement. High value can cause delay in camera movement")
MACRO_CONFIG_INT(EdAutosaveInterval, ed_autosave_interval, 10, 0, 240, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder (0 for off)")
MACRO_CONFIG_INT(EdAutosaveMax, ed_autosave_max, 10, 0, 1000, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Maximum number of autosaves that are kept per map name (0 = no limit)")
MACRO_CONFIG_INT(EdSmoothZoomTime, ed_smooth_zoom_time, 250, 0, 5000, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Time of smooth zoom animation in the editor in ms (0 for off)")
MACRO_CONFIG_INT(EdLimitMaxZoomLevel, ed_limit_max_zoom_level, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Specifies, if zooming in the editor should be limited or not (0 = no limit)")
MACRO_CONFIG_INT(EdZoomTarget, ed_zoom_target, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Zoom to the current mouse target")