From aa120fa69f3ab95c98421206949d368c71f1e9e9 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Mon, 5 Dec 2022 01:32:50 +0400 Subject: [PATCH 1/2] Implemented cut copy paste --- mapeditor/inspector/inspector.cpp | 3 ++- mapeditor/mainwindow.cpp | 28 ++++++++++++++++++++ mapeditor/mainwindow.h | 6 +++++ mapeditor/mainwindow.ui | 3 +++ mapeditor/mapcontroller.cpp | 43 +++++++++++++++++++++++++++++++ mapeditor/mapcontroller.h | 5 ++++ mapeditor/mapview.cpp | 10 ++++--- mapeditor/scenelayer.cpp | 8 +++--- mapeditor/scenelayer.h | 2 +- 9 files changed, 99 insertions(+), 9 deletions(-) diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index b5a26a41f..e2bd905aa 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -67,7 +67,8 @@ void Initializer::initialize(CGCreature * o) if(!o) return; o->character = CGCreature::Character::HOSTILE; - o->putStack(SlotID(0), new CStackInstance(CreatureID(o->subID), 0, false)); + if(!o->hasStackAtSlot(SlotID(0))) + o->putStack(SlotID(0), new CStackInstance(CreatureID(o->subID), 0, false)); } void Initializer::initialize(CGDwelling * o) diff --git a/mapeditor/mainwindow.cpp b/mapeditor/mainwindow.cpp index 73b6d1524..c57dd2cef 100644 --- a/mapeditor/mainwindow.cpp +++ b/mapeditor/mainwindow.cpp @@ -1126,3 +1126,31 @@ void MainWindow::on_actionRecreate_obstacles_triggered() } + +void MainWindow::on_actionCut_triggered() +{ + if(controller.map()) + { + controller.copyToClipboard(mapLevel); + controller.commitObjectErase(mapLevel); + } +} + + +void MainWindow::on_actionCopy_triggered() +{ + if(controller.map()) + { + controller.copyToClipboard(mapLevel); + } +} + + +void MainWindow::on_actionPaste_triggered() +{ + if(controller.map()) + { + controller.pasteFromClipboard(mapLevel); + } +} + diff --git a/mapeditor/mainwindow.h b/mapeditor/mainwindow.h index a728c87dc..c3c30874a 100644 --- a/mapeditor/mainwindow.h +++ b/mapeditor/mainwindow.h @@ -98,6 +98,12 @@ private slots: void switchDefaultPlayer(const PlayerColor &); + void on_actionCut_triggered(); + + void on_actionCopy_triggered(); + + void on_actionPaste_triggered(); + public slots: void treeViewSelected(const QModelIndex &selected, const QModelIndex &deselected); diff --git a/mapeditor/mainwindow.ui b/mapeditor/mainwindow.ui index 6da92787e..766114052 100644 --- a/mapeditor/mainwindow.ui +++ b/mapeditor/mainwindow.ui @@ -79,6 +79,9 @@ + + + diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index 21eb65384..82d554b87 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -20,6 +20,7 @@ #include "../lib/CSkillHandler.h" #include "../lib/spells/CSpellHandler.h" #include "../lib/CHeroHandler.h" +#include "../lib/serializer/CMemorySerializer.h" #include "mapview.h" #include "scenelayer.h" #include "maphandler.h" @@ -323,6 +324,48 @@ void MapController::commitObjectErase(int level) main->mapChanged(); } +void MapController::copyToClipboard(int level) +{ + _clipboard.clear(); + _clipboardShiftIndex = 0; + auto selectedObjects = _scenes[level]->selectionObjectsView.getSelection(); + for(auto * obj : selectedObjects) + { + assert(obj->pos.z == level); + _clipboard.push_back(CMemorySerializer::deepCopy(*obj)); + } +} + +void MapController::pasteFromClipboard(int level) +{ + _scenes[level]->selectionObjectsView.clear(); + + auto shift = int3::getDirs()[_clipboardShiftIndex++]; + if(_clipboardShiftIndex == int3::getDirs().size()) + _clipboardShiftIndex = 0; + + for(auto & objuptr : _clipboard) + { + auto * obj = CMemorySerializer::deepCopy(*objuptr).release(); + auto newpos = objuptr->pos + shift; + if(_map->isInTheMap(newpos)) + obj->pos = newpos; + obj->pos.z = level; + + Initializer init(obj, defaultPlayer); + _map->getEditManager()->insertObject(obj); + _scenes[level]->selectionObjectsView.selectObject(obj); + _mapHandler->invalidate(obj); + } + + _scenes[level]->objectsView.draw(); + _scenes[level]->passabilityView.update(); + _scenes[level]->selectionObjectsView.draw(); + + _miniscenes[level]->updateViews(); + main->mapChanged(); +} + bool MapController::discardObject(int level) const { _scenes[level]->selectionObjectsView.clear(); diff --git a/mapeditor/mapcontroller.h b/mapeditor/mapcontroller.h index 3fef9adcc..1446225f6 100644 --- a/mapeditor/mapcontroller.h +++ b/mapeditor/mapcontroller.h @@ -49,6 +49,9 @@ public: void commitObjectCreate(int level); void commitObjectChange(int level); + void copyToClipboard(int level); + void pasteFromClipboard(int level); + bool discardObject(int level) const; void createObject(int level, CGObjectInstance * obj) const; bool canPlaceObject(int level, CGObjectInstance * obj, QString & error) const; @@ -64,6 +67,8 @@ private: MainWindow * main; mutable std::array, 2> _scenes; mutable std::array, 2> _miniscenes; + std::vector> _clipboard; + int _clipboardShiftIndex = 0; void connectScenes(); }; diff --git a/mapeditor/mapview.cpp b/mapeditor/mapview.cpp index c719b80f1..6af283db3 100644 --- a/mapeditor/mapview.cpp +++ b/mapeditor/mapview.cpp @@ -270,6 +270,7 @@ void MapView::mousePressEvent(QMouseEvent *event) if(event->button() == Qt::LeftButton) { auto * obj = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y); + auto * obj2 = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y, obj); if(obj) { if(sc->selectionObjectsView.isSelected(obj)) @@ -284,10 +285,13 @@ void MapView::mousePressEvent(QMouseEvent *event) } else { - if(!(qApp->keyboardModifiers() & Qt::ControlModifier)) - sc->selectionObjectsView.clear(); + if(!obj2 || !sc->selectionObjectsView.isSelected(obj2)) + { + if(!(qApp->keyboardModifiers() & Qt::ControlModifier)) + sc->selectionObjectsView.clear(); + sc->selectionObjectsView.selectObject(obj); + } sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT; - sc->selectionObjectsView.selectObject(obj); } } else diff --git a/mapeditor/scenelayer.cpp b/mapeditor/scenelayer.cpp index 605237c5f..370af0549 100644 --- a/mapeditor/scenelayer.cpp +++ b/mapeditor/scenelayer.cpp @@ -399,7 +399,7 @@ void SelectionObjectsLayer::draw() redraw(); } -CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y) const +CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGObjectInstance * ignore) const { if(!map || !map->isInTheMap(int3(x, y, scene->level))) return nullptr; @@ -409,7 +409,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y) const //visitable is most important for(auto & object : objects) { - if(!object.obj) + if(!object.obj || object.obj == ignore) continue; if(object.obj->visitableAt(x, y)) @@ -421,7 +421,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y) const //if not visitable tile - try to get blocked for(auto & object : objects) { - if(!object.obj) + if(!object.obj || object.obj == ignore) continue; if(object.obj->blockingAt(x, y)) @@ -433,7 +433,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y) const //finally, we can take any object for(auto & object : objects) { - if(!object.obj) + if(!object.obj || object.obj == ignore) continue; if(object.obj->coveringAt(x, y)) diff --git a/mapeditor/scenelayer.h b/mapeditor/scenelayer.h index 7b99b4df1..848c64d99 100644 --- a/mapeditor/scenelayer.h +++ b/mapeditor/scenelayer.h @@ -138,7 +138,7 @@ public: void draw(); - CGObjectInstance * selectObjectAt(int x, int y) const; + CGObjectInstance * selectObjectAt(int x, int y, const CGObjectInstance * ignore = nullptr) const; void selectObjects(int x1, int y1, int x2, int y2); void selectObject(CGObjectInstance *, bool inform = true); void deselectObject(CGObjectInstance *); From e6f459cbe48f108f04b905c1fd0a9e492f6541d3 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Tue, 27 Dec 2022 04:04:09 +0400 Subject: [PATCH 2/2] Address naming questions --- mapeditor/mapcontroller.cpp | 10 +++++----- mapeditor/mapview.cpp | 16 +++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index 82d554b87..efd3d54d3 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -344,12 +344,12 @@ void MapController::pasteFromClipboard(int level) if(_clipboardShiftIndex == int3::getDirs().size()) _clipboardShiftIndex = 0; - for(auto & objuptr : _clipboard) + for(auto & objUniquePtr : _clipboard) { - auto * obj = CMemorySerializer::deepCopy(*objuptr).release(); - auto newpos = objuptr->pos + shift; - if(_map->isInTheMap(newpos)) - obj->pos = newpos; + auto * obj = CMemorySerializer::deepCopy(*objUniquePtr).release(); + auto newPos = objUniquePtr->pos + shift; + if(_map->isInTheMap(newPos)) + obj->pos = newPos; obj->pos.z = level; Initializer init(obj, defaultPlayer); diff --git a/mapeditor/mapview.cpp b/mapeditor/mapview.cpp index 6af283db3..0f162de58 100644 --- a/mapeditor/mapview.cpp +++ b/mapeditor/mapview.cpp @@ -269,15 +269,17 @@ void MapView::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { - auto * obj = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y); - auto * obj2 = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y, obj); - if(obj) + //when paste, new object could be beyond initial object so we need to test two objects in order to select new one + //if object is pasted at place where is multiple objects then proper selection is not guaranteed + auto * firstSelectedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y); + auto * secondSelectedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y, firstSelectedObject); + if(firstSelectedObject) { - if(sc->selectionObjectsView.isSelected(obj)) + if(sc->selectionObjectsView.isSelected(firstSelectedObject)) { if(qApp->keyboardModifiers() & Qt::ControlModifier) { - sc->selectionObjectsView.deselectObject(obj); + sc->selectionObjectsView.deselectObject(firstSelectedObject); sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION; } else @@ -285,11 +287,11 @@ void MapView::mousePressEvent(QMouseEvent *event) } else { - if(!obj2 || !sc->selectionObjectsView.isSelected(obj2)) + if(!secondSelectedObject || !sc->selectionObjectsView.isSelected(secondSelectedObject)) { if(!(qApp->keyboardModifiers() & Qt::ControlModifier)) sc->selectionObjectsView.clear(); - sc->selectionObjectsView.selectObject(obj); + sc->selectionObjectsView.selectObject(firstSelectedObject); } sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT; }