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