mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-18 17:40:48 +02:00
First draft of undo/redo. Can move objects and undo new object placement.
Signed-off-by: Tomasz Zieliński <tomaszzielinskijedenzwielu@gmail.com>
This commit is contained in:
parent
d1471fb3ed
commit
81ec08b55e
@ -155,14 +155,17 @@ MapRect CMapOperation::extendTileAroundSafely(const int3 & centerPos) const
|
||||
}
|
||||
|
||||
|
||||
CMapUndoManager::CMapUndoManager() : undoRedoLimit(10)
|
||||
CMapUndoManager::CMapUndoManager() :
|
||||
undoRedoLimit(10),
|
||||
undoCallback([](bool, bool) {})
|
||||
{
|
||||
|
||||
//TODO: unlimited undo
|
||||
}
|
||||
|
||||
void CMapUndoManager::undo()
|
||||
{
|
||||
doOperation(undoStack, redoStack, true);
|
||||
|
||||
}
|
||||
|
||||
void CMapUndoManager::redo()
|
||||
@ -174,6 +177,7 @@ void CMapUndoManager::clearAll()
|
||||
{
|
||||
undoStack.clear();
|
||||
redoStack.clear();
|
||||
onUndoRedo();
|
||||
}
|
||||
|
||||
int CMapUndoManager::getUndoRedoLimit() const
|
||||
@ -219,6 +223,7 @@ void CMapUndoManager::doOperation(TStack & fromStack, TStack & toStack, bool doU
|
||||
}
|
||||
toStack.push_front(std::move(operation));
|
||||
fromStack.pop_front();
|
||||
onUndoRedo();
|
||||
}
|
||||
|
||||
const CMapOperation * CMapUndoManager::peek(const TStack & stack) const
|
||||
@ -227,6 +232,18 @@ const CMapOperation * CMapUndoManager::peek(const TStack & stack) const
|
||||
return stack.front().get();
|
||||
}
|
||||
|
||||
void CMapUndoManager::onUndoRedo()
|
||||
{
|
||||
//true if there's anything on the stack
|
||||
undoCallback((bool)peekUndo(), (bool)peekRedo());
|
||||
}
|
||||
|
||||
void CMapUndoManager::setUndoCallback(std::function<void(bool, bool)> functor)
|
||||
{
|
||||
undoCallback = functor;
|
||||
onUndoRedo(); //inform immediately
|
||||
}
|
||||
|
||||
CMapEditManager::CMapEditManager(CMap * map)
|
||||
: map(map), terrainSel(map), objectSel(map)
|
||||
{
|
||||
@ -322,6 +339,7 @@ void CComposedOperation::undo()
|
||||
|
||||
void CComposedOperation::redo()
|
||||
{
|
||||
//TODO: double-chekcif the order is correct
|
||||
for(auto & operation : operations)
|
||||
{
|
||||
operation->redo();
|
||||
@ -1070,7 +1088,7 @@ void CInsertObjectOperation::execute()
|
||||
|
||||
void CInsertObjectOperation::undo()
|
||||
{
|
||||
//TODO
|
||||
map->removeObject(obj);
|
||||
}
|
||||
|
||||
void CInsertObjectOperation::redo()
|
||||
@ -1083,20 +1101,24 @@ std::string CInsertObjectOperation::getLabel() const
|
||||
return "Insert Object";
|
||||
}
|
||||
|
||||
CMoveObjectOperation::CMoveObjectOperation(CMap * map, CGObjectInstance * obj, const int3 & position)
|
||||
: CMapOperation(map), obj(obj), pos(position)
|
||||
CMoveObjectOperation::CMoveObjectOperation(CMap * map, CGObjectInstance * obj, const int3 & targetPosition)
|
||||
: CMapOperation(map),
|
||||
obj(obj),
|
||||
initialPos(obj->pos),
|
||||
targetPos(targetPosition)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMoveObjectOperation::execute()
|
||||
{
|
||||
map->moveObject(obj, pos);
|
||||
map->moveObject(obj, targetPos);
|
||||
logGlobal->debug("Moved object %s to position %s", obj->instanceName, targetPos.toString());
|
||||
}
|
||||
|
||||
void CMoveObjectOperation::undo()
|
||||
{
|
||||
//TODO
|
||||
map->moveObject(obj, initialPos);
|
||||
logGlobal->debug("Moved object %s back to position %s", obj->instanceName, initialPos.toString());
|
||||
}
|
||||
|
||||
void CMoveObjectOperation::redo()
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
|
||||
/// The undo redo limit is a number which says how many undo/redo items can be saved. The default
|
||||
/// value is 10. If the value is 0, no undo/redo history will be maintained.
|
||||
|
||||
/// FIXME: unlimited undo please
|
||||
int getUndoRedoLimit() const;
|
||||
void setUndoRedoLimit(int value);
|
||||
|
||||
@ -146,6 +148,9 @@ public:
|
||||
|
||||
void addOperation(std::unique_ptr<CMapOperation> && operation); /// Client code does not need to call this method.
|
||||
|
||||
//poor man's signal
|
||||
void setUndoCallback(std::function<void(bool, bool)> functor);
|
||||
|
||||
private:
|
||||
typedef std::list<std::unique_ptr<CMapOperation> > TStack;
|
||||
|
||||
@ -155,6 +160,9 @@ private:
|
||||
TStack undoStack;
|
||||
TStack redoStack;
|
||||
int undoRedoLimit;
|
||||
|
||||
void onUndoRedo();
|
||||
std::function<void(bool allowUndo, bool allowRedo)> undoCallback;
|
||||
};
|
||||
|
||||
/// The map edit manager provides functionality for drawing terrain and placing
|
||||
@ -425,7 +433,7 @@ private:
|
||||
class CMoveObjectOperation : public CMapOperation
|
||||
{
|
||||
public:
|
||||
CMoveObjectOperation(CMap * map, CGObjectInstance * obj, const int3 & position);
|
||||
CMoveObjectOperation(CMap * map, CGObjectInstance * obj, const int3 & targetPosition);
|
||||
|
||||
void execute() override;
|
||||
void undo() override;
|
||||
@ -434,7 +442,8 @@ public:
|
||||
|
||||
private:
|
||||
CGObjectInstance * obj;
|
||||
int3 pos;
|
||||
int3 initialPos;
|
||||
int3 targetPos;
|
||||
};
|
||||
|
||||
/// The CRemoveObjectOperation class removes object from the map
|
||||
|
@ -554,6 +554,28 @@ void MainWindow::on_actionLevel_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionUndo_triggered()
|
||||
{
|
||||
QString str("Undo clicked");
|
||||
statusBar()->showMessage(str, 1000);
|
||||
|
||||
if (controller.map())
|
||||
{
|
||||
controller.undo();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRedo_triggered()
|
||||
{
|
||||
QString str("Redo clicked");
|
||||
statusBar()->showMessage(str, 1000);
|
||||
|
||||
if (controller.map())
|
||||
{
|
||||
controller.redo();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPass_triggered(bool checked)
|
||||
{
|
||||
if(controller.map())
|
||||
@ -769,3 +791,12 @@ void MainWindow::on_actionPlayers_settings_triggered()
|
||||
mapSettingsDialog->setModal(true);
|
||||
}
|
||||
|
||||
void MainWindow::enableUndo(bool enable)
|
||||
{
|
||||
ui->actionUndo->setEnabled(enable);
|
||||
}
|
||||
|
||||
void MainWindow::enableRedo(bool enable)
|
||||
{
|
||||
ui->actionRedo->setEnabled(enable);
|
||||
}
|
@ -48,6 +48,10 @@ private slots:
|
||||
void on_actionLevel_triggered();
|
||||
|
||||
void on_actionSave_triggered();
|
||||
|
||||
void on_actionUndo_triggered();
|
||||
|
||||
void on_actionRedo_triggered();
|
||||
|
||||
void on_actionPass_triggered(bool checked);
|
||||
|
||||
@ -84,6 +88,8 @@ public slots:
|
||||
void treeViewSelected(const QModelIndex &selected, const QModelIndex &deselected);
|
||||
void loadInspector(CGObjectInstance * obj);
|
||||
void mapChanged();
|
||||
void enableUndo(bool enable);
|
||||
void enableRedo(bool enable);
|
||||
|
||||
private:
|
||||
void preparePreview(const QModelIndex &index, bool createNew);
|
||||
|
@ -51,7 +51,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1024</width>
|
||||
<height>22</height>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@ -70,7 +70,15 @@
|
||||
<addaction name="actionMapSettings"/>
|
||||
<addaction name="actionPlayers_settings"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<addaction name="actionUndo"/>
|
||||
<addaction name="actionRedo"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuMap"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
@ -647,7 +655,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>271</height>
|
||||
<height>356</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -690,7 +698,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>271</height>
|
||||
<height>356</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -709,7 +717,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>271</height>
|
||||
<height>356</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -823,6 +831,37 @@
|
||||
<string>Players settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUndo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
<property name="iconText">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Z</string>
|
||||
</property>
|
||||
<property name="shortcutVisibleInContextMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRedo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Redo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Y</string>
|
||||
</property>
|
||||
<property name="shortcutVisibleInContextMenu">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
@ -833,4 +872,8 @@
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<slots>
|
||||
<signal>enableUndo(bool)</signal>
|
||||
<signal>enableRedo(bool)</signal>
|
||||
</slots>
|
||||
</ui>
|
||||
|
@ -46,6 +46,13 @@ void MapController::setMap(std::unique_ptr<CMap> cmap)
|
||||
_scenes[1].reset(new MapScene(1));
|
||||
resetMapHandler();
|
||||
sceneForceUpdate();
|
||||
|
||||
_map->getEditManager()->getUndoManager().setUndoCallback([this](bool allowUndo, bool allowRedo)
|
||||
{
|
||||
main->enableUndo(allowUndo);
|
||||
main->enableRedo(allowRedo);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void MapController::sceneForceUpdate()
|
||||
@ -211,3 +218,19 @@ void MapController::commitObjectCreate(int level)
|
||||
|
||||
main->mapChanged();
|
||||
}
|
||||
|
||||
void MapController::undo()
|
||||
{
|
||||
_map->getEditManager()->getUndoManager().undo();
|
||||
resetMapHandler();
|
||||
sceneForceUpdate();
|
||||
main->mapChanged();
|
||||
}
|
||||
|
||||
void MapController::redo()
|
||||
{
|
||||
_map->getEditManager()->getUndoManager().redo();
|
||||
resetMapHandler();
|
||||
sceneForceUpdate();
|
||||
main->mapChanged();
|
||||
}
|
@ -27,6 +27,7 @@ public:
|
||||
void sceneForceUpdate(int level);
|
||||
|
||||
void commitTerrainChange(int level, const Terrain & terrain);
|
||||
void commitObjectErase(const CGObjectInstance* obj);
|
||||
void commitObjectErase(int level);
|
||||
void commitObstacleFill(int level);
|
||||
void commitChangeWithoutRedraw();
|
||||
@ -36,6 +37,9 @@ public:
|
||||
|
||||
bool discardObject(int level) const;
|
||||
void createObject(int level, CGObjectInstance * obj) const;
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
private:
|
||||
std::unique_ptr<CMap> _map;
|
||||
|
Loading…
Reference in New Issue
Block a user