2025-12-20 16:38:51 +03:00
|
|
|
#include "BookmarkManager.hpp"
|
|
|
|
|
#include "../World.hpp"
|
|
|
|
|
#include "../MainProgram.hpp"
|
2025-12-23 17:17:33 +03:00
|
|
|
#include "BookmarkListItem.hpp"
|
2025-12-21 00:33:04 +03:00
|
|
|
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
|
|
|
|
|
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
|
2026-01-02 09:22:52 +03:00
|
|
|
#include <cereal/types/unordered_map.hpp>
|
2025-12-20 16:38:51 +03:00
|
|
|
|
|
|
|
|
BookmarkManager::BookmarkManager(World& w):
|
|
|
|
|
world(w)
|
|
|
|
|
{}
|
|
|
|
|
|
2026-01-01 22:46:02 +03:00
|
|
|
void BookmarkManager::server_init_no_file() {
|
|
|
|
|
bookmarkListRoot = world.netObjMan.make_obj_from_ptr<BookmarkListItem>(new BookmarkListItem(world.netObjMan, "ROOT", true, {}));
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BookmarkManager::refresh_gui_data() {
|
|
|
|
|
selectionData = GUIStuff::TreeListing::SelectionData();
|
2026-01-03 13:35:24 +03:00
|
|
|
editing_bookmark_check();
|
2025-12-23 17:17:33 +03:00
|
|
|
nameToEdit.clear();
|
|
|
|
|
nameForNew.clear();
|
2025-12-20 16:38:51 +03:00
|
|
|
}
|
|
|
|
|
|
2025-12-21 00:33:04 +03:00
|
|
|
void BookmarkManager::setup_list_gui(const std::string& id) {
|
|
|
|
|
using namespace NetworkingObjects;
|
|
|
|
|
if(bookmarkListRoot) {
|
|
|
|
|
auto& gui = world.main.toolbar.gui;
|
2025-12-23 17:17:33 +03:00
|
|
|
gui.push_id(id);
|
2025-12-24 12:42:27 +03:00
|
|
|
if(bookmarkListRoot->get_folder_list()->empty()) {
|
|
|
|
|
gui.text_label_centered("No bookmarks yet...");
|
|
|
|
|
selectionData = GUIStuff::TreeListing::SelectionData();
|
|
|
|
|
oldSelection.clear();
|
|
|
|
|
nameToEdit.clear();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
std::optional<NetObjID> toDeleteParent;
|
|
|
|
|
std::optional<NetObjID> toDeleteObject;
|
|
|
|
|
gui.tree_listing("list", bookmarkListRoot.get_net_id(), GUIStuff::TreeListing::DisplayData{
|
|
|
|
|
.getObjInListAtIndex = [&](NetObjID parentId, size_t index) -> std::optional<GUIStuff::TreeListing::DisplayData::ObjInList> {
|
|
|
|
|
NetObjOrderedList<BookmarkListItem>& bookmarkParentFolder = *world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(parentId)->get_folder_list();
|
|
|
|
|
if(bookmarkParentFolder.size() <= index)
|
|
|
|
|
return std::nullopt;
|
2025-12-30 19:46:08 +03:00
|
|
|
auto itemAtIndex = bookmarkParentFolder.at(index);
|
2025-12-24 12:42:27 +03:00
|
|
|
return GUIStuff::TreeListing::DisplayData::ObjInList{
|
2025-12-30 19:46:08 +03:00
|
|
|
.id = itemAtIndex->obj.get_net_id(),
|
|
|
|
|
.isDirectory = itemAtIndex->obj->is_folder(),
|
|
|
|
|
.isDirectoryOpen = itemAtIndex->obj->is_folder() ? itemAtIndex->obj->is_folder_open() : false
|
2025-12-24 12:42:27 +03:00
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
.getIndexOfObjInList = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
|
|
|
|
|
return world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(idPair.parent)->get_folder_list()->get(idPair.object)->pos;
|
|
|
|
|
},
|
|
|
|
|
.setDirectoryOpen = [&](NetObjID netID, bool newDirectoryOpen) {
|
|
|
|
|
world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(netID)->set_folder_open(newDirectoryOpen);
|
|
|
|
|
},
|
|
|
|
|
.drawNonDirectoryObjIconGUI = [&](NetObjID netID) {
|
|
|
|
|
CLAY_AUTO_ID({
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
|
|
|
|
.padding = CLAY_PADDING_ALL(2),
|
|
|
|
|
},
|
|
|
|
|
}) {
|
|
|
|
|
gui.svg_icon("bookmark ico", "data/icons/bookmark.svg");
|
2025-12-23 14:10:33 +03:00
|
|
|
}
|
2025-12-24 12:42:27 +03:00
|
|
|
return false;
|
|
|
|
|
},
|
|
|
|
|
.drawObjGUI = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
|
|
|
|
|
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(idPair.object);
|
2025-12-25 17:18:28 +03:00
|
|
|
bool isButtonClicked = false;
|
2025-12-24 12:42:27 +03:00
|
|
|
if(Clay_Hovered() && gui.io->mouse.leftClick >= 2 && !tempPtr->is_folder() && selectionData.objsSelected.contains(idPair.object) && !gui.io->key.leftCtrl && !gui.io->key.leftShift)
|
|
|
|
|
tempPtr->get_bookmark_data().jump_to(world);
|
|
|
|
|
CLAY_AUTO_ID({
|
|
|
|
|
.layout = {
|
|
|
|
|
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
|
|
|
|
|
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
|
|
|
|
|
},
|
|
|
|
|
}) {
|
|
|
|
|
gui.text_label(tempPtr->get_name());
|
2025-12-23 14:10:33 +03:00
|
|
|
}
|
2025-12-24 12:42:27 +03:00
|
|
|
if(!tempPtr->is_folder() && gui.svg_icon_button_transparent("jump button", "data/icons/jump.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
|
|
|
|
|
tempPtr->get_bookmark_data().jump_to(world);
|
2025-12-25 17:18:28 +03:00
|
|
|
isButtonClicked = true;
|
2025-12-23 14:10:33 +03:00
|
|
|
}
|
2025-12-24 12:42:27 +03:00
|
|
|
if(gui.svg_icon_button_transparent("delete button", "data/icons/trash.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
|
|
|
|
|
toDeleteParent = idPair.parent;
|
|
|
|
|
toDeleteObject = idPair.object;
|
2025-12-25 17:18:28 +03:00
|
|
|
isButtonClicked = true;
|
2025-12-24 12:42:27 +03:00
|
|
|
}
|
2025-12-25 17:18:28 +03:00
|
|
|
return isButtonClicked;
|
2025-12-24 12:42:27 +03:00
|
|
|
},
|
|
|
|
|
.moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector<GUIStuff::TreeListing::ParentObjectIDPair>& objsToInsert) {
|
|
|
|
|
world.netObjMan.send_multi_update_messsage([&]() {
|
2025-12-30 19:46:08 +03:00
|
|
|
std::unordered_map<NetObjID, std::vector<NetObjOrderedListIterator<BookmarkListItem>>> toEraseMap;
|
2025-12-24 12:42:27 +03:00
|
|
|
uint32_t newIndex = index;
|
|
|
|
|
std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
|
|
|
|
|
auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listObj)->get_folder_list();
|
2025-12-23 17:17:33 +03:00
|
|
|
|
2025-12-24 12:42:27 +03:00
|
|
|
for(size_t i = 0; i < objsToInsert.size(); i++) {
|
2025-12-30 19:46:08 +03:00
|
|
|
auto& parentListPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(objsToInsert[i].parent)->get_folder_list();
|
|
|
|
|
toEraseMap[objsToInsert[i].parent].emplace_back(parentListPtr->get(objsToInsert[i].object));
|
2025-12-24 12:42:27 +03:00
|
|
|
if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index)
|
|
|
|
|
newIndex--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
|
|
|
|
|
auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
|
2025-12-30 19:46:08 +03:00
|
|
|
listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
|
2025-12-24 12:42:27 +03:00
|
|
|
}
|
|
|
|
|
|
2025-12-30 19:46:08 +03:00
|
|
|
std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
|
|
|
|
|
auto insertIt = listPtr->at(newIndex);
|
2025-12-24 12:42:27 +03:00
|
|
|
for(uint32_t i = 0; i < objsToInsert.size(); i++) {
|
|
|
|
|
auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [id = objsToInsert[i].object](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
|
|
|
|
|
return objPtr.get_net_id() == id;
|
|
|
|
|
});
|
2025-12-30 19:46:08 +03:00
|
|
|
toInsert.emplace_back(insertIt, std::move(*it));
|
2025-12-24 12:42:27 +03:00
|
|
|
toInsert.back().second.reassign_ids();
|
|
|
|
|
}
|
|
|
|
|
listPtr->insert_ordered_list_and_send_create(listPtr, toInsert);
|
|
|
|
|
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}, selectionData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(selectionData.objsSelected != oldSelection) {
|
2026-01-03 13:35:24 +03:00
|
|
|
editing_bookmark_check();
|
2025-12-24 12:42:27 +03:00
|
|
|
if(selectionData.objsSelected.size() == 1) {
|
|
|
|
|
NetObjTemporaryPtr<BookmarkListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(*selectionData.objsSelected.begin());
|
|
|
|
|
if(tempPtr)
|
|
|
|
|
nameToEdit = tempPtr->get_name();
|
2026-01-03 13:35:24 +03:00
|
|
|
else
|
2025-12-24 12:42:27 +03:00
|
|
|
nameToEdit.clear();
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
2025-12-24 12:42:27 +03:00
|
|
|
else
|
|
|
|
|
nameToEdit.clear();
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 13:35:24 +03:00
|
|
|
if(toDeleteObject.has_value())
|
|
|
|
|
remove_bookmark(toDeleteParent.value(), toDeleteObject.value());
|
2025-12-21 00:33:04 +03:00
|
|
|
}
|
2025-12-23 17:17:33 +03:00
|
|
|
|
|
|
|
|
gui.left_to_right_line_layout([&]() {
|
|
|
|
|
bool addByEnter = false;
|
|
|
|
|
gui.input_text("input new name", &nameForNew, true, [&](GUIStuff::SelectionHelper& s) {
|
|
|
|
|
addByEnter = s.selected && gui.io->key.enter;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(gui.svg_icon_button("create new bookmark", "data/icons/plusbold.svg", false, gui.SMALL_BUTTON_SIZE) || addByEnter)
|
2026-01-03 13:35:24 +03:00
|
|
|
create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, false, {world.drawData.cam.c, world.main.window.size.cast<int32_t>()}));
|
2025-12-23 17:17:33 +03:00
|
|
|
else if(gui.svg_icon_button("create new folder", "data/icons/folderbold.svg", false, gui.SMALL_BUTTON_SIZE)) {
|
2026-01-03 13:35:24 +03:00
|
|
|
auto newFolderObjInfo = create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, true, {}));
|
2025-12-23 17:17:33 +03:00
|
|
|
newFolderObjInfo->obj->set_folder_open(true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(selectionData.objsSelected.size() == 1) {
|
|
|
|
|
NetObjTemporaryPtr<BookmarkListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(*selectionData.objsSelected.begin());
|
|
|
|
|
if(tempPtr) {
|
|
|
|
|
gui.text_label_centered(tempPtr->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
|
|
|
|
|
gui.input_text_field("input edit name", "Name", &nameToEdit);
|
2025-12-24 12:42:27 +03:00
|
|
|
tempPtr->set_name(world.delayedUpdateObjectManager, nameToEdit);
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gui.pop_id();
|
2025-12-21 00:33:04 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-03 13:35:24 +03:00
|
|
|
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>> BookmarkManager::try_to_create_in_proper_position(BookmarkListItem* newItem) {
|
2025-12-23 17:17:33 +03:00
|
|
|
using namespace NetworkingObjects;
|
|
|
|
|
if(selectionData.orderedObjsSelected.empty())
|
2025-12-30 19:46:08 +03:00
|
|
|
return std::nullopt;
|
2025-12-23 17:17:33 +03:00
|
|
|
auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back();
|
|
|
|
|
NetObjTemporaryPtr<BookmarkListItem> parentPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(backObjParentObjectPair.parent);
|
|
|
|
|
if(!parentPtr)
|
2025-12-30 19:46:08 +03:00
|
|
|
return std::nullopt;
|
2025-12-23 17:17:33 +03:00
|
|
|
NetObjTemporaryPtr<BookmarkListItem> objectPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(backObjParentObjectPair.object);
|
|
|
|
|
if(!objectPtr)
|
2025-12-30 19:46:08 +03:00
|
|
|
return std::nullopt;
|
2025-12-23 17:17:33 +03:00
|
|
|
if(objectPtr->is_folder()) {
|
|
|
|
|
objectPtr->set_folder_open(true);
|
2026-01-03 13:35:24 +03:00
|
|
|
return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>{objectPtr.get_net_id(), objectPtr->get_folder_list()->push_back_and_send_create(objectPtr->get_folder_list(), newItem)};
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
2026-01-03 13:35:24 +03:00
|
|
|
return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>{parentPtr.get_net_id(), parentPtr->get_folder_list()->insert_and_send_create(parentPtr->get_folder_list(), std::next(parentPtr->get_folder_list()->get(objectPtr.get_net_id())), newItem)};
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 13:35:24 +03:00
|
|
|
std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>> BookmarkManager::create_in_proper_position(BookmarkListItem* newItem) {
|
2025-12-23 17:17:33 +03:00
|
|
|
auto toRet = try_to_create_in_proper_position(newItem);
|
|
|
|
|
if(!toRet)
|
2026-01-03 13:35:24 +03:00
|
|
|
return {bookmarkListRoot.get_net_id(), bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), newItem)};
|
2025-12-30 19:46:08 +03:00
|
|
|
return toRet.value();
|
2025-12-23 17:17:33 +03:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 13:35:24 +03:00
|
|
|
NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem> BookmarkManager::create_bookmark(BookmarkListItem* newItem) {
|
|
|
|
|
class AddBookmarkWorldUndoAction : public WorldUndoAction {
|
|
|
|
|
public:
|
|
|
|
|
AddBookmarkWorldUndoAction(const BookmarkCompleteUndoData& initBookmarkData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
|
|
|
|
|
bookmarkData(initBookmarkData),
|
|
|
|
|
pos(newPos),
|
|
|
|
|
parentUndoID(initParentUndoID),
|
|
|
|
|
undoID(initUndoID)
|
|
|
|
|
{}
|
|
|
|
|
std::string get_name() const override {
|
|
|
|
|
return bookmarkData.folderList ? "Add Bookmark Folder" : "Add Bookmark";
|
|
|
|
|
}
|
|
|
|
|
bool undo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toEraseParentID = undoMan.get_netid_from_undoid(parentUndoID);
|
|
|
|
|
if(!toEraseParentID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toEraseID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(!toEraseID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto& bookmarkList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toEraseParentID.value())->get_folder_list();
|
|
|
|
|
bookmarkList->erase(bookmarkList, bookmarkList->get(toEraseID.value()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
bool redo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toInsertParentID = undoMan.get_netid_from_undoid(parentUndoID);
|
|
|
|
|
if(!toInsertParentID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toInsertID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(toInsertID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto& bookmarkList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toInsertParentID.value())->get_folder_list();
|
|
|
|
|
auto insertedIt = bookmarkList->emplace_direct(bookmarkList, bookmarkList->at(pos), undoMan.world, bookmarkData);
|
|
|
|
|
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
void scale_up(const WorldScalar& scaleAmount) override {
|
|
|
|
|
bookmarkData.scale_up(scaleAmount);
|
|
|
|
|
}
|
|
|
|
|
~AddBookmarkWorldUndoAction() {}
|
|
|
|
|
|
|
|
|
|
BookmarkCompleteUndoData bookmarkData;
|
|
|
|
|
uint32_t pos;
|
|
|
|
|
WorldUndoManager::UndoObjectID parentUndoID;
|
|
|
|
|
WorldUndoManager::UndoObjectID undoID;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto insertedBookmarkPair = create_in_proper_position(newItem);
|
|
|
|
|
auto& it = insertedBookmarkPair.second;
|
|
|
|
|
world.undo.push(std::make_unique<AddBookmarkWorldUndoAction>(it->obj->get_complete_undo_data(world.undo), it->pos, world.undo.get_undoid_from_netid(insertedBookmarkPair.first), world.undo.get_undoid_from_netid(it->obj.get_net_id())));
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BookmarkManager::remove_bookmark(const NetworkingObjects::NetObjID& parentID, const NetworkingObjects::NetObjID& objectID) {
|
|
|
|
|
class DeleteBookmarkWorldUndoAction : public WorldUndoAction {
|
|
|
|
|
public:
|
|
|
|
|
DeleteBookmarkWorldUndoAction(const BookmarkCompleteUndoData& initBookmarkData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
|
|
|
|
|
bookmarkData(initBookmarkData),
|
|
|
|
|
pos(newPos),
|
|
|
|
|
parentUndoID(initParentUndoID),
|
|
|
|
|
undoID(initUndoID)
|
|
|
|
|
{}
|
|
|
|
|
std::string get_name() const override {
|
|
|
|
|
return bookmarkData.folderList ? "Delete Bookmark Folder" : "Delete Bookmark";
|
|
|
|
|
}
|
|
|
|
|
bool undo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toInsertParentID = undoMan.get_netid_from_undoid(parentUndoID);
|
|
|
|
|
if(!toInsertParentID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toInsertID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(toInsertID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto& bookmarkList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toInsertParentID.value())->get_folder_list();
|
|
|
|
|
auto insertedIt = bookmarkList->emplace_direct(bookmarkList, bookmarkList->at(pos), undoMan.world, bookmarkData);
|
|
|
|
|
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
bool redo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toEraseParentID = undoMan.get_netid_from_undoid(parentUndoID);
|
|
|
|
|
if(!toEraseParentID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toEraseID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(!toEraseID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
auto& bookmarkList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toEraseParentID.value())->get_folder_list();
|
|
|
|
|
bookmarkList->erase(bookmarkList, bookmarkList->get(toEraseID.value()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
void scale_up(const WorldScalar& scaleAmount) override {
|
|
|
|
|
bookmarkData.scale_up(scaleAmount);
|
|
|
|
|
}
|
|
|
|
|
~DeleteBookmarkWorldUndoAction() {}
|
|
|
|
|
|
|
|
|
|
BookmarkCompleteUndoData bookmarkData;
|
|
|
|
|
uint32_t pos;
|
|
|
|
|
WorldUndoManager::UndoObjectID parentUndoID;
|
|
|
|
|
WorldUndoManager::UndoObjectID undoID;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(parentID)->get_folder_list();
|
|
|
|
|
auto it = folderList->get(objectID);
|
|
|
|
|
world.undo.push(std::make_unique<DeleteBookmarkWorldUndoAction>(it->obj->get_complete_undo_data(world.undo), it->pos, world.undo.get_undoid_from_netid(parentID), world.undo.get_undoid_from_netid(objectID)));
|
|
|
|
|
folderList->erase(folderList, it);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-20 16:38:51 +03:00
|
|
|
void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) {
|
2025-12-31 16:30:56 +03:00
|
|
|
bookmarkListRoot->scale_up(scaleUpAmount);
|
2025-12-20 16:38:51 +03:00
|
|
|
}
|
2026-01-01 22:46:02 +03:00
|
|
|
|
|
|
|
|
void BookmarkManager::save_file(cereal::PortableBinaryOutputArchive& a) const {
|
|
|
|
|
bookmarkListRoot->save_file(a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BookmarkManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) {
|
2026-01-02 09:22:52 +03:00
|
|
|
if(version >= VersionNumber(0, 4, 0)) {
|
|
|
|
|
bookmarkListRoot = world.netObjMan.make_obj_from_ptr<BookmarkListItem>(new BookmarkListItem());
|
|
|
|
|
bookmarkListRoot->load_file(a, version, *this);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
server_init_no_file();
|
|
|
|
|
std::unordered_map<std::string, BookmarkData> bookmarkMap;
|
|
|
|
|
std::vector<std::pair<std::string, BookmarkData>> bookmarkDataSorted;
|
|
|
|
|
a(bookmarkMap);
|
|
|
|
|
for(auto& [name, bData] : bookmarkMap)
|
|
|
|
|
bookmarkDataSorted.emplace_back(name, bData);
|
|
|
|
|
std::sort(bookmarkDataSorted.begin(), bookmarkDataSorted.end(), [](auto& aPair, auto& bPair) {
|
|
|
|
|
return aPair.first < bPair.first;
|
|
|
|
|
});
|
|
|
|
|
for(auto& [name, bData] : bookmarkDataSorted)
|
|
|
|
|
bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, name, false, bData));
|
|
|
|
|
}
|
2026-01-01 22:46:02 +03:00
|
|
|
}
|
2026-01-03 13:35:24 +03:00
|
|
|
|
|
|
|
|
void BookmarkManager::editing_bookmark_check() {
|
|
|
|
|
class EditBookmarkWorldUndoAction : public WorldUndoAction {
|
|
|
|
|
public:
|
|
|
|
|
EditBookmarkWorldUndoAction(const std::string& initNameOld, const std::string& initNameNew, WorldUndoManager::UndoObjectID initUndoID):
|
|
|
|
|
nameOld(initNameOld),
|
|
|
|
|
nameNew(initNameNew),
|
|
|
|
|
undoID(initUndoID)
|
|
|
|
|
{}
|
|
|
|
|
std::string get_name() const override {
|
|
|
|
|
return "Edit Bookmark";
|
|
|
|
|
}
|
|
|
|
|
bool undo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toModifyID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(!toModifyID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toModifyID.value());
|
|
|
|
|
objPtr->set_name(undoMan.world.delayedUpdateObjectManager, nameOld);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
bool redo(WorldUndoManager& undoMan) override {
|
|
|
|
|
std::optional<NetworkingObjects::NetObjID> toModifyID = undoMan.get_netid_from_undoid(undoID);
|
|
|
|
|
if(!toModifyID.has_value())
|
|
|
|
|
return false;
|
|
|
|
|
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toModifyID.value());
|
|
|
|
|
objPtr->set_name(undoMan.world.delayedUpdateObjectManager, nameNew);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
~EditBookmarkWorldUndoAction() {}
|
|
|
|
|
|
|
|
|
|
std::string nameOld;
|
|
|
|
|
std::string nameNew;
|
|
|
|
|
WorldUndoManager::UndoObjectID undoID;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if(oldSelection.size() == 1 && editingBookmarkName.has_value()) {
|
|
|
|
|
const NetworkingObjects::NetObjID& oldNetObjID = *oldSelection.begin();
|
|
|
|
|
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(oldNetObjID);
|
|
|
|
|
if(tempPtr) {
|
|
|
|
|
const std::string& currentNameData = tempPtr->get_name();
|
|
|
|
|
if(currentNameData != editingBookmarkName.value())
|
|
|
|
|
world.undo.push(std::make_unique<EditBookmarkWorldUndoAction>(editingBookmarkName.value(), currentNameData, world.undo.get_undoid_from_netid(oldNetObjID)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
editingBookmarkName = std::nullopt;
|
|
|
|
|
if(selectionData.objsSelected.size() == 1) {
|
|
|
|
|
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(*selectionData.objsSelected.begin());
|
|
|
|
|
if(tempPtr)
|
|
|
|
|
editingBookmarkName = tempPtr->get_name();
|
|
|
|
|
}
|
|
|
|
|
oldSelection = selectionData.objsSelected;
|
|
|
|
|
}
|