Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / r2 / dmc / action_historic.cpp
blob7a018d10a507bd011f2c29620945e0fa8f45a569
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
22 #include "action_historic.h"
23 #include "property_accessor.h"
24 #include "../object_factory_client.h"
25 #include "../editor.h"
26 #include "nel/gui/lua_ihm.h"
28 #ifdef DEBUG_NEW
29 #define new DEBUG_NEW
30 #endif
32 namespace R2
35 /////////////////////
36 // CActionHistoric //
37 /////////////////////
40 //====================================================================================
41 CActionHistoric::CActionHistoric() : _Scenario(NULL, st_edit)
43 _NewActionIsPending = false;
44 _CurrActionIndex = -1;
45 setMaxNumActions(50);
46 _SubActionCount = 0;
49 //====================================================================================
50 CActionHistoric::~CActionHistoric()
54 //====================================================================================
55 void CActionHistoric::newSingleAction(const ucstring &name)
57 //H_AUTO(R2_CActionHistoric_newSingleAction)
58 endAction();
59 if (_SubActionCount == 0)
61 _SubActionCount = 1;
62 _NewActionIsPending = false;
64 if (!_NewActionIsPending)
66 _NewActionName = name;
70 //====================================================================================
71 void CActionHistoric::cancelAction()
73 //H_AUTO(R2_CActionHistoric_cancelAction)
74 if (_NewAction && _NewActionIsPending)
76 _NewAction->rollback(_DMC, _Scenario);
78 _NewAction = NULL;
79 _NewActionIsPending = false;
80 _SubActionCount = 1;
81 _NewActionName.clear();
82 getEditor().callEnvMethod("onCancelActionInHistoric", 0, 0);
85 //====================================================================================
86 void CActionHistoric::newMultiAction(const ucstring &name, uint actionCount)
88 //H_AUTO(R2_CActionHistoric_newMultiAction)
89 _SubActionCount = 1; // force previous multi action to finish
90 endAction();
91 _NewActionIsPending = false;
92 _SubActionCount = actionCount;
93 _NewActionName = name;
96 //====================================================================================
97 void CActionHistoric::flushPendingAction()
99 //H_AUTO(R2_CActionHistoric_flushPendingAction)
100 if (_NewAction && _NewActionIsPending)
102 _NewAction->flush(_DMC, _Scenario);
106 //====================================================================================
107 void CActionHistoric::newPendingMultiAction(const ucstring &name, uint actionCount)
109 //H_AUTO(R2_CActionHistoric_newPendingMultiAction)
110 _SubActionCount = 1; // force previous multi action to finish
111 endAction();
112 _NewActionIsPending = true;
113 _SubActionCount = actionCount;
114 _NewActionName = name;
115 getEditor().callEnvMethod("onPendingActionBegin", 0, 0);
118 //====================================================================================
119 void CActionHistoric::newPendingAction(const ucstring &name)
121 //H_AUTO(R2_CActionHistoric_newPendingAction)
122 endAction();
123 _NewActionIsPending = true;
124 _NewActionName = name;
125 getEditor().callEnvMethod("onPendingActionBegin", 0, 0);
128 //====================================================================================
129 void CActionHistoric::endAction()
131 //H_AUTO(R2_CActionHistoric_endAction)
132 // if current action is void, no-op
133 if (!_NewAction)
135 return;
138 if (_SubActionCount == 0)
140 return;
142 -- _SubActionCount;
143 if (_SubActionCount > 0)
145 return; // several actions expected before the merge
147 ++_CurrActionIndex;
148 // Push the new action -> discard all actions beyond _CurrActionIndex
149 uint newSize = (uint) std::max((sint) _Actions.getSize() + _CurrActionIndex, 0);
150 while (_Actions.getSize() > newSize)
152 _Actions.pop();
154 _CurrActionIndex = -1;
155 _Actions.push(_NewAction);
156 if (!_NewActionIsPending)
158 _NewAction->flush(_DMC, _Scenario); // redo may trigger other observers that complete the action
160 _NewAction->setCompleted();
161 _CurrActionIndex = -1;
162 _NewAction = NULL;
163 _NewActionIsPending = false;
164 // warn lua that a new action has been added
165 if (isUndoSupported())
167 getEditor().callEnvMethod("onNewActionAddedInHistoric", 0, 0);
171 //====================================================================================
172 void CActionHistoric::forceEndMultiAction()
174 //H_AUTO(R2_CActionHistoric_forceEndMultiAction)
175 if (_NewActionIsPending && _NewAction)
177 _NewAction->flush(_DMC, _Scenario);
179 if (_SubActionCount > 1) _SubActionCount = 1;
180 endAction();
183 //====================================================================================
184 void CActionHistoric::setMaxNumActions(uint count)
186 //H_AUTO(R2_CActionHistoric_setMaxNumActions)
187 nlassert(count >= 1);
188 _Actions.setMaxSize(count);
191 //====================================================================================
192 void CActionHistoric::clear(CObject *newScenario)
194 //H_AUTO(R2_CActionHistoric_clear)
195 if (_NewActionIsPending)
197 nlwarning("Historic was cleared while a pending action!!");
199 _Actions.clear();
200 _CurrActionIndex = -1;
201 _NewAction = NULL;
202 _NewActionIsPending = false;
203 _Scenario.setHighLevel(newScenario ? CRequestBase::cloneObject(newScenario) : NULL);
204 // warn lua that all actions have been cleared
205 getEditor().callEnvMethod("onClearActionHistoric", 0, 0);
209 //====================================================================================
210 sint CActionHistoric::getPreviousActionIndex() const
212 //H_AUTO(R2_CActionHistoric_getPreviousActionIndex)
213 sint index = (sint) _Actions.getSize() + _CurrActionIndex;
214 return index >= 0 ? index : -1;
217 //====================================================================================
218 sint CActionHistoric::getNextActionIndex() const
220 //H_AUTO(R2_CActionHistoric_getNextActionIndex)
221 if (_Actions.empty()) return -1;
222 sint index = (sint) _Actions.getSize() + (_CurrActionIndex + 1);
223 return index >= 0 && index < (sint) _Actions.getSize() ? index : -1;
226 //====================================================================================
227 bool CActionHistoric::canUndo() const
229 //H_AUTO(R2_CActionHistoric_canUndo)
230 if (_NewActionIsPending) return false;
231 return getPreviousActionIndex() != -1;
234 //====================================================================================
235 bool CActionHistoric::canRedo() const
237 //H_AUTO(R2_CActionHistoric_canRedo)
238 if (_NewActionIsPending) return false;
239 return getNextActionIndex() != -1;
242 //====================================================================================
243 bool CActionHistoric::undo()
245 //H_AUTO(R2_CActionHistoric_undo)
246 nlassert(!_NewActionIsPending);
247 sint index = getPreviousActionIndex();
248 if (index == -1) return false;
249 _Actions[index]->undo(_DMC, _Scenario);
250 -- _CurrActionIndex;
251 return true;
254 //====================================================================================
255 bool CActionHistoric::redo()
257 //H_AUTO(R2_CActionHistoric_redo)
258 nlassert(!_NewActionIsPending);
259 sint index = getNextActionIndex();
260 if (index == -1) return false;
261 _Actions[index]->redo(_DMC, _Scenario);
262 ++ _CurrActionIndex;
263 return true;
266 //====================================================================================
267 const ucstring *CActionHistoric::getPreviousActionName() const
269 //H_AUTO(R2_CActionHistoric_getPreviousActionName)
270 sint index = getPreviousActionIndex();
271 return index != -1 ? &_Actions[index]->getName() : NULL;
274 //====================================================================================
275 const ucstring *CActionHistoric::getNextActionName() const
277 //H_AUTO(R2_CActionHistoric_getNextActionName)
278 sint index = getNextActionIndex();
279 return index != -1 ? &_Actions[index]->getName() : NULL;
282 //====================================================================================
283 void CActionHistoric::requestInsertNode(const std::string& instanceId, const std::string& name,sint32 position, const std::string& key, CObject* value)
285 //H_AUTO(R2_CActionHistoric_requestInsertNode)
286 if (_Scenario.getHighLevel())
288 CObject *target = _DMC->find(instanceId, name);
289 if (value->getGhost() || (target && target->getGhost()))
291 // direct effect, assumed to be local display only
292 getEditor().getDMC().nodeInserted(instanceId, name, position, key, value->clone());
293 return;
296 if (!_NewAction) _NewAction = new CAction(_NewActionName);
297 CRequestBase::TSmartPtr req = new CRequestInsertNode(instanceId, name, position, key, value);
298 //if (_NewActionIsPending) req->redo(_DMC, _Scenario);
299 _NewAction->pushRequest(req);
302 //====================================================================================
303 void CActionHistoric::requestSetNode(const std::string& instanceId,const std::string& attrName, CObject* value)
305 //H_AUTO(R2_CActionHistoric_requestSetNode)
306 if (_Scenario.getHighLevel())
308 CObject *clObj = _DMC->find(instanceId, attrName);
309 if (clObj && clObj->getGhost())
311 value->setGhost(true);
313 if (value->getGhost())
315 // direct effect, assumed to be local display only
316 getEditor().getDMC().nodeSet(instanceId, attrName, value->clone());
317 return;
320 if (!_NewAction) _NewAction = new CAction(_NewActionName);
321 CRequestBase::TSmartPtr req = new CRequestSetNode(instanceId, attrName, value);
322 //if (_NewActionIsPending) req->redo(_DMC, _Scenario);
323 _NewAction->pushRequest(req);
326 //====================================================================================
327 void CActionHistoric::requestEraseNode(const std::string& instanceId, const std::string& attrName, sint32 position)
329 //H_AUTO(R2_CActionHistoric_requestEraseNode)
330 if (_Scenario.getHighLevel())
332 CObject *obj = _DMC->find(instanceId, attrName, position);
333 if (obj && obj->getGhost())
335 // direct effect, assumed to be local display only
336 getEditor().getDMC().nodeErased(instanceId, attrName, position);
337 return;
340 if (!_NewAction) _NewAction = new CAction(_NewActionName);
341 CRequestBase::TSmartPtr req = new CRequestEraseNode(instanceId, attrName, position);
342 //if (_NewActionIsPending) req->redo(_DMC, _Scenario);
343 _NewAction->pushRequest(req);
346 //====================================================================================
347 void CActionHistoric::requestMoveNode(const std::string& instanceId, const std::string& attrName, sint32 position, const std::string& destInstanceId, const std::string& destAttrName, sint32 destPosition)
349 //H_AUTO(R2_CActionHistoric_requestMoveNode)
350 if (_Scenario.getHighLevel())
352 CObject *src = _DMC->find(instanceId, attrName, position);
353 CObject *dest = _DMC->find(destInstanceId, destAttrName);
354 if (src && dest)
356 nlassert(src->getGhost() == dest->getGhost());
357 if (src->getGhost())
359 // direct effect, assumed to be local display only
360 getEditor().getDMC().nodeMoved(instanceId, attrName, position, destInstanceId, destAttrName, destPosition);
361 return;
365 if (!_NewAction) _NewAction = new CAction(_NewActionName);
366 CRequestBase::TSmartPtr req = new CRequestMoveNode(instanceId, attrName, position, destInstanceId, destAttrName, destPosition);
367 //if (_NewActionIsPending) req->redo(_DMC, _Scenario);
368 _NewAction->pushRequest(req);
371 /////////////
372 // CAction //
373 /////////////
376 //====================================================================================
377 CActionHistoric::CAction::CAction(const ucstring &name) : _Name(name), _FlushedCount(0), _Completed(false), _Flushing(false)
381 //====================================================================================
382 void CActionHistoric::CAction::pushRequest(CRequestBase *req)
384 //H_AUTO(R2_CAction_pushRequest)
385 nlassert(req);
386 nlassert(!_Completed);
387 _Requests.push_back(req);
391 //====================================================================================
392 CActionHistoric::CAction::~CAction()
396 //====================================================================================
397 void CActionHistoric::CAction::flush(IDynamicMapClient *dmc, CScenario &scenario)
399 //H_AUTO(R2_CAction_flush)
400 nlwarning("Flushing action at 0x%p", this);
401 if (_Flushing) return;
402 _Flushing = true;
403 nlassert(_FlushedCount <= _Requests.size());
404 nlassert(!_Completed);
405 while (_FlushedCount != _Requests.size())
407 _Requests[_FlushedCount]->redo(dmc, scenario);
408 ++ _FlushedCount;
409 nlassert(_FlushedCount <= _Requests.size());
411 nlassert(_FlushedCount == _Requests.size());
412 _Flushing = false;
415 //====================================================================================
416 void CActionHistoric::CAction::rollback(IDynamicMapClient *dmc, CScenario &scenario)
418 //H_AUTO(R2_CAction_rollback)
419 nlassert(_FlushedCount <= _Requests.size());
420 for (sint k = _FlushedCount - 1; k >= 0; --k)
422 _Requests[k]->undo(dmc, scenario);
424 _FlushedCount = 0;
427 //====================================================================================
428 void CActionHistoric::CAction::redo(IDynamicMapClient *dmc, CScenario &scenario)
430 //H_AUTO(R2_CAction_redo)
431 nlassert(_FlushedCount <= _Requests.size());
432 nlassert(_Completed);
433 nlassert(dmc);
434 for (uint k = 0; k < _Requests.size(); ++k)
436 _Requests[k]->redo(dmc, scenario);
440 //====================================================================================
441 void CActionHistoric::CAction::undo(IDynamicMapClient *dmc, CScenario &scenario)
443 //H_AUTO(R2_CAction_undo)
444 nlassert(_FlushedCount <= _Requests.size());
445 nlassert(_Completed);
446 nlassert(dmc);
447 for (sint k = (sint)_Requests.size() - 1; k >= 0; --k)
449 _Requests[k]->undo(dmc, scenario);
453 //////////////
454 // REQUESTS //
455 //////////////
457 //====================================================================================
458 CObject *CActionHistoric::CRequestBase::cloneObject(const CObject *src)
460 //H_AUTO(R2_CRequestBase_cloneObject)
461 CObject *result = src->clone();
462 struct CDisableRefIDs : public IObjectVisitor
464 virtual void visit(CObjectRefId &obj)
466 CObjectRefIdClient *refId = NLMISC::safe_cast<CObjectRefIdClient *>(&obj);
467 refId->enable(false); // disable events
470 CDisableRefIDs disableRefIDs;
471 result->visit(disableRefIDs);
472 return result;
475 //====================================================================================
476 CActionHistoric::CRequestSetNode::CRequestSetNode(const std::string &instanceId,
477 const std::string& attrName,
478 CObject* value)
480 nlassert(value);
481 _InstanceId = instanceId;
482 _AttrName = attrName;
483 _NewValue = cloneObject(value);
486 void CActionHistoric::CRequestSetNode::redo(IDynamicMapClient *dmc, CScenario &scenario)
488 //H_AUTO(R2_CRequestSetNode_redo)
489 _OldValue = NULL;
490 if (scenario.getHighLevel()) // undo allowed ?
492 CObject *old = scenario.find(_InstanceId, _AttrName);
493 if (old) // may be not found if defined in the base and not redefined yet
495 // maybe a shadowed property ?
496 /*CObject *shadow = dmc->getPropertyAccessor().getShadowingValue(old);
497 if (shadow) old = shadow; // use the shadow instead*/
498 _OldValue = cloneObject(old);
499 nlwarning("**** backupped value for undo request set node");
500 _OldValue->dump();
502 // modify local version
503 scenario.setNode(_InstanceId, _AttrName, _NewValue);
505 // send to network
506 dmc->doRequestSetNode(_InstanceId, _AttrName, _NewValue);
509 void CActionHistoric::CRequestSetNode::undo(IDynamicMapClient *dmc, CScenario &scenario)
511 //H_AUTO(R2_CRequestSetNode_undo)
512 nlassert(scenario.getHighLevel()); // if this assert fires, then 'clear' was called with a NULL pointer ! The action historic need a start scenario to have undo capability
513 if (!_OldValue)
515 // was a value from the base ? just erase ...
517 // modify local version
518 scenario.eraseNode(_InstanceId, _AttrName, -1);
519 // send to network
520 dmc->doRequestEraseNode(_InstanceId, _AttrName, -1);
522 else
524 // modify local version
525 scenario.setNode(_InstanceId, _AttrName, _OldValue);
526 // send to network
527 // TODO nico : handle case where same value than the base is restored here
528 dmc->doRequestSetNode(_InstanceId, _AttrName, _OldValue);
531 _OldValue = NULL;
533 //====================================================================================
534 CActionHistoric::CRequestEraseNode::CRequestEraseNode(const std::string& instanceId, const std::string& attrName, sint32 position)
536 //H_AUTO(R2_CRequestEraseNode_CRequestEraseNode)
537 _InstanceId = instanceId;
538 _AttrName = attrName;
539 _Position = position;
542 void CActionHistoric::CRequestEraseNode::redo(IDynamicMapClient *dmc, CScenario &scenario)
544 //H_AUTO(R2_CRequestEraseNode_redo)
545 nlassert(dmc);
546 _OldValue = NULL;
547 if (scenario.getHighLevel()) // undo allowed ?
549 CObject *old = scenario.find(_InstanceId, _AttrName, _Position);
550 if (!old)
552 nlwarning("Can't redo erase request!!");
553 nlassert(0); // TMP TMP
554 return;
556 if (!old->getNameInParent(_ParentInstanceId, _AttrNameInParent, _PositionInParent))
558 nlwarning("Can't retrieve name in parent, requestEraseNode undo will fail!");
560 _OldValue = cloneObject(old);
562 // modify local version
563 scenario.eraseNode(_InstanceId, _AttrName, _Position);
565 // send to network
566 dmc->doRequestEraseNode(_InstanceId, _AttrName, _Position);
569 void CActionHistoric::CRequestEraseNode::undo(IDynamicMapClient *dmc, CScenario &scenario)
571 //H_AUTO(R2_CRequestEraseNode_undo)
572 nlassert(scenario.getHighLevel()); // if this assert fires, then 'clear' was called with a NULL pointer ! The action historic need a start scenario to have undo capability
573 nlassert(dmc);
574 if (!_OldValue)
576 nlwarning("Can't undo erase node, previous node not saved");
577 return;
579 if (_ParentInstanceId.empty())
581 nlwarning("Can't undo erase node, parent name not known");
582 return;
584 // modify local version
585 scenario.insertNode(_ParentInstanceId, _AttrNameInParent, _PositionInParent, "", cloneObject(_OldValue));
586 // send to network
587 dmc->doRequestInsertNode(_ParentInstanceId, _AttrNameInParent, _PositionInParent, "", _OldValue);
588 _OldValue = NULL;
590 #ifdef RYZOM_LUA_UCSTRING
591 CLuaIHM::push(getEditor().getLua(), ucstring::makeFromUtf8(_InstanceId));
592 #else
593 getEditor().getLua().push(_InstanceId);
594 #endif
595 getEditor().callEnvMethod("setUndoRedoInstances", 1, 0);
597 //====================================================================================
598 CActionHistoric::CRequestInsertNode::CRequestInsertNode(const std::string& instanceId,
599 const std::string &attrName,
600 sint32 position,
601 const std::string& key,
602 CObject* value)
604 _InstanceId = instanceId;
605 _AttrName = attrName;
606 _Position = position;
607 _Key = key;
608 _Value = cloneObject(value);
611 void CActionHistoric::CRequestInsertNode::redo(IDynamicMapClient *dmc, CScenario &scenario)
613 //H_AUTO(R2_CRequestInsertNode_redo)
614 nlassert(dmc);
615 if (scenario.getHighLevel())
617 // modify local version
618 scenario.insertNode(_InstanceId, _AttrName, _Position, _Key, cloneObject(_Value));
620 // send to network
621 dmc->doRequestInsertNode(_InstanceId, _AttrName, _Position, _Key, _Value);
623 CObject* nodeId = _Value->findAttr("InstanceId");
624 #ifdef RYZOM_LUA_UCSTRING
625 CLuaIHM::push(getEditor().getLua(), ucstring::makeFromUtf8(nodeId->toString()));
626 #else
627 getEditor().getLua().push(nodeId->toString());
628 #endif
629 getEditor().callEnvMethod("setUndoRedoInstances", 1, 0);
632 void CActionHistoric::CRequestInsertNode::undo(IDynamicMapClient *dmc, CScenario &scenario)
634 //H_AUTO(R2_CRequestInsertNode_undo)
635 nlassert(scenario.getHighLevel()); // if this assert fires, then 'clear' was called with a NULL pointer ! The action historic need a start scenario to have undo capability
636 nlassert(dmc);
637 // if there's a key here, not good for us :(
638 // so try to find another shorter name for this object...
639 if (!_Key.empty())
641 std::string instanceId;
642 std::string attrName;
643 sint32 position;
644 CObject *currObj = scenario.find(_InstanceId, _AttrName, _Position, _Key);
645 if (!currObj) return;
646 if (currObj->getShortestName(instanceId, attrName, position))
648 // modify local version
649 scenario.eraseNode(instanceId, attrName, position);
650 // send to network
651 dmc->doRequestEraseNode(instanceId, attrName, position);
653 #ifdef RYZOM_LUA_UCSTRING
654 CLuaIHM::push(getEditor().getLua(), ucstring::makeFromUtf8(instanceId));
655 #else
656 getEditor().getLua().push(instanceId);
657 #endif
658 getEditor().callEnvMethod("setUndoRedoInstances", 1, 0);
660 else
662 nlassert(0); // TMP : can this really happen in practice ?
663 nlwarning("Can't build request insert node reciprocal");
666 else
668 // special here : if position is -1, requestEraseNode will erase the
669 // table, not the last element!
670 if (!_AttrName.empty() && _Position == -1)
672 CObject *parentTable = scenario.find(_InstanceId, _AttrName);
673 if (parentTable && parentTable->isTable())
675 uint index = parentTable->getSize() - 1;
676 // modify local version
677 scenario.eraseNode(_InstanceId, _AttrName, index);
678 // send to network
679 dmc->doRequestEraseNode(_InstanceId, _AttrName, index);
682 else
684 // modify local version
685 scenario.eraseNode(_InstanceId, _AttrName, _Position);
686 // send to network
687 dmc->doRequestEraseNode(_InstanceId, _AttrName, _Position);
691 //====================================================================================
692 CActionHistoric::CRequestMoveNode::CRequestMoveNode(const std::string &srcInstanceId,
693 const std::string &srcAttrName,
694 sint32 srcPosition,
695 const std::string &destInstanceId,
696 const std::string &destAttrName,
697 sint32 destPosition)
699 _SrcInstanceId = srcInstanceId;
700 _SrcAttrName = srcAttrName;
701 _SrcPosition = srcPosition;
702 _DestInstanceId = destInstanceId;
703 _DestAttrName = destAttrName;
704 _DestPosition = destPosition;
707 void CActionHistoric::CRequestMoveNode::redo(IDynamicMapClient *dmc, CScenario &scenario)
709 //H_AUTO(R2_CRequestMoveNode_redo)
710 nlassert(dmc);
711 if (scenario.getHighLevel())
713 CObject *src = scenario.find(_SrcInstanceId, _SrcAttrName, _SrcPosition);
714 if (!src)
716 nlwarning("Can't find source when moving node");
717 return;
719 if (!src->getNameInParent(_SrcInstanceIdInParent, _SrcAttrNameInParent, _SrcPositionInParent))
721 nlwarning("Can't find name of source object in its parent");
722 return;
724 // modify local version
725 scenario.moveNode(_SrcInstanceId,
726 _SrcAttrName,
727 _SrcPosition,
728 _DestInstanceId,
729 _DestAttrName,
730 _DestPosition);
731 if (!src->getShortestName(_DestInstanceIdAfterMove, _DestAttrNameAfterMove, _DestPositionAfterMove))
733 nlwarning("Can't retrieve name of instance after move, undo will fail");
736 // send to network
737 dmc->doRequestMoveNode(_SrcInstanceId,
738 _SrcAttrName,
739 _SrcPosition,
740 _DestInstanceId,
741 _DestAttrName,
742 _DestPosition);
745 void CActionHistoric::CRequestMoveNode::undo(IDynamicMapClient *dmc, CScenario &scenario)
747 //H_AUTO(R2_CRequestMoveNode_undo)
748 nlassert(scenario.getHighLevel()); // if this assert fires, then 'clear' was called with a NULL pointer ! The action historic need a start scenario to have undo capability
749 nlassert(dmc);
750 // modify local version
751 scenario.moveNode(_DestInstanceIdAfterMove,
752 _DestAttrNameAfterMove,
753 _DestPositionAfterMove,
754 _SrcInstanceIdInParent,
755 _SrcAttrNameInParent,
756 _SrcPositionInParent);
757 // send to network
758 dmc->doRequestMoveNode(_DestInstanceIdAfterMove,
759 _DestAttrNameAfterMove,
760 _DestPositionAfterMove,
761 _SrcInstanceIdInParent,
762 _SrcAttrNameInParent,
763 _SrcPositionInParent);
777 } // R2