1#include "editor_trackers.h"
2
3#include <game/editor/mapitems/layer_group.h>
4#include <game/editor/mapitems/layer_tiles.h>
5
6#include "editor.h"
7#include "editor_actions.h"
8
9CQuadEditTracker::CQuadEditTracker() :
10 m_pEditor(nullptr), m_TrackedProp(EQuadProp::PROP_NONE) {}
11
12CQuadEditTracker::~CQuadEditTracker()
13{
14 m_InitalPoints.clear();
15 m_vSelectedQuads.clear();
16}
17
18void CQuadEditTracker::BeginQuadTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int GroupIndex, int LayerIndex)
19{
20 if(m_Tracking)
21 return;
22 m_Tracking = true;
23 m_vSelectedQuads.clear();
24 m_pLayer = pLayer;
25 m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
26 m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
27 // Init all points
28 for(auto QuadIndex : vSelectedQuads)
29 {
30 auto &pQuad = pLayer->m_vQuads[QuadIndex];
31 m_InitalPoints[QuadIndex] = std::vector<CPoint>(pQuad.m_aPoints, pQuad.m_aPoints + 5);
32 m_vSelectedQuads.push_back(x: QuadIndex);
33 }
34}
35
36void CQuadEditTracker::EndQuadTrack()
37{
38 if(!m_Tracking)
39 return;
40 m_Tracking = false;
41
42 // Record all moved stuff
43 std::vector<std::shared_ptr<IEditorAction>> vpActions;
44 for(auto QuadIndex : m_vSelectedQuads)
45 {
46 auto &pQuad = m_pLayer->m_vQuads[QuadIndex];
47 auto vCurrentPoints = std::vector<CPoint>(pQuad.m_aPoints, pQuad.m_aPoints + 5);
48 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPoint>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: m_InitalPoints[QuadIndex], args&: vCurrentPoints));
49 }
50 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions));
51}
52
53void CQuadEditTracker::BeginQuadPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, EQuadProp Prop, int GroupIndex, int LayerIndex)
54{
55 if(m_TrackedProp != EQuadProp::PROP_NONE)
56 return;
57 m_TrackedProp = Prop;
58 m_pLayer = pLayer;
59 m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
60 m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
61 m_vSelectedQuads = vSelectedQuads;
62 m_PreviousValues.clear();
63
64 for(auto QuadIndex : vSelectedQuads)
65 {
66 auto &Quad = pLayer->m_vQuads[QuadIndex];
67 if(Prop == EQuadProp::PROP_POS_X || Prop == EQuadProp::PROP_POS_Y)
68 m_InitalPoints[QuadIndex] = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
69 else if(Prop == EQuadProp::PROP_POS_ENV)
70 m_PreviousValues[QuadIndex] = Quad.m_PosEnv;
71 else if(Prop == EQuadProp::PROP_POS_ENV_OFFSET)
72 m_PreviousValues[QuadIndex] = Quad.m_PosEnvOffset;
73 else if(Prop == EQuadProp::PROP_COLOR_ENV)
74 m_PreviousValues[QuadIndex] = Quad.m_ColorEnv;
75 else if(Prop == EQuadProp::PROP_COLOR_ENV_OFFSET)
76 m_PreviousValues[QuadIndex] = Quad.m_ColorEnvOffset;
77 }
78}
79void CQuadEditTracker::EndQuadPropTrack(EQuadProp Prop)
80{
81 if(m_TrackedProp != Prop)
82 return;
83 m_TrackedProp = EQuadProp::PROP_NONE;
84
85 std::vector<std::shared_ptr<IEditorAction>> vpActions;
86
87 for(auto QuadIndex : m_vSelectedQuads)
88 {
89 auto &Quad = m_pLayer->m_vQuads[QuadIndex];
90 if(Prop == EQuadProp::PROP_POS_X || Prop == EQuadProp::PROP_POS_Y)
91 {
92 auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
93 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPoint>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: m_InitalPoints[QuadIndex], args&: vCurrentPoints));
94 }
95 else
96 {
97 int Value = 0;
98 if(Prop == EQuadProp::PROP_POS_ENV)
99 Value = Quad.m_PosEnv;
100 else if(Prop == EQuadProp::PROP_POS_ENV_OFFSET)
101 Value = Quad.m_PosEnvOffset;
102 else if(Prop == EQuadProp::PROP_COLOR_ENV)
103 Value = Quad.m_ColorEnv;
104 else if(Prop == EQuadProp::PROP_COLOR_ENV_OFFSET)
105 Value = Quad.m_ColorEnvOffset;
106
107 if(Value != m_PreviousValues[QuadIndex])
108 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadProp>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: Prop, args&: m_PreviousValues[QuadIndex], args&: Value));
109 }
110 }
111
112 if(!vpActions.empty())
113 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions));
114}
115
116void CQuadEditTracker::BeginQuadPointPropTrack(const std::shared_ptr<CLayerQuads> &pLayer, const std::vector<int> &vSelectedQuads, int SelectedQuadPoints, int GroupIndex, int LayerIndex)
117{
118 if(!m_vTrackedProps.empty())
119 return;
120
121 m_pLayer = pLayer;
122 m_GroupIndex = GroupIndex < 0 ? m_pEditor->m_SelectedGroup : GroupIndex;
123 m_LayerIndex = LayerIndex < 0 ? m_pEditor->m_vSelectedLayers[0] : LayerIndex;
124 m_SelectedQuadPoints = SelectedQuadPoints;
125 m_vSelectedQuads = vSelectedQuads;
126 m_PreviousValuesPoint.clear();
127
128 for(auto QuadIndex : vSelectedQuads)
129 {
130 m_PreviousValuesPoint[QuadIndex] = std::vector<std::map<EQuadPointProp, int>>(4);
131 }
132}
133
134void CQuadEditTracker::AddQuadPointPropTrack(EQuadPointProp Prop)
135{
136 if(std::find(first: m_vTrackedProps.begin(), last: m_vTrackedProps.end(), val: Prop) != m_vTrackedProps.end())
137 return;
138
139 m_vTrackedProps.push_back(x: Prop);
140
141 for(auto QuadIndex : m_vSelectedQuads)
142 {
143 auto &Quad = m_pLayer->m_vQuads[QuadIndex];
144 if(Prop == EQuadPointProp::PROP_POS_X || Prop == EQuadPointProp::PROP_POS_Y)
145 m_InitalPoints[QuadIndex] = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
146 else if(Prop == EQuadPointProp::PROP_COLOR)
147 {
148 for(int v = 0; v < 4; v++)
149 {
150 if(m_SelectedQuadPoints & (1 << v))
151 {
152 int Color = PackColor(Color: Quad.m_aColors[v]);
153 m_PreviousValuesPoint[QuadIndex][v][Prop] = Color;
154 }
155 }
156 }
157 else if(Prop == EQuadPointProp::PROP_TEX_U)
158 {
159 for(int v = 0; v < 4; v++)
160 {
161 if(m_SelectedQuadPoints & (1 << v))
162 {
163 m_PreviousValuesPoint[QuadIndex][v][Prop] = Quad.m_aTexcoords[v].x;
164 }
165 }
166 }
167 else if(Prop == EQuadPointProp::PROP_TEX_V)
168 {
169 for(int v = 0; v < 4; v++)
170 {
171 if(m_SelectedQuadPoints & (1 << v))
172 {
173 m_PreviousValuesPoint[QuadIndex][v][Prop] = Quad.m_aTexcoords[v].y;
174 }
175 }
176 }
177 }
178}
179
180void CQuadEditTracker::EndQuadPointPropTrack(EQuadPointProp Prop)
181{
182 auto It = std::find(first: m_vTrackedProps.begin(), last: m_vTrackedProps.end(), val: Prop);
183 if(It == m_vTrackedProps.end())
184 return;
185
186 m_vTrackedProps.erase(position: It);
187
188 std::vector<std::shared_ptr<IEditorAction>> vpActions;
189
190 for(auto QuadIndex : m_vSelectedQuads)
191 {
192 auto &Quad = m_pLayer->m_vQuads[QuadIndex];
193 if(Prop == EQuadPointProp::PROP_POS_X || Prop == EQuadPointProp::PROP_POS_Y)
194 {
195 auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
196 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPoint>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: m_InitalPoints[QuadIndex], args&: vCurrentPoints));
197 }
198 else
199 {
200 int Value = 0;
201 for(int v = 0; v < 4; v++)
202 {
203 if(m_SelectedQuadPoints & (1 << v))
204 {
205 if(Prop == EQuadPointProp::PROP_COLOR)
206 {
207 Value = PackColor(Color: Quad.m_aColors[v]);
208 }
209 else if(Prop == EQuadPointProp::PROP_TEX_U)
210 {
211 Value = Quad.m_aTexcoords[v].x;
212 }
213 else if(Prop == EQuadPointProp::PROP_TEX_V)
214 {
215 Value = Quad.m_aTexcoords[v].y;
216 }
217
218 if(Value != m_PreviousValuesPoint[QuadIndex][v][Prop])
219 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPointProp>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: v, args&: Prop, args&: m_PreviousValuesPoint[QuadIndex][v][Prop], args&: Value));
220 }
221 }
222 }
223 }
224
225 if(!vpActions.empty())
226 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions));
227}
228
229void CQuadEditTracker::EndQuadPointPropTrackAll()
230{
231 std::vector<std::shared_ptr<IEditorAction>> vpActions;
232 for(auto &Prop : m_vTrackedProps)
233 {
234 for(auto QuadIndex : m_vSelectedQuads)
235 {
236 auto &Quad = m_pLayer->m_vQuads[QuadIndex];
237 if(Prop == EQuadPointProp::PROP_POS_X || Prop == EQuadPointProp::PROP_POS_Y)
238 {
239 auto vCurrentPoints = std::vector<CPoint>(Quad.m_aPoints, Quad.m_aPoints + 5);
240 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPoint>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: m_InitalPoints[QuadIndex], args&: vCurrentPoints));
241 }
242 else
243 {
244 int Value = 0;
245 for(int v = 0; v < 4; v++)
246 {
247 if(m_SelectedQuadPoints & (1 << v))
248 {
249 if(Prop == EQuadPointProp::PROP_COLOR)
250 {
251 Value = PackColor(Color: Quad.m_aColors[v]);
252 }
253 else if(Prop == EQuadPointProp::PROP_TEX_U)
254 {
255 Value = Quad.m_aTexcoords[v].x;
256 }
257 else if(Prop == EQuadPointProp::PROP_TEX_V)
258 {
259 Value = Quad.m_aTexcoords[v].y;
260 }
261
262 if(Value != m_PreviousValuesPoint[QuadIndex][v][Prop])
263 vpActions.push_back(x: std::make_shared<CEditorActionEditQuadPointProp>(args&: m_pEditor, args&: m_GroupIndex, args&: m_LayerIndex, args&: QuadIndex, args&: v, args&: Prop, args&: m_PreviousValuesPoint[QuadIndex][v][Prop], args&: Value));
264 }
265 }
266 }
267 }
268 }
269
270 if(!vpActions.empty())
271 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions));
272
273 m_vTrackedProps.clear();
274}
275
276// -----------------------------
277
278void CEnvelopeEditorOperationTracker::Begin(EEnvelopeEditorOp Operation)
279{
280 if(m_TrackedOp == Operation)
281 return;
282
283 if(m_TrackedOp != EEnvelopeEditorOp::OP_NONE)
284 {
285 Stop(Switch: true);
286 }
287
288 m_TrackedOp = Operation;
289
290 if(Operation == EEnvelopeEditorOp::OP_DRAG_POINT || Operation == EEnvelopeEditorOp::OP_DRAG_POINT_X || Operation == EEnvelopeEditorOp::OP_DRAG_POINT_Y || Operation == EEnvelopeEditorOp::OP_SCALE)
291 {
292 HandlePointDragStart();
293 }
294}
295
296void CEnvelopeEditorOperationTracker::Stop(bool Switch)
297{
298 if(m_TrackedOp == EEnvelopeEditorOp::OP_NONE)
299 return;
300
301 if(m_TrackedOp == EEnvelopeEditorOp::OP_DRAG_POINT || m_TrackedOp == EEnvelopeEditorOp::OP_DRAG_POINT_X || m_TrackedOp == EEnvelopeEditorOp::OP_DRAG_POINT_Y || m_TrackedOp == EEnvelopeEditorOp::OP_SCALE)
302 {
303 HandlePointDragEnd(Switch);
304 }
305
306 m_TrackedOp = EEnvelopeEditorOp::OP_NONE;
307}
308
309void CEnvelopeEditorOperationTracker::HandlePointDragStart()
310{
311 // Figure out which points are selected and which channels
312 // Save their X and Y position (time and value)
313 auto pEnv = m_pEditor->m_Map.m_vpEnvelopes[m_pEditor->m_SelectedEnvelope];
314
315 for(auto [PointIndex, Channel] : m_pEditor->m_vSelectedEnvelopePoints)
316 {
317 auto &Point = pEnv->m_vPoints[PointIndex];
318 auto &Data = m_SavedValues[PointIndex];
319 Data.m_Values[Channel] = Point.m_aValues[Channel];
320 if(Data.m_Used)
321 continue;
322 Data.m_Time = Point.m_Time;
323 Data.m_Used = true;
324 }
325}
326
327void CEnvelopeEditorOperationTracker::HandlePointDragEnd(bool Switch)
328{
329 if(Switch && m_TrackedOp != EEnvelopeEditorOp::OP_SCALE)
330 return;
331
332 int EnvIndex = m_pEditor->m_SelectedEnvelope;
333 auto pEnv = m_pEditor->m_Map.m_vpEnvelopes[EnvIndex];
334 std::vector<std::shared_ptr<IEditorAction>> vpActions;
335
336 for(auto const &Entry : m_SavedValues)
337 {
338 int PointIndex = Entry.first;
339 auto &Point = pEnv->m_vPoints[PointIndex];
340 const auto &Data = Entry.second;
341
342 if(Data.m_Time != Point.m_Time)
343 { // Save time
344 vpActions.push_back(x: std::make_shared<CEditorActionEnvelopeEditPoint>(args&: m_pEditor, args&: EnvIndex, args&: PointIndex, args: 0, args: CEditorActionEnvelopeEditPoint::EEditType::TIME, args: Data.m_Time, args&: Point.m_Time));
345 }
346
347 for(auto Value : Data.m_Values)
348 {
349 // Value.second is the saved value, Value.first is the channel
350 int Channel = Value.first;
351 if(Value.second != Point.m_aValues[Channel])
352 { // Save value
353 vpActions.push_back(x: std::make_shared<CEditorActionEnvelopeEditPoint>(args&: m_pEditor, args&: EnvIndex, args&: PointIndex, args&: Channel, args: CEditorActionEnvelopeEditPoint::EEditType::VALUE, args&: Value.second, args&: Point.m_aValues[Channel]));
354 }
355 }
356 }
357
358 if(!vpActions.empty())
359 {
360 m_pEditor->m_EnvelopeEditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions, args: "Envelope point drag"));
361 }
362
363 m_SavedValues.clear();
364}
365
366// -----------------------------------------------------------------------
367CSoundSourceOperationTracker::CSoundSourceOperationTracker(CEditor *pEditor) :
368 m_pEditor(pEditor), m_pSource(nullptr), m_TrackedOp(ESoundSourceOp::OP_NONE), m_LayerIndex(-1)
369{
370}
371
372void CSoundSourceOperationTracker::Begin(CSoundSource *pSource, ESoundSourceOp Operation, int LayerIndex)
373{
374 if(m_TrackedOp == Operation || m_TrackedOp != ESoundSourceOp::OP_NONE)
375 return;
376
377 m_TrackedOp = Operation;
378 m_pSource = pSource;
379 m_LayerIndex = LayerIndex;
380
381 if(m_TrackedOp == ESoundSourceOp::OP_MOVE)
382 HandlePointMove(State: EState::STATE_BEGIN);
383}
384
385void CSoundSourceOperationTracker::End()
386{
387 if(m_TrackedOp == ESoundSourceOp::OP_NONE)
388 return;
389
390 if(m_TrackedOp == ESoundSourceOp::OP_MOVE)
391 HandlePointMove(State: EState::STATE_END);
392
393 m_TrackedOp = ESoundSourceOp::OP_NONE;
394}
395
396void CSoundSourceOperationTracker::HandlePointMove(EState State)
397{
398 if(State == EState::STATE_BEGIN)
399 {
400 m_Data.m_OriginalPoint = m_pSource->m_Position;
401 }
402 else if(State == EState::STATE_END)
403 {
404 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionMoveSoundSource>(args&: m_pEditor, args&: m_pEditor->m_SelectedGroup, args&: m_LayerIndex, args&: m_pEditor->m_SelectedSource, args&: m_Data.m_OriginalPoint, args&: m_pSource->m_Position));
405 }
406}
407
408// -----------------------------------------------------------------------
409
410int SPropTrackerHelper::GetDefaultGroupIndex(CEditor *pEditor)
411{
412 return pEditor->m_SelectedGroup;
413}
414
415int SPropTrackerHelper::GetDefaultLayerIndex(CEditor *pEditor)
416{
417 return pEditor->m_vSelectedLayers[0];
418}
419
420// -----------------------------------------------------------------------
421
422void CLayerPropTracker::OnEnd(ELayerProp Prop, int Value)
423{
424 if(Prop == ELayerProp::PROP_GROUP)
425 {
426 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditLayersGroupAndOrder>(args&: m_pEditor, args&: m_OriginalGroupIndex, args: std::vector<int>{m_OriginalLayerIndex}, args&: m_CurrentGroupIndex, args: std::vector<int>{m_CurrentLayerIndex}));
427 }
428 else
429 {
430 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditLayerProp>(args&: m_pEditor, args&: m_CurrentGroupIndex, args&: m_CurrentLayerIndex, args&: Prop, args&: m_OriginalValue, args&: Value));
431 }
432}
433
434int CLayerPropTracker::PropToValue(ELayerProp Prop)
435{
436 switch(Prop)
437 {
438 case ELayerProp::PROP_GROUP: return m_CurrentGroupIndex;
439 case ELayerProp::PROP_HQ: return m_pObject->m_Flags;
440 case ELayerProp::PROP_ORDER: return m_CurrentLayerIndex;
441 default: return 0;
442 }
443}
444
445// -----------------------------------------------------------------------
446
447bool CLayerTilesPropTracker::EndChecker(ETilesProp Prop, EEditState State, int Value)
448{
449 return (State == EEditState::END || State == EEditState::ONE_GO) && (Value != m_OriginalValue || Prop == ETilesProp::PROP_SHIFT);
450}
451
452void CLayerTilesPropTracker::OnStart(ETilesProp Prop)
453{
454 if(Prop == ETilesProp::PROP_WIDTH || Prop == ETilesProp::PROP_HEIGHT)
455 {
456 m_SavedLayers[LAYERTYPE_TILES] = m_pObject->Duplicate();
457 if(m_pObject->m_Game || m_pObject->m_Front || m_pObject->m_Switch || m_pObject->m_Speedup || m_pObject->m_Tune || m_pObject->m_Tele)
458 { // Need to save all entities layers when any entity layer
459 if(m_pEditor->m_Map.m_pFrontLayer && !m_pObject->m_Front)
460 m_SavedLayers[LAYERTYPE_FRONT] = m_pEditor->m_Map.m_pFrontLayer->Duplicate();
461 if(m_pEditor->m_Map.m_pTeleLayer && !m_pObject->m_Tele)
462 m_SavedLayers[LAYERTYPE_TELE] = m_pEditor->m_Map.m_pTeleLayer->Duplicate();
463 if(m_pEditor->m_Map.m_pSwitchLayer && !m_pObject->m_Switch)
464 m_SavedLayers[LAYERTYPE_SWITCH] = m_pEditor->m_Map.m_pSwitchLayer->Duplicate();
465 if(m_pEditor->m_Map.m_pSpeedupLayer && !m_pObject->m_Speedup)
466 m_SavedLayers[LAYERTYPE_SPEEDUP] = m_pEditor->m_Map.m_pSpeedupLayer->Duplicate();
467 if(m_pEditor->m_Map.m_pTuneLayer && !m_pObject->m_Tune)
468 m_SavedLayers[LAYERTYPE_TUNE] = m_pEditor->m_Map.m_pTuneLayer->Duplicate();
469 if(!m_pObject->m_Game)
470 m_SavedLayers[LAYERTYPE_GAME] = m_pEditor->m_Map.m_pGameLayer->Duplicate();
471 }
472 }
473 else if(Prop == ETilesProp::PROP_SHIFT)
474 {
475 m_SavedLayers[LAYERTYPE_TILES] = m_pObject->Duplicate();
476 }
477}
478
479void CLayerTilesPropTracker::OnEnd(ETilesProp Prop, int Value)
480{
481 auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: Prop, args&: m_OriginalValue, args&: Value);
482
483 pAction->SetSavedLayers(m_SavedLayers);
484 m_SavedLayers.clear();
485
486 m_pEditor->m_EditorHistory.RecordAction(pAction);
487}
488
489int CLayerTilesPropTracker::PropToValue(ETilesProp Prop)
490{
491 switch(Prop)
492 {
493 case ETilesProp::PROP_AUTOMAPPER: return m_pObject->m_AutoMapperConfig;
494 case ETilesProp::PROP_COLOR: return PackColor(Color: m_pObject->m_Color);
495 case ETilesProp::PROP_COLOR_ENV: return m_pObject->m_ColorEnv;
496 case ETilesProp::PROP_COLOR_ENV_OFFSET: return m_pObject->m_ColorEnvOffset;
497 case ETilesProp::PROP_HEIGHT: return m_pObject->m_Height;
498 case ETilesProp::PROP_WIDTH: return m_pObject->m_Width;
499 case ETilesProp::PROP_IMAGE: return m_pObject->m_Image;
500 case ETilesProp::PROP_SEED: return m_pObject->m_Seed;
501 case ETilesProp::PROP_SHIFT_BY: return m_pEditor->m_ShiftBy;
502 default: return 0;
503 }
504}
505
506// ------------------------------
507
508void CLayerTilesCommonPropTracker::OnStart(ETilesCommonProp Prop)
509{
510 for(auto &pLayer : m_vpLayers)
511 {
512 if(Prop == ETilesCommonProp::PROP_SHIFT)
513 {
514 m_SavedLayers[pLayer][LAYERTYPE_TILES] = pLayer->Duplicate();
515 }
516 }
517}
518
519void CLayerTilesCommonPropTracker::OnEnd(ETilesCommonProp Prop, int Value)
520{
521 std::vector<std::shared_ptr<IEditorAction>> vpActions;
522
523 static std::map<ETilesCommonProp, ETilesProp> s_PropMap{
524 {ETilesCommonProp::PROP_COLOR, ETilesProp::PROP_COLOR},
525 {ETilesCommonProp::PROP_SHIFT, ETilesProp::PROP_SHIFT},
526 {ETilesCommonProp::PROP_SHIFT_BY, ETilesProp::PROP_SHIFT_BY}};
527
528 int j = 0;
529 for(auto &pLayer : m_vpLayers)
530 {
531 int LayerIndex = m_vLayerIndices[j++];
532 auto pAction = std::make_shared<CEditorActionEditLayerTilesProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: LayerIndex, args&: s_PropMap[Prop], args&: m_OriginalValue, args&: Value);
533 pAction->SetSavedLayers(m_SavedLayers[pLayer]);
534 vpActions.push_back(x: pAction);
535 }
536
537 char aDisplay[256];
538 static const char *s_apNames[] = {
539 "width",
540 "height",
541 "shift",
542 "shift by",
543 "color",
544 };
545
546 str_format(buffer: aDisplay, buffer_size: sizeof(aDisplay), format: "Edit %d layers common property: %s", (int)m_vpLayers.size(), s_apNames[(int)Prop]);
547 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionBulk>(args&: m_pEditor, args&: vpActions, args&: aDisplay));
548}
549
550bool CLayerTilesCommonPropTracker::EndChecker(ETilesCommonProp Prop, EEditState State, int Value)
551{
552 return (State == EEditState::END || State == EEditState::ONE_GO) && (Value != m_OriginalValue || Prop == ETilesCommonProp::PROP_SHIFT);
553}
554
555int CLayerTilesCommonPropTracker::PropToValue(ETilesCommonProp Prop)
556{
557 if(Prop == ETilesCommonProp::PROP_SHIFT_BY)
558 return m_pEditor->m_ShiftBy;
559 return 0;
560}
561
562// ------------------------------
563
564void CLayerGroupPropTracker::OnEnd(EGroupProp Prop, int Value)
565{
566 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditGroupProp>(args&: m_pEditor, args&: m_pEditor->m_SelectedGroup, args&: Prop, args&: m_OriginalValue, args&: Value));
567}
568
569int CLayerGroupPropTracker::PropToValue(EGroupProp Prop)
570{
571 switch(Prop)
572 {
573 case EGroupProp::PROP_ORDER: return m_pEditor->m_SelectedGroup;
574 case EGroupProp::PROP_POS_X: return m_pObject->m_OffsetX;
575 case EGroupProp::PROP_POS_Y: return m_pObject->m_OffsetY;
576 case EGroupProp::PROP_PARA_X: return m_pObject->m_ParallaxX;
577 case EGroupProp::PROP_PARA_Y: return m_pObject->m_ParallaxY;
578 case EGroupProp::PROP_USE_CLIPPING: return m_pObject->m_UseClipping;
579 case EGroupProp::PROP_CLIP_X: return m_pObject->m_ClipX;
580 case EGroupProp::PROP_CLIP_Y: return m_pObject->m_ClipY;
581 case EGroupProp::PROP_CLIP_W: return m_pObject->m_ClipW;
582 case EGroupProp::PROP_CLIP_H: return m_pObject->m_ClipH;
583 default: return 0;
584 }
585}
586
587// ------------------------------------------------------------------
588
589void CLayerQuadsPropTracker::OnEnd(ELayerQuadsProp Prop, int Value)
590{
591 auto pAction = std::make_shared<CEditorActionEditLayerQuadsProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: Prop, args&: m_OriginalValue, args&: Value);
592 m_pEditor->m_EditorHistory.RecordAction(pAction);
593}
594
595int CLayerQuadsPropTracker::PropToValue(ELayerQuadsProp Prop)
596{
597 if(Prop == ELayerQuadsProp::PROP_IMAGE)
598 return m_pObject->m_Image;
599 return 0;
600}
601
602// -------------------------------------------------------------------
603
604void CLayerSoundsPropTracker::OnEnd(ELayerSoundsProp Prop, int Value)
605{
606 auto pAction = std::make_shared<CEditorActionEditLayerSoundsProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: Prop, args&: m_OriginalValue, args&: Value);
607 m_pEditor->m_EditorHistory.RecordAction(pAction);
608}
609
610int CLayerSoundsPropTracker::PropToValue(ELayerSoundsProp Prop)
611{
612 if(Prop == ELayerSoundsProp::PROP_SOUND)
613 return m_pObject->m_Sound;
614 return 0;
615}
616
617// ----
618
619void CSoundSourcePropTracker::OnEnd(ESoundProp Prop, int Value)
620{
621 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditSoundSourceProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: m_pEditor->m_SelectedSource, args&: Prop, args&: m_OriginalValue, args&: Value));
622}
623
624int CSoundSourcePropTracker::PropToValue(ESoundProp Prop)
625{
626 switch(Prop)
627 {
628 case ESoundProp::PROP_POS_X: return m_pObject->m_Position.x;
629 case ESoundProp::PROP_POS_Y: return m_pObject->m_Position.y;
630 case ESoundProp::PROP_LOOP: return m_pObject->m_Loop;
631 case ESoundProp::PROP_PAN: return m_pObject->m_Pan;
632 case ESoundProp::PROP_TIME_DELAY: return m_pObject->m_TimeDelay;
633 case ESoundProp::PROP_FALLOFF: return m_pObject->m_Falloff;
634 case ESoundProp::PROP_POS_ENV: return m_pObject->m_PosEnv;
635 case ESoundProp::PROP_POS_ENV_OFFSET: return m_pObject->m_PosEnvOffset;
636 case ESoundProp::PROP_SOUND_ENV: return m_pObject->m_SoundEnv;
637 case ESoundProp::PROP_SOUND_ENV_OFFSET: return m_pObject->m_SoundEnvOffset;
638 default: return 0;
639 }
640}
641
642// ----
643
644void CSoundSourceRectShapePropTracker::OnEnd(ERectangleShapeProp Prop, int Value)
645{
646 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditRectSoundSourceShapeProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: m_pEditor->m_SelectedSource, args&: Prop, args&: m_OriginalValue, args&: Value));
647}
648
649int CSoundSourceRectShapePropTracker::PropToValue(ERectangleShapeProp Prop)
650{
651 switch(Prop)
652 {
653 case ERectangleShapeProp::PROP_RECTANGLE_WIDTH: return m_pObject->m_Shape.m_Rectangle.m_Width;
654 case ERectangleShapeProp::PROP_RECTANGLE_HEIGHT: return m_pObject->m_Shape.m_Rectangle.m_Height;
655 default: return 0;
656 }
657}
658
659void CSoundSourceCircleShapePropTracker::OnEnd(ECircleShapeProp Prop, int Value)
660{
661 m_pEditor->m_EditorHistory.RecordAction(pAction: std::make_shared<CEditorActionEditCircleSoundSourceShapeProp>(args&: m_pEditor, args&: m_OriginalGroupIndex, args&: m_OriginalLayerIndex, args&: m_pEditor->m_SelectedSource, args&: Prop, args&: m_OriginalValue, args&: Value));
662}
663
664int CSoundSourceCircleShapePropTracker::PropToValue(ECircleShapeProp Prop)
665{
666 switch(Prop)
667 {
668 case ECircleShapeProp::PROP_CIRCLE_RADIUS: return m_pObject->m_Shape.m_Circle.m_Radius;
669 default: return 0;
670 }
671}
672