Started work on new undo system
This commit is contained in:
parent
da3a764ae9
commit
be2ba1e285
8 changed files with 182 additions and 4 deletions
|
|
@ -49,6 +49,7 @@ set(sources "src/main.cpp"
|
|||
"src/FileHelpers.cpp"
|
||||
"src/VersionConstants.cpp"
|
||||
"src/ScaleUpCanvas.cpp"
|
||||
"src/WorldUndoManager.cpp"
|
||||
"src/Bookmarks/BookmarkListItem.cpp"
|
||||
"src/Bookmarks/BookmarkManager.cpp"
|
||||
"src/ResourceDisplay/ResourceDisplay.cpp"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ namespace NetworkingObjects {
|
|||
bool NetObjManager::is_connected() const {
|
||||
return (server && !server->is_disconnected()) || (client && !client->is_disconnected());
|
||||
}
|
||||
void NetObjManager::set_netid_reassign_callback(const std::function<void(const NetworkingObjects::NetObjID& oldID, const NetworkingObjects::NetObjID& newID)>& newNetIDReassignCallback) {
|
||||
netIDReassignCallback = newNetIDReassignCallback;
|
||||
}
|
||||
void NetObjManager::set_netobj_destroy_callback(const std::function<void(const NetworkingObjects::NetObjID& netID)>& newDestroyCallback) {
|
||||
destroyCallback = newDestroyCallback;
|
||||
}
|
||||
void NetObjManager::send_multi_update_messsage(std::function<void()> captureSendBlock, SendUpdateType updateType, const std::shared_ptr<NetServer::ClientData>& specificClient) {
|
||||
if(is_connected()) {
|
||||
std::shared_ptr<MultiUpdateData> d = std::make_shared<MultiUpdateData>();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ namespace NetworkingObjects {
|
|||
void disconnect();
|
||||
bool is_server() const;
|
||||
bool is_connected() const;
|
||||
void set_netid_reassign_callback(const std::function<void(const NetworkingObjects::NetObjID& oldID, const NetworkingObjects::NetObjID& newID)>& newNetIDReassignCallback);
|
||||
void set_netobj_destroy_callback(const std::function<void(const NetworkingObjects::NetObjID& netID)>& newDestroyCallback);
|
||||
template <typename T> NetObjOwnerPtr<T> read_create_message(cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& clientReceivedFrom) {
|
||||
NetObjID id;
|
||||
a(id);
|
||||
|
|
@ -173,5 +175,7 @@ namespace NetworkingObjects {
|
|||
std::unordered_map<NetObjID, SingleObjectData> objectData;
|
||||
NetObjManagerTypeList typeList;
|
||||
NetTypeIDType nextTypeID;
|
||||
std::function<void(const NetworkingObjects::NetObjID& oldID, const NetworkingObjects::NetObjID& newID)> netIDReassignCallback;
|
||||
std::function<void(const NetworkingObjects::NetObjID& netID)> destroyCallback;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ namespace NetworkingObjects {
|
|||
|
||||
template <typename T> NetObjOwnerPtr<T>::~NetObjOwnerPtr() {
|
||||
if(objMan && rawPtr) {
|
||||
if(objMan->destroyCallback)
|
||||
objMan->destroyCallback(id);
|
||||
auto it = objMan->objectData.find(id);
|
||||
delete static_cast<T*>(it->second.p);
|
||||
objMan->objectData.erase(it);
|
||||
|
|
@ -49,10 +51,13 @@ namespace NetworkingObjects {
|
|||
NetObjManager::SingleObjectData objData = it->second;
|
||||
objData.p = rawPtr;
|
||||
objMan->objectData.erase(it);
|
||||
NetworkingObjects::NetObjID oldID = id;
|
||||
id = NetObjID::random_gen();
|
||||
objMan->objectData.emplace(id, objData);
|
||||
if constexpr(hasReassignNetObjIds)
|
||||
rawPtr->reassign_netobj_ids_call();
|
||||
if(objMan->netIDReassignCallback)
|
||||
objMan->netIDReassignCallback(oldID, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
||||
netObjMan(!worldInfo.isClient),
|
||||
main(initMain),
|
||||
undo(*this),
|
||||
rMan(*this),
|
||||
drawProg(*this),
|
||||
bMan(*this),
|
||||
|
|
@ -45,6 +46,12 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
|||
canvasTheme(*this)
|
||||
{
|
||||
init_net_obj_type_list();
|
||||
netObjMan.set_netobj_destroy_callback([&undo = undo](const NetworkingObjects::NetObjID& idToDestroy) {
|
||||
undo.remove_by_netid(idToDestroy);
|
||||
});
|
||||
netObjMan.set_netid_reassign_callback([&undo = undo](const NetworkingObjects::NetObjID& oldID, const NetworkingObjects::NetObjID& newID) {
|
||||
undo.reassign_netid(oldID, newID);
|
||||
});
|
||||
|
||||
netSource = worldInfo.netSource;
|
||||
|
||||
|
|
@ -474,8 +481,7 @@ void World::scale_up(const WorldScalar& scaleUpAmount) {
|
|||
// This means that the scale up message must be send BEFORE the World::scale_up function is called on our end
|
||||
// if this client is the one responsible for the scale up
|
||||
drawProg.scale_up(scaleUpAmount);
|
||||
|
||||
undo.clear(); // Do last to make sure that any undo generated while scaling up is removed, as it contains outdated scale info
|
||||
undo.scale_up(scaleUpAmount);
|
||||
}
|
||||
|
||||
void World::draw(SkCanvas* canvas) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
|
||||
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
|
||||
#include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp"
|
||||
#include "UndoManager.hpp"
|
||||
#include "WorldUndoManager.hpp"
|
||||
#include "Bookmarks/BookmarkManager.hpp"
|
||||
#include "ResourceManager.hpp"
|
||||
#include "DrawingProgram/DrawingProgram.hpp"
|
||||
|
|
@ -42,7 +42,7 @@ class World {
|
|||
|
||||
MainProgram& main;
|
||||
DrawData drawData;
|
||||
UndoManager undo;
|
||||
WorldUndoManager undo;
|
||||
ResourceManager rMan;
|
||||
DrawingProgram drawProg;
|
||||
BookmarkManager bMan;
|
||||
|
|
|
|||
107
src/WorldUndoManager.cpp
Normal file
107
src/WorldUndoManager.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "WorldUndoManager.hpp"
|
||||
|
||||
void WorldUndoAction::scale_up(const WorldScalar& scaleAmount) {}
|
||||
WorldUndoAction::~WorldUndoAction() {}
|
||||
|
||||
WorldUndoManager::WorldUndoManager(World& initWorld):
|
||||
world(initWorld)
|
||||
{}
|
||||
|
||||
bool WorldUndoManager::can_undo() {
|
||||
return !undoQueue.empty();
|
||||
}
|
||||
|
||||
bool WorldUndoManager::can_redo() {
|
||||
return !redoQueue.empty();
|
||||
}
|
||||
|
||||
void WorldUndoManager::push(std::unique_ptr<WorldUndoAction> undoAction) {
|
||||
push_undo(std::move(undoAction));
|
||||
redoQueue.clear();
|
||||
}
|
||||
|
||||
void WorldUndoManager::push_undo(std::unique_ptr<WorldUndoAction> undoAction) {
|
||||
if(undoQueue.size() == UNDO_QUEUE_LIMIT)
|
||||
undoQueue.pop_front();
|
||||
undoQueue.emplace_back(std::move(undoAction));
|
||||
}
|
||||
|
||||
void WorldUndoManager::push_redo(std::unique_ptr<WorldUndoAction> undoAction) {
|
||||
if(redoQueue.size() == UNDO_QUEUE_LIMIT)
|
||||
redoQueue.pop_front();
|
||||
redoQueue.emplace_back(std::move(undoAction));
|
||||
}
|
||||
|
||||
void WorldUndoManager::undo() {
|
||||
if(undoQueue.empty())
|
||||
return;
|
||||
if(!undoQueue.back()->undo(*this))
|
||||
clear();
|
||||
else {
|
||||
push_redo(std::move(undoQueue.back()));
|
||||
undoQueue.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldUndoManager::redo() {
|
||||
if(redoQueue.empty())
|
||||
return;
|
||||
if(!redoQueue.back()->redo(*this))
|
||||
clear();
|
||||
else {
|
||||
push_undo(std::move(redoQueue.back()));
|
||||
redoQueue.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldUndoManager::clear() {
|
||||
redoQueue.clear();
|
||||
undoQueue.clear();
|
||||
}
|
||||
|
||||
void WorldUndoManager::scale_up(const WorldScalar& scaleAmount) {
|
||||
for(auto& u : undoQueue)
|
||||
u->scale_up(scaleAmount);
|
||||
for(auto& r : redoQueue)
|
||||
r->scale_up(scaleAmount);
|
||||
}
|
||||
|
||||
void WorldUndoManager::reassign_netid(const NetworkingObjects::NetObjID& oldNetObjID, const NetworkingObjects::NetObjID& newNetObjID) {
|
||||
auto netIDtoUndoIDIterator = netIDToUndoID.find(oldNetObjID);
|
||||
if(netIDtoUndoIDIterator != netIDToUndoID.end()) {
|
||||
UndoObjectID undoID = netIDtoUndoIDIterator->second;
|
||||
netIDToUndoID.erase(netIDtoUndoIDIterator);
|
||||
netIDToUndoID.emplace(newNetObjID, undoID);
|
||||
undoIDToNetID[undoID] = newNetObjID;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldUndoManager::remove_by_netid(const NetworkingObjects::NetObjID& netObjID) {
|
||||
auto netIDtoUndoIDIterator = netIDToUndoID.find(netObjID);
|
||||
if(netIDtoUndoIDIterator != netIDToUndoID.end()) {
|
||||
undoIDToNetID.erase(netIDtoUndoIDIterator->second);
|
||||
netIDToUndoID.erase(netIDtoUndoIDIterator);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldUndoManager::remove_by_undoid(UndoObjectID undoID) {
|
||||
auto undoIDtoNetIDIterator = undoIDToNetID.find(undoID);
|
||||
if(undoIDtoNetIDIterator != undoIDToNetID.end()) {
|
||||
netIDToUndoID.erase(undoIDtoNetIDIterator->second);
|
||||
undoIDToNetID.erase(undoID);
|
||||
}
|
||||
}
|
||||
|
||||
WorldUndoManager::UndoObjectID WorldUndoManager::register_new_netobj(const NetworkingObjects::NetObjID& netObjID) {
|
||||
++lastUndoObjectID;
|
||||
undoIDToNetID[lastUndoObjectID] = netObjID;
|
||||
netIDToUndoID[netObjID] = lastUndoObjectID;
|
||||
return lastUndoObjectID;
|
||||
}
|
||||
|
||||
std::optional<NetworkingObjects::NetObjID> WorldUndoManager::get_netid_from_undoid(UndoObjectID undoID) {
|
||||
auto it = undoIDToNetID.find(undoID);
|
||||
if(it == undoIDToNetID.end())
|
||||
return std::nullopt;
|
||||
return it->second;
|
||||
}
|
||||
49
src/WorldUndoManager.hpp
Normal file
49
src/WorldUndoManager.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <Helpers/NetworkingObjects/NetObjID.hpp>
|
||||
#include <unordered_map>
|
||||
#include <deque>
|
||||
|
||||
class World;
|
||||
class WorldUndoManager;
|
||||
|
||||
class WorldUndoAction {
|
||||
public:
|
||||
virtual bool undo(WorldUndoManager& undoMan) = 0;
|
||||
virtual bool redo(WorldUndoManager& undoMan) = 0;
|
||||
virtual void scale_up(const WorldScalar& scaleAmount);
|
||||
virtual ~WorldUndoAction();
|
||||
};
|
||||
|
||||
class WorldUndoManager {
|
||||
public:
|
||||
typedef uint64_t UndoObjectID;
|
||||
WorldUndoManager(World& initWorld);
|
||||
|
||||
void push(std::unique_ptr<WorldUndoAction> undoAction);
|
||||
void undo();
|
||||
void redo();
|
||||
void clear();
|
||||
bool can_undo();
|
||||
bool can_redo();
|
||||
void scale_up(const WorldScalar& scaleAmount);
|
||||
|
||||
void reassign_netid(const NetworkingObjects::NetObjID& oldNetObjID, const NetworkingObjects::NetObjID& newNetObjID);
|
||||
void remove_by_netid(const NetworkingObjects::NetObjID& netObjID);
|
||||
void remove_by_undoid(UndoObjectID undoID);
|
||||
UndoObjectID register_new_netobj(const NetworkingObjects::NetObjID& netObjID);
|
||||
std::optional<NetworkingObjects::NetObjID> get_netid_from_undoid(UndoObjectID undoID);
|
||||
|
||||
World& world;
|
||||
private:
|
||||
void push_undo(std::unique_ptr<WorldUndoAction> undoAction);
|
||||
void push_redo(std::unique_ptr<WorldUndoAction> undoAction);
|
||||
constexpr static size_t UNDO_QUEUE_LIMIT = 500;
|
||||
|
||||
std::unordered_map<UndoObjectID, NetworkingObjects::NetObjID> undoIDToNetID;
|
||||
std::unordered_map<NetworkingObjects::NetObjID, UndoObjectID> netIDToUndoID;
|
||||
std::deque<std::unique_ptr<WorldUndoAction>> undoQueue;
|
||||
std::deque<std::unique_ptr<WorldUndoAction>> redoQueue;
|
||||
|
||||
UndoObjectID lastUndoObjectID = 0;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue