Fix multiple editor undo/redo issues

Fixed crash when runing tool 'Remove unused envelopes' and trying to undo the addition of an envelope (#7738)
Fixed issues where undo/redo would not work properly when changing a layer's order or group property
Added missing action for changing the position of a sound source
This commit is contained in:
Corantin H 2024-01-14 16:49:42 +01:00
parent 6ad92edd95
commit d2ea9cbcf1
9 changed files with 298 additions and 129 deletions

View file

@ -1431,18 +1431,11 @@ static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation)
pPoint->y = (int)(x * std::sin(Rotation) + y * std::cos(Rotation) + pCenter->y);
}
void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
void CEditor::DoSoundSource(int LayerIndex, CSoundSource *pSource, int Index)
{
enum
{
OP_NONE = 0,
OP_MOVE,
OP_CONTEXT_MENU,
};
void *pID = &pSource->m_Position;
static int s_Operation = OP_NONE;
static ESoundSourceOp s_Operation = ESoundSourceOp::OP_NONE;
float wx = UI()->MouseWorldX();
float wy = UI()->MouseWorldY();
@ -1456,12 +1449,24 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
UI()->SetHotItem(pID);
const bool IgnoreGrid = Input()->AltIsPressed();
static CSoundSourceOperationTracker s_Tracker(this);
if(s_Operation == ESoundSourceOp::OP_NONE)
{
if(!UI()->MouseButton(0))
s_Tracker.End();
}
if(UI()->CheckActiveItem(pID))
{
if(s_Operation != ESoundSourceOp::OP_NONE)
{
s_Tracker.Begin(pSource, s_Operation, LayerIndex);
}
if(m_MouseDeltaWx * m_MouseDeltaWx + m_MouseDeltaWy * m_MouseDeltaWy > 0.0f)
{
if(s_Operation == OP_MOVE)
if(s_Operation == ESoundSourceOp::OP_MOVE)
{
float x = wx;
float y = wy;
@ -1472,7 +1477,7 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
}
}
if(s_Operation == OP_CONTEXT_MENU)
if(s_Operation == ESoundSourceOp::OP_CONTEXT_MENU)
{
if(!UI()->MouseButton(1))
{
@ -1482,7 +1487,7 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
UI()->DoPopupMenu(&s_PopupSourceId, UI()->MouseX(), UI()->MouseY(), 120, 200, this, PopupSource);
UI()->DisableMouseLock();
}
s_Operation = OP_NONE;
s_Operation = ESoundSourceOp::OP_NONE;
UI()->SetActiveItem(nullptr);
}
}
@ -1491,7 +1496,7 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
if(!UI()->MouseButton(0))
{
UI()->DisableMouseLock();
s_Operation = OP_NONE;
s_Operation = ESoundSourceOp::OP_NONE;
UI()->SetActiveItem(nullptr);
}
}
@ -1507,7 +1512,7 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
if(UI()->MouseButton(0))
{
s_Operation = OP_MOVE;
s_Operation = ESoundSourceOp::OP_MOVE;
UI()->SetActiveItem(pID);
m_SelectedSource = Index;
@ -1516,7 +1521,7 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
if(UI()->MouseButton(1))
{
m_SelectedSource = Index;
s_Operation = OP_CONTEXT_MENU;
s_Operation = ESoundSourceOp::OP_CONTEXT_MENU;
UI()->SetActiveItem(pID);
}
}
@ -1988,7 +1993,7 @@ void CEditor::ApplyAxisAlignment(int &OffsetX, int &OffsetY)
OffsetY = ((Axis == EAxis::AXIS_NONE || Axis == EAxis::AXIS_Y) ? OffsetY : 0);
}
void CEditor::DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int Index)
void CEditor::DoQuad(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int Index)
{
enum
{
@ -2088,7 +2093,7 @@ void CEditor::DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, i
// check if we only should move pivot
if(s_Operation == OP_MOVE_PIVOT)
{
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads);
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads, -1, LayerIndex);
s_LastOffset = GetDragOffset(); // Update offset
ApplyAxisAlignment(s_LastOffset.x, s_LastOffset.y); // Apply axis alignment to the offset
@ -2104,7 +2109,7 @@ void CEditor::DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, i
}
else if(s_Operation == OP_MOVE_ALL)
{
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads);
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads, -1, LayerIndex);
// Compute drag offset
s_LastOffset = GetDragOffset();
@ -2124,7 +2129,7 @@ void CEditor::DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, i
}
else if(s_Operation == OP_ROTATE)
{
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads);
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads, -1, LayerIndex);
for(size_t i = 0; i < m_vSelectedQuads.size(); ++i)
{
@ -2309,7 +2314,7 @@ void CEditor::DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, i
Graphics()->QuadsDraw(&QuadItem, 1);
}
void CEditor::DoQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int V)
void CEditor::DoQuadPoint(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int V)
{
void *pID = &pQuad->m_aPoints[V];
@ -2393,7 +2398,7 @@ void CEditor::DoQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQu
if(s_Operation == OP_MOVEPOINT)
{
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads);
m_QuadTracker.BeginQuadTrack(pLayer, m_vSelectedQuads, -1, LayerIndex);
s_LastOffset = GetDragOffset(); // Update offset
ApplyAxisAlignment(s_LastOffset.x, s_LastOffset.y); // Apply axis alignment to offset
@ -2416,7 +2421,7 @@ void CEditor::DoQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQu
{
int SelectedPoints = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
m_QuadTracker.BeginQuadPointPropTrack(pLayer, m_vSelectedQuads, SelectedPoints);
m_QuadTracker.BeginQuadPointPropTrack(pLayer, m_vSelectedQuads, SelectedPoints, -1, LayerIndex);
m_QuadTracker.AddQuadPointPropTrack(EQuadPointProp::PROP_TEX_U);
m_QuadTracker.AddQuadPointPropTrack(EQuadPointProp::PROP_TEX_V);
@ -3107,17 +3112,17 @@ void CEditor::DoMapEditor(CUIRect View)
static int s_Operation = OP_NONE;
// draw layer borders
std::shared_ptr<CLayer> apEditLayers[128];
std::pair<int, std::shared_ptr<CLayer>> apEditLayers[128];
size_t NumEditLayers = 0;
if(m_ShowPicker && GetSelectedLayer(0) && GetSelectedLayer(0)->m_Type == LAYERTYPE_TILES)
{
apEditLayers[0] = m_pTilesetPicker;
apEditLayers[0] = {0, m_pTilesetPicker};
NumEditLayers++;
}
else if(m_ShowPicker)
{
apEditLayers[0] = m_pQuadsetPicker;
apEditLayers[0] = {0, m_pQuadsetPicker};
NumEditLayers++;
}
else
@ -3136,8 +3141,8 @@ void CEditor::DoMapEditor(CUIRect View)
}
for(size_t i = 0; i < m_vSelectedLayers.size() && NumEditLayers < 128; i++)
{
apEditLayers[NumEditLayers] = GetSelectedLayerType(i, EditingType);
if(apEditLayers[NumEditLayers])
apEditLayers[NumEditLayers] = {m_vSelectedLayers[i], GetSelectedLayerType(i, EditingType)};
if(apEditLayers[NumEditLayers].second)
{
NumEditLayers++;
}
@ -3261,11 +3266,11 @@ void CEditor::DoMapEditor(CUIRect View)
for(size_t k = 0; k < NumEditLayers; k++)
{
size_t BrushIndex = k % m_pBrush->m_vpLayers.size();
if(apEditLayers[k]->m_Type == m_pBrush->m_vpLayers[BrushIndex]->m_Type)
if(apEditLayers[k].second->m_Type == m_pBrush->m_vpLayers[BrushIndex]->m_Type)
{
if(apEditLayers[k]->m_Type == LAYERTYPE_TILES)
if(apEditLayers[k].second->m_Type == LAYERTYPE_TILES)
{
std::shared_ptr<CLayerTiles> pLayer = std::static_pointer_cast<CLayerTiles>(apEditLayers[k]);
std::shared_ptr<CLayerTiles> pLayer = std::static_pointer_cast<CLayerTiles>(apEditLayers[k].second);
std::shared_ptr<CLayerTiles> pBrushLayer = std::static_pointer_cast<CLayerTiles>(m_pBrush->m_vpLayers[BrushIndex]);
if(pLayer->m_Tele <= pBrushLayer->m_Tele && pLayer->m_Speedup <= pBrushLayer->m_Speedup && pLayer->m_Front <= pBrushLayer->m_Front && pLayer->m_Game <= pBrushLayer->m_Game && pLayer->m_Switch <= pBrushLayer->m_Switch && pLayer->m_Tune <= pBrushLayer->m_Tune)
@ -3273,7 +3278,7 @@ void CEditor::DoMapEditor(CUIRect View)
}
else
{
apEditLayers[k]->BrushDraw(m_pBrush->m_vpLayers[BrushIndex], wx, wy);
apEditLayers[k].second->BrushDraw(m_pBrush->m_vpLayers[BrushIndex], wx, wy);
}
}
}
@ -3307,7 +3312,7 @@ void CEditor::DoMapEditor(CUIRect View)
// TODO: do all layers
int Grabs = 0;
for(size_t k = 0; k < NumEditLayers; k++)
Grabs += apEditLayers[k]->BrushGrab(m_pBrush, r);
Grabs += apEditLayers[k].second->BrushGrab(m_pBrush, r);
if(Grabs == 0)
m_pBrush->Clear();
@ -3318,7 +3323,7 @@ void CEditor::DoMapEditor(CUIRect View)
else
{
for(size_t k = 0; k < NumEditLayers; k++)
apEditLayers[k]->BrushSelecting(r);
apEditLayers[k].second->BrushSelecting(r);
UI()->MapScreen();
}
}
@ -3332,7 +3337,7 @@ void CEditor::DoMapEditor(CUIRect View)
if(m_pBrush->m_vpLayers.size() != NumEditLayers)
BrushIndex = 0;
std::shared_ptr<CLayer> pBrush = m_pBrush->IsEmpty() ? nullptr : m_pBrush->m_vpLayers[BrushIndex];
apEditLayers[k]->FillSelection(m_pBrush->IsEmpty(), pBrush, r);
apEditLayers[k].second->FillSelection(m_pBrush->IsEmpty(), pBrush, r);
}
std::shared_ptr<IEditorAction> Action = std::make_shared<CEditorBrushDrawAction>(this, m_SelectedGroup);
m_EditorHistory.RecordAction(Action);
@ -3340,7 +3345,7 @@ void CEditor::DoMapEditor(CUIRect View)
else
{
for(size_t k = 0; k < NumEditLayers; k++)
apEditLayers[k]->BrushSelecting(r);
apEditLayers[k].second->BrushSelecting(r);
UI()->MapScreen();
}
}
@ -3367,8 +3372,8 @@ void CEditor::DoMapEditor(CUIRect View)
if(m_pBrush->m_vpLayers.size() != NumEditLayers)
BrushIndex = 0;
if(apEditLayers[k]->m_Type == m_pBrush->m_vpLayers[BrushIndex]->m_Type)
apEditLayers[k]->BrushPlace(m_pBrush->m_vpLayers[BrushIndex], wx, wy);
if(apEditLayers[k].second->m_Type == m_pBrush->m_vpLayers[BrushIndex]->m_Type)
apEditLayers[k].second->BrushPlace(m_pBrush->m_vpLayers[BrushIndex], wx, wy);
}
}
@ -3427,9 +3432,11 @@ void CEditor::DoMapEditor(CUIRect View)
for(size_t k = 0; k < NumEditLayers; k++)
{
if(apEditLayers[k]->m_Type == LAYERTYPE_QUADS)
auto &[LayerIndex, pEditLayer] = apEditLayers[k];
if(pEditLayer->m_Type == LAYERTYPE_QUADS)
{
std::shared_ptr<CLayerQuads> pLayer = std::static_pointer_cast<CLayerQuads>(apEditLayers[k]);
std::shared_ptr<CLayerQuads> pLayer = std::static_pointer_cast<CLayerQuads>(pEditLayer);
if(m_ShowEnvelopePreview == SHOWENV_NONE)
m_ShowEnvelopePreview = SHOWENV_ALL;
@ -3445,23 +3452,23 @@ void CEditor::DoMapEditor(CUIRect View)
for(size_t i = 0; i < pLayer->m_vQuads.size(); i++)
{
for(int v = 0; v < 4; v++)
DoQuadPoint(pLayer, &pLayer->m_vQuads[i], i, v);
DoQuadPoint(LayerIndex, pLayer, &pLayer->m_vQuads[i], i, v);
DoQuad(pLayer, &pLayer->m_vQuads[i], i);
DoQuad(LayerIndex, pLayer, &pLayer->m_vQuads[i], i);
}
Graphics()->QuadsEnd();
}
}
if(apEditLayers[k]->m_Type == LAYERTYPE_SOUNDS)
if(pEditLayer->m_Type == LAYERTYPE_SOUNDS)
{
std::shared_ptr<CLayerSounds> pLayer = std::static_pointer_cast<CLayerSounds>(apEditLayers[k]);
std::shared_ptr<CLayerSounds> pLayer = std::static_pointer_cast<CLayerSounds>(pEditLayer);
Graphics()->TextureClear();
Graphics()->QuadsBegin();
for(size_t i = 0; i < pLayer->m_vSources.size(); i++)
{
DoSoundSource(&pLayer->m_vSources[i], i);
DoSoundSource(LayerIndex, &pLayer->m_vSources[i], i);
}
Graphics()->QuadsEnd();
}
@ -4339,12 +4346,15 @@ void CEditor::RenderLayers(CUIRect LayersBox)
else
{
std::vector<std::shared_ptr<IEditorAction>> vpActions;
for(int k = 0; k < (int)m_vSelectedLayers.size(); k++)
std::vector<int> vLayerIndices = m_vSelectedLayers;
std::sort(vLayerIndices.begin(), vLayerIndices.end());
std::sort(s_vInitialLayerIndices.begin(), s_vInitialLayerIndices.end());
for(int k = 0; k < (int)vLayerIndices.size(); k++)
{
int LayerIndex = m_vSelectedLayers[k];
int LayerIndex = vLayerIndices[k];
vpActions.push_back(std::make_shared<CEditorActionEditLayerProp>(this, m_SelectedGroup, LayerIndex, ELayerProp::PROP_ORDER, s_vInitialLayerIndices[k], LayerIndex));
}
m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(CEditorActionBulk(this, vpActions)));
m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(this, vpActions, nullptr, true));
}
s_PreviousOperation = OP_NONE;
}
@ -5870,6 +5880,8 @@ bool CEditor::IsEnvelopeUsed(int EnvelopeIndex) const
void CEditor::RemoveUnusedEnvelopes()
{
m_EnvelopeEditorHistory.BeginBulk();
int DeletedCount = 0;
for(size_t Envelope = 0; Envelope < m_Map.m_vpEnvelopes.size();)
{
if(IsEnvelopeUsed(Envelope))
@ -5878,9 +5890,14 @@ void CEditor::RemoveUnusedEnvelopes()
}
else
{
m_EnvelopeEditorHistory.RecordAction(std::make_shared<CEditorActionEveloppeDelete>(this, Envelope));
m_Map.DeleteEnvelope(Envelope);
DeletedCount++;
}
}
char aDisplay[256];
str_format(aDisplay, sizeof(aDisplay), "Tool 'Remove unused envelopes': delete %d envelopes", DeletedCount);
m_EnvelopeEditorHistory.EndBulk(aDisplay);
}
void CEditor::ZoomAdaptOffsetX(float ZoomFactor, const CUIRect &View)

View file

@ -876,14 +876,14 @@ public:
void DoQuadEnvelopes(const std::vector<CQuad> &vQuads, IGraphics::CTextureHandle Texture = IGraphics::CTextureHandle());
void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex);
void DoQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int v);
void DoQuadPoint(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int v);
void SetHotQuadPoint(const std::shared_ptr<CLayerQuads> &pLayer);
float TriangleArea(vec2 A, vec2 B, vec2 C);
bool IsInTriangle(vec2 Point, vec2 A, vec2 B, vec2 C);
void DoQuadKnife(int QuadIndex);
void DoSoundSource(CSoundSource *pSource, int Index);
void DoSoundSource(int LayerIndex, CSoundSource *pSource, int Index);
enum class EAxis
{
@ -907,7 +907,7 @@ public:
void DoMapEditor(CUIRect View);
void DoToolbarLayers(CUIRect Toolbar);
void DoToolbarSounds(CUIRect Toolbar);
void DoQuad(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int Index);
void DoQuad(int LayerIndex, const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int Index);
void PreparePointDrag(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int PointIndex);
void DoPointDrag(const std::shared_ptr<CLayerQuads> &pLayer, CQuad *pQuad, int QuadIndex, int PointIndex, int OffsetX, int OffsetY);
EAxis GetDragAxis(int OffsetX, int OffsetY);

View file

@ -794,12 +794,14 @@ void CEditorActionEditLayerProp::Apply(int Value)
if(m_Prop == ELayerProp::PROP_GROUP)
{
auto pCurrentGroup = m_pEditor->m_Map.m_vpGroups[Value == m_Previous ? m_Current : m_Previous];
auto Position = std::find(pCurrentGroup->m_vpLayers.begin(), pCurrentGroup->m_vpLayers.end(), m_pLayer);
if(Position != pCurrentGroup->m_vpLayers.end())
pCurrentGroup->m_vpLayers.erase(Position);
m_pEditor->m_Map.m_vpGroups[Value]->m_vpLayers.push_back(m_pLayer);
auto pPreviousGroup = m_pEditor->m_Map.m_vpGroups[Value];
pCurrentGroup->m_vpLayers.erase(pCurrentGroup->m_vpLayers.begin() + pCurrentGroup->m_vpLayers.size() - 1);
if(Value == m_Previous)
pPreviousGroup->m_vpLayers.insert(pPreviousGroup->m_vpLayers.begin() + m_LayerIndex, m_pLayer);
else
pPreviousGroup->m_vpLayers.push_back(m_pLayer);
m_pEditor->m_SelectedGroup = Value;
m_pEditor->SelectLayer(m_pEditor->m_Map.m_vpGroups[Value]->m_vpLayers.size() - 1);
m_pEditor->SelectLayer(m_LayerIndex);
}
else if(m_Prop == ELayerProp::PROP_HQ)
{
@ -2065,3 +2067,23 @@ void CEditorActionNewQuad::Redo()
std::shared_ptr<CLayerQuads> pLayerQuads = std::static_pointer_cast<CLayerQuads>(m_pLayer);
pLayerQuads->m_vQuads.emplace_back(m_Quad);
}
// --------------
CEditorActionMoveSoundSource::CEditorActionMoveSoundSource(CEditor *pEditor, int GroupIndex, int LayerIndex, int SourceIndex, CPoint OriginalPosition, CPoint CurrentPosition) :
CEditorActionLayerBase(pEditor, GroupIndex, LayerIndex), m_SourceIndex(SourceIndex), m_OriginalPosition(OriginalPosition), m_CurrentPosition(CurrentPosition)
{
str_format(m_aDisplayText, sizeof(m_aDisplayText), "Move sound source %d of layer %d in group %d", SourceIndex, LayerIndex, GroupIndex);
}
void CEditorActionMoveSoundSource::Undo()
{
dbg_assert(m_pLayer->m_Type == LAYERTYPE_SOUNDS, "Layer type does not match a sound layer");
std::static_pointer_cast<CLayerSounds>(m_pLayer)->m_vSources[m_SourceIndex].m_Position = m_OriginalPosition;
}
void CEditorActionMoveSoundSource::Redo()
{
dbg_assert(m_pLayer->m_Type == LAYERTYPE_SOUNDS, "Layer type does not match a sound layer");
std::static_pointer_cast<CLayerSounds>(m_pLayer)->m_vSources[m_SourceIndex].m_Position = m_CurrentPosition;
}

View file

@ -645,4 +645,18 @@ private:
CQuad m_Quad;
};
class CEditorActionMoveSoundSource : public CEditorActionLayerBase
{
public:
CEditorActionMoveSoundSource(CEditor *pEditor, int GroupIndex, int LayerIndex, int SourceIndex, CPoint OriginalPosition, CPoint CurrentPosition);
void Undo() override;
void Redo() override;
private:
int m_SourceIndex;
CPoint m_OriginalPosition;
CPoint m_CurrentPosition;
};
#endif

View file

@ -17,6 +17,12 @@ void CEditorHistory::Execute(const std::shared_ptr<IEditorAction> &pAction, cons
void CEditorHistory::RecordAction(const std::shared_ptr<IEditorAction> &pAction, const char *pDisplay)
{
if(m_IsBulk)
{
m_vpBulkActions.push_back(pAction);
return;
}
m_vpRedoActions.clear();
if((int)m_vpUndoActions.size() >= g_Config.m_ClEditorMaxHistory)
@ -63,3 +69,22 @@ void CEditorHistory::Clear()
m_vpUndoActions.clear();
m_vpRedoActions.clear();
}
void CEditorHistory::BeginBulk()
{
m_IsBulk = true;
m_vpBulkActions.clear();
}
void CEditorHistory::EndBulk(const char *pDisplay)
{
if(!m_IsBulk)
return;
m_IsBulk = false;
// Record bulk action
if(!m_vpBulkActions.empty())
RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, m_vpBulkActions, pDisplay, true));
m_vpBulkActions.clear();
}

View file

@ -11,6 +11,7 @@ public:
CEditorHistory()
{
m_pEditor = nullptr;
m_IsBulk = false;
}
~CEditorHistory()
@ -29,9 +30,16 @@ public:
bool CanUndo() const { return !m_vpUndoActions.empty(); }
bool CanRedo() const { return !m_vpRedoActions.empty(); }
void BeginBulk();
void EndBulk(const char *pDisplay = nullptr);
CEditor *m_pEditor;
std::deque<std::shared_ptr<IEditorAction>> m_vpUndoActions;
std::deque<std::shared_ptr<IEditorAction>> m_vpRedoActions;
private:
std::vector<std::shared_ptr<IEditorAction>> m_vpBulkActions;
bool m_IsBulk;
};
#endif

View file

@ -15,13 +15,15 @@ CQuadEditTracker::~CQuadEditTracker()
m_vSelectedQuads.clear();
}
void CQuadEditTracker::BeginQuadTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads)
void CQuadEditTracker::BeginQuadTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int GroupIndex, int LayerIndex)
{
if(m_Tracking)
return;
m_Tracking = true;
m_vSelectedQuads.clear();
m_pLayer = pLayer;
m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
// Init all points
for(auto QuadIndex : vSelectedQuads)
{
@ -37,26 +39,25 @@ void CQuadEditTracker::EndQuadTrack()
return;
m_Tracking = false;
int GroupIndex = m_pEditor->m_SelectedGroup;
int LayerIndex = m_pEditor->m_vSelectedLayers[0];
// Record all moved stuff
std::vector<std::shared_ptr<IEditorAction>> vpActions;
for(auto QuadIndex : m_vSelectedQuads)
{
auto &pQuad = m_pLayer->m_vQuads[QuadIndex];
auto vCurrentPoints = std::vector<CPoint>(pQuad.m_aPoints, pQuad.m_aPoints + 5);
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
}
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions));
}
void CQuadEditTracker::BeginQuadPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, EQuadProp Prop)
void CQuadEditTracker::BeginQuadPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, EQuadProp Prop, int GroupIndex, int LayerIndex)
{
if(m_TrackedProp != EQuadProp::PROP_NONE)
return;
m_TrackedProp = Prop;
m_pLayer = pLayer;
m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
m_vSelectedQuads = vSelectedQuads;
m_PreviousValues.clear();
@ -83,16 +84,13 @@ void CQuadEditTracker::EndQuadPropTrack(EQuadProp Prop)
std::vector<std::shared_ptr<IEditorAction>> vpActions;
int GroupIndex = m_pEditor->m_SelectedGroup;
int LayerIndex = m_pEditor->m_vSelectedLayers[0];
for(auto QuadIndex : m_vSelectedQuads)
{
auto &Quad = m_pLayer->m_vQuads[QuadIndex];
if(Prop == EQuadProp::PROP_POS_X || Prop == EQuadProp::PROP_POS_Y)
{
auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
}
else
{
@ -107,7 +105,7 @@ void CQuadEditTracker::EndQuadPropTrack(EQuadProp Prop)
Value = Quad.m_ColorEnvOffset;
if(Value != m_PreviousValues[QuadIndex])
vpActions.push_back(std::make_shared<CEditorActionEditQuadProp>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, Prop, m_PreviousValues[QuadIndex], Value));
vpActions.push_back(std::make_shared<CEditorActionEditQuadProp>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, Prop, m_PreviousValues[QuadIndex], Value));
}
}
@ -115,12 +113,14 @@ void CQuadEditTracker::EndQuadPropTrack(EQuadProp Prop)
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionBulk>(m_pEditor, vpActions));
}
void CQuadEditTracker::BeginQuadPointPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int SelectedQuadPoints)
void CQuadEditTracker::BeginQuadPointPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int SelectedQuadPoints, int GroupIndex, int LayerIndex)
{
if(!m_vTrackedProps.empty())
return;
m_pLayer = pLayer;
m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
m_SelectedQuadPoints = SelectedQuadPoints;
m_vSelectedQuads = vSelectedQuads;
m_PreviousValuesPoint.clear();
@ -187,16 +187,13 @@ void CQuadEditTracker::EndQuadPointPropTrack(EQuadPointProp Prop)
std::vector<std::shared_ptr<IEditorAction>> vpActions;
int GroupIndex = m_pEditor->m_SelectedGroup;
int LayerIndex = m_pEditor->m_vSelectedLayers[0];
for(auto QuadIndex : m_vSelectedQuads)
{
auto &Quad = m_pLayer->m_vQuads[QuadIndex];
if(Prop == EQuadPointProp::PROP_POS_X || Prop == EQuadPointProp::PROP_POS_Y)
{
auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
}
else
{
@ -219,7 +216,7 @@ void CQuadEditTracker::EndQuadPointPropTrack(EQuadPointProp Prop)
}
if(Value != m_PreviousValuesPoint[QuadIndex][v][Prop])
vpActions.push_back(std::make_shared<CEditorActionEditQuadPointProp>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, v, Prop, m_PreviousValuesPoint[QuadIndex][v][Prop], Value));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPointProp>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, v, Prop, m_PreviousValuesPoint[QuadIndex][v][Prop], Value));
}
}
}
@ -234,16 +231,13 @@ void CQuadEditTracker::EndQuadPointPropTrackAll()
std::vector<std::shared_ptr<IEditorAction>> vpActions;
for(auto &Prop : m_vTrackedProps)
{
int GroupIndex = m_pEditor->m_SelectedGroup;
int LayerIndex = m_pEditor->m_vSelectedLayers[0];
for(auto QuadIndex : m_vSelectedQuads)
{
auto &Quad = m_pLayer->m_vQuads[QuadIndex];
if(Prop == EQuadPointProp::PROP_POS_X || Prop == EQuadPointProp::PROP_POS_Y)
{
auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPoint>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, m_InitalPoints[QuadIndex], vCurrentPoints));
}
else
{
@ -266,7 +260,7 @@ void CQuadEditTracker::EndQuadPointPropTrackAll()
}
if(Value != m_PreviousValuesPoint[QuadIndex][v][Prop])
vpActions.push_back(std::make_shared<CEditorActionEditQuadPointProp>(m_pEditor, GroupIndex, LayerIndex, QuadIndex, v, Prop, m_PreviousValuesPoint[QuadIndex][v][Prop], Value));
vpActions.push_back(std::make_shared<CEditorActionEditQuadPointProp>(m_pEditor, m_GroupIndex, m_LayerIndex, QuadIndex, v, Prop, m_PreviousValuesPoint[QuadIndex][v][Prop], Value));
}
}
}
@ -279,22 +273,6 @@ void CQuadEditTracker::EndQuadPointPropTrackAll()
m_vTrackedProps.clear();
}
void CEditorPropTracker::BeginPropTrack(int Prop, int Value)
{
if(m_TrackedProp != -1 || m_TrackedProp == Prop)
return;
m_TrackedProp = Prop;
m_PreviousValue = Value;
}
void CEditorPropTracker::StopPropTrack(int Prop, int Value)
{
if(Prop != m_TrackedProp)
return;
m_TrackedProp = -1;
m_CurrentValue = Value;
}
// -----------------------------
void CEnvelopeEditorOperationTracker::Begin(EEnvelopeEditorOp Operation)
@ -385,20 +363,81 @@ void CEnvelopeEditorOperationTracker::HandlePointDragEnd(bool Switch)
m_SavedValues.clear();
}
// -----------------------------------------------------------------------
CSoundSourceOperationTracker::CSoundSourceOperationTracker(CEditor *pEditor) :
m_pEditor(pEditor), m_pSource(nullptr), m_TrackedOp(ESoundSourceOp::OP_NONE), m_LayerIndex(-1)
{
}
void CSoundSourceOperationTracker::Begin(CSoundSource *pSource, ESoundSourceOp Operation, int LayerIndex)
{
if(m_TrackedOp == Operation || m_TrackedOp != ESoundSourceOp::OP_NONE)
return;
m_TrackedOp = Operation;
m_pSource = pSource;
m_LayerIndex = LayerIndex;
if(m_TrackedOp == ESoundSourceOp::OP_MOVE)
HandlePointMove(EState::STATE_BEGIN);
}
void CSoundSourceOperationTracker::End()
{
if(m_TrackedOp == ESoundSourceOp::OP_NONE)
return;
if(m_TrackedOp == ESoundSourceOp::OP_MOVE)
HandlePointMove(EState::STATE_END);
m_TrackedOp = ESoundSourceOp::OP_NONE;
}
void CSoundSourceOperationTracker::HandlePointMove(EState State)
{
if(State == EState::STATE_BEGIN)
{
m_Data.m_OriginalPoint = m_pSource->m_Position;
}
else if(State == EState::STATE_END)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionMoveSoundSource>(m_pEditor, m_pEditor->m_SelectedGroup, m_LayerIndex, m_pEditor->m_SelectedSource, m_Data.m_OriginalPoint, m_pSource->m_Position));
}
}
// -----------------------------------------------------------------------
int SPropTrackerHelper::GetDefaultGroupIndex(CEditor *pEditor)
{
return pEditor->m_SelectedGroup;
}
int SPropTrackerHelper::GetDefaultLayerIndex(CEditor *pEditor)
{
return pEditor->m_vSelectedLayers[0];
}
// -----------------------------------------------------------------------
void CLayerPropTracker::OnEnd(ELayerProp Prop, int Value)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditLayerProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], Prop, m_OriginalValue, Value));
if(Prop == ELayerProp::PROP_GROUP)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditLayersGroupAndOrder>(m_pEditor, m_OriginalGroupIndex, std::vector<int>{m_OriginalLayerIndex}, m_CurrentGroupIndex, std::vector<int>{m_CurrentLayerIndex}));
}
else
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditLayerProp>(m_pEditor, m_CurrentGroupIndex, m_CurrentLayerIndex, Prop, m_OriginalValue, Value));
}
}
int CLayerPropTracker::PropToValue(ELayerProp Prop)
{
switch(Prop)
{
case ELayerProp::PROP_GROUP: return m_pEditor->m_SelectedGroup;
case ELayerProp::PROP_GROUP: return m_CurrentGroupIndex;
case ELayerProp::PROP_HQ: return m_pObject->m_Flags;
case ELayerProp::PROP_ORDER: return m_pEditor->m_vSelectedLayers[0];
case ELayerProp::PROP_ORDER: return m_CurrentLayerIndex;
default: return 0;
}
}
@ -439,7 +478,7 @@ void CLayerTilesPropTracker::OnStart(ETilesProp Prop)
void CLayerTilesPropTracker::OnEnd(ETilesProp Prop, int Value)
{
auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], Prop, m_OriginalValue, Value);
auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, Prop, m_OriginalValue, Value);
pAction->SetSavedLayers(m_SavedLayers);
m_SavedLayers.clear();
@ -490,7 +529,7 @@ void CLayerTilesCommonPropTracker::OnEnd(ETilesCommonProp Prop, int Value)
for(auto &pLayer : m_vpLayers)
{
int LayerIndex = m_vLayerIndices[j++];
auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_pEditor->m_SelectedGroup, LayerIndex, s_PropMap[Prop], m_OriginalValue, Value);
auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(m_pEditor, m_OriginalGroupIndex, LayerIndex, s_PropMap[Prop], m_OriginalValue, Value);
pAction->SetSavedLayers(m_SavedLayers[pLayer]);
vpActions.push_back(pAction);
}
@ -549,7 +588,7 @@ int CLayerGroupPropTracker::PropToValue(EGroupProp Prop)
void CLayerQuadsPropTracker::OnEnd(ELayerQuadsProp Prop, int Value)
{
auto pAction = std::make_shared<CEditorActionEditLayerQuadsProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], Prop, m_OriginalValue, Value);
auto pAction = std::make_shared<CEditorActionEditLayerQuadsProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, Prop, m_OriginalValue, Value);
m_pEditor->m_EditorHistory.RecordAction(pAction);
}
@ -564,7 +603,7 @@ int CLayerQuadsPropTracker::PropToValue(ELayerQuadsProp Prop)
void CLayerSoundsPropTracker::OnEnd(ELayerSoundsProp Prop, int Value)
{
auto pAction = std::make_shared<CEditorActionEditLayerSoundsProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], Prop, m_OriginalValue, Value);
auto pAction = std::make_shared<CEditorActionEditLayerSoundsProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, Prop, m_OriginalValue, Value);
m_pEditor->m_EditorHistory.RecordAction(pAction);
}
@ -579,7 +618,7 @@ int CLayerSoundsPropTracker::PropToValue(ELayerSoundsProp Prop)
void CSoundSourcePropTracker::OnEnd(ESoundProp Prop, int Value)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditSoundSourceProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditSoundSourceProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
}
int CSoundSourcePropTracker::PropToValue(ESoundProp Prop)
@ -604,7 +643,7 @@ int CSoundSourcePropTracker::PropToValue(ESoundProp Prop)
void CSoundSourceRectShapePropTracker::OnEnd(ERectangleShapeProp Prop, int Value)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditRectSoundSourceShapeProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditRectSoundSourceShapeProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
}
int CSoundSourceRectShapePropTracker::PropToValue(ERectangleShapeProp Prop)
@ -619,7 +658,7 @@ int CSoundSourceRectShapePropTracker::PropToValue(ERectangleShapeProp Prop)
void CSoundSourceCircleShapePropTracker::OnEnd(ECircleShapeProp Prop, int Value)
{
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditCircleSoundSourceShapeProp>(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_vSelectedLayers[0], m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
m_pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionEditCircleSoundSourceShapeProp>(m_pEditor, m_OriginalGroupIndex, m_OriginalLayerIndex, m_pEditor->m_SelectedSource, Prop, m_OriginalValue, Value));
}
int CSoundSourceCircleShapePropTracker::PropToValue(ECircleShapeProp Prop)

View file

@ -21,13 +21,13 @@ public:
CQuadEditTracker();
~CQuadEditTracker();
void BeginQuadTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads);
void BeginQuadTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int GroupIndex = -1, int LayerIndex = -1);
void EndQuadTrack();
void BeginQuadPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, EQuadProp Prop);
void BeginQuadPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, EQuadProp Prop, int GroupIndex = -1, int LayerIndex = -1);
void EndQuadPropTrack(EQuadProp Prop);
void BeginQuadPointPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int SelectedQuadPoints);
void BeginQuadPointPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int SelectedQuadPoints, int GroupIndex = -1, int LayerIndex = -1);
void AddQuadPointPropTrack(EQuadPointProp Prop);
void EndQuadPointPropTrack(EQuadPointProp Prop);
void EndQuadPointPropTrackAll();
@ -46,23 +46,8 @@ private:
std::vector<EQuadPointProp> m_vTrackedProps;
std::map<int, int> m_PreviousValues;
std::map<int, std::vector<std::map<EQuadPointProp, int>>> m_PreviousValuesPoint;
};
class CEditorPropTracker
{
public:
CEditorPropTracker() = default;
void BeginPropTrack(int Prop, int Value);
void StopPropTrack(int Prop, int Value);
inline void Reset() { m_TrackedProp = -1; }
CEditor *m_pEditor;
int m_PreviousValue;
int m_CurrentValue;
private:
int m_TrackedProp = -1;
int m_LayerIndex;
int m_GroupIndex;
};
enum class EEnvelopeEditorOp
@ -77,6 +62,13 @@ enum class EEnvelopeEditorOp
OP_SCALE
};
enum class ESoundSourceOp
{
OP_NONE = 0,
OP_MOVE,
OP_CONTEXT_MENU,
};
class CEnvelopeEditorOperationTracker
{
public:
@ -104,34 +96,81 @@ private:
void HandlePointDragEnd(bool Switch);
};
class CSoundSourceOperationTracker
{
public:
CSoundSourceOperationTracker(CEditor *pEditor);
void Begin(CSoundSource *pSource, ESoundSourceOp Operation, int LayerIndex);
void End();
private:
CEditor *m_pEditor;
CSoundSource *m_pSource;
ESoundSourceOp m_TrackedOp;
int m_LayerIndex;
struct SData
{
CPoint m_OriginalPoint;
};
SData m_Data;
enum EState
{
STATE_BEGIN,
STATE_EDITING,
STATE_END
};
void HandlePointMove(EState State);
};
struct SPropTrackerHelper
{
static int GetDefaultGroupIndex(CEditor *pEditor);
static int GetDefaultLayerIndex(CEditor *pEditor);
};
template<typename T, typename E>
class CPropTracker
{
public:
CPropTracker(CEditor *pEditor) :
m_pEditor(pEditor), m_OriginalValue(0) {}
m_pEditor(pEditor), m_OriginalValue(0), m_pObject(nullptr), m_OriginalLayerIndex(-1), m_OriginalGroupIndex(-1), m_CurrentLayerIndex(-1), m_CurrentGroupIndex(-1), m_Tracking(false) {}
CEditor *m_pEditor;
void Begin(T *pObject, E Prop, EEditState State)
void Begin(T *pObject, E Prop, EEditState State, int GroupIndex = -1, int LayerIndex = -1)
{
if(Prop == static_cast<E>(-1))
if(m_Tracking || Prop == static_cast<E>(-1))
return;
m_pObject = pObject;
m_OriginalGroupIndex = GroupIndex < 0 ? SPropTrackerHelper::GetDefaultGroupIndex(m_pEditor) : GroupIndex;
m_OriginalLayerIndex = LayerIndex < 0 ? SPropTrackerHelper::GetDefaultLayerIndex(m_pEditor) : LayerIndex;
m_CurrentGroupIndex = m_OriginalGroupIndex;
m_CurrentLayerIndex = m_OriginalLayerIndex;
int Value = PropToValue(Prop);
if(StartChecker(Prop, State, Value))
{
m_Tracking = true;
m_OriginalValue = Value;
OnStart(Prop);
}
}
void End(E Prop, EEditState State)
void End(E Prop, EEditState State, int GroupIndex = -1, int LayerIndex = -1)
{
if(Prop == static_cast<E>(-1))
if(!m_Tracking || Prop == static_cast<E>(-1))
return;
m_CurrentGroupIndex = GroupIndex < 0 ? SPropTrackerHelper::GetDefaultGroupIndex(m_pEditor) : GroupIndex;
m_CurrentLayerIndex = LayerIndex < 0 ? SPropTrackerHelper::GetDefaultLayerIndex(m_pEditor) : LayerIndex;
int Value = PropToValue(Prop);
if(EndChecker(Prop, State, Value))
{
m_Tracking = false;
OnEnd(Prop, Value);
}
}
@ -151,6 +190,11 @@ protected:
int m_OriginalValue;
T *m_pObject;
int m_OriginalLayerIndex;
int m_OriginalGroupIndex;
int m_CurrentLayerIndex;
int m_CurrentGroupIndex;
bool m_Tracking;
};
class CLayerPropTracker : public CPropTracker<CLayer, ELayerProp>

View file

@ -782,7 +782,7 @@ CUI::EPopupMenuFunctionResult CEditor::PopupLayer(void *pContext, CUIRect View,
}
else if(Prop == ELayerProp::PROP_GROUP)
{
if(NewVal >= 0 && (size_t)NewVal < pEditor->m_Map.m_vpGroups.size())
if(NewVal >= 0 && (size_t)NewVal < pEditor->m_Map.m_vpGroups.size() && NewVal != pEditor->m_SelectedGroup)
{
auto Position = std::find(pCurrentGroup->m_vpLayers.begin(), pCurrentGroup->m_vpLayers.end(), pCurrentLayer);
if(Position != pCurrentGroup->m_vpLayers.end())