瀏覽代碼

Implemented cut copy paste

nordsoft 2 年之前
父節點
當前提交
aa120fa69f

+ 2 - 1
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)

+ 28 - 0
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);
+	}
+}
+

+ 6 - 0
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);

+ 3 - 0
mapeditor/mainwindow.ui

@@ -79,6 +79,9 @@
     </property>
     <addaction name="actionUndo"/>
     <addaction name="actionRedo"/>
+    <addaction name="actionCut"/>
+    <addaction name="actionCopy"/>
+    <addaction name="actionPaste"/>
     <addaction name="actionErase"/>
    </widget>
    <widget class="QMenu" name="menuView">

+ 43 - 0
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();

+ 5 - 0
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<std::unique_ptr<MapScene>, 2> _scenes;
 	mutable std::array<std::unique_ptr<MinimapScene>, 2> _miniscenes;
+	std::vector<std::unique_ptr<CGObjectInstance>> _clipboard;
+	int _clipboardShiftIndex = 0;
 
 	void connectScenes();
 };

+ 7 - 3
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

+ 4 - 4
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))

+ 1 - 1
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 *);