Readded bookmark menu

This commit is contained in:
Yousef Khadadeh 2026-04-06 20:16:25 +03:00
parent b7bd2efc71
commit 915fbe598b
10 changed files with 711 additions and 813 deletions

View file

@ -300,6 +300,8 @@ template <typename T> std::array<Vector<T, 2>, 4> triangle_from_rect_points(cons
}
template <typename T> std::string vec_pretty(const T& a) {
if(a.size() == 0)
return "[]";
std::stringstream ss;
ss << "[";
for(size_t i = 0; i < a.size(); i++) {

View file

@ -6,6 +6,12 @@
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
#include <cereal/types/unordered_map.hpp>
#include "../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../GUIStuff/ElementHelpers/ButtonHelpers.hpp"
#include "../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
#include "../GUIStuff/ElementHelpers/TextBoxHelpers.hpp"
#include "../GUIStuff/Elements/SVGIcon.hpp"
BookmarkManager::BookmarkManager(World& w):
world(w)
{}
@ -15,326 +21,345 @@ void BookmarkManager::server_init_no_file() {
}
void BookmarkManager::refresh_gui_data() {
selectionData = GUIStuff::TreeListing::SelectionData();
selectedBookmarkIndices.clear();
editing_bookmark_check();
oldSelection.clear();
editingBookmarkName = std::nullopt;
nameToEdit.clear();
nameForNew.clear();
world.main.g.gui.set_to_layout();
}
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> BookmarkManager::get_bookmark_parent_from_obj_index(const GUIStuff::TreeListingObjIndexList& objIndex) {
if(objIndex.empty())
throw std::runtime_error("[BookmarkManager::get_bookmark_parent_from_obj_index] Called on empty objIndex");
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> toRet = bookmarkListRoot;
for(size_t i = 0; i < objIndex.size() - 1; i++)
toRet = toRet->get_folder_list()->at(objIndex[i])->obj;
return toRet;
}
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> BookmarkManager::get_bookmark_from_obj_index(const GUIStuff::TreeListingObjIndexList& objIndex) {
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> toRet = bookmarkListRoot;
for(size_t i : objIndex)
toRet = toRet->get_folder_list()->at(i)->obj;
return toRet;
}
void BookmarkManager::setup_list_gui(const char* id) {
//using namespace NetworkingObjects;
//if(bookmarkListRoot) {
// auto& gui = world.main.toolbar.gui;
// gui.push_id(id);
// 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;
// auto itemAtIndex = bookmarkParentFolder.at(index);
// return GUIStuff::TreeListing::DisplayData::ObjInList{
// .id = itemAtIndex->obj.get_net_id(),
// .isDirectory = itemAtIndex->obj->is_folder(),
// .isDirectoryOpen = itemAtIndex->obj->is_folder() ? itemAtIndex->obj->is_folder_open() : false
// };
// },
// .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");
// }
// return false;
// },
// .drawObjGUI = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
// auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(idPair.object);
// bool isButtonClicked = false;
// 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());
// }
// 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);
// isButtonClicked = true;
// }
// if(gui.svg_icon_button_transparent("delete button", "data/icons/trash.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
// toDeleteParent = idPair.parent;
// toDeleteObject = idPair.object;
// isButtonClicked = true;
// }
// return isButtonClicked;
// },
// .moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector<GUIStuff::TreeListing::ParentObjectIDPair>& objsToInsert) {
// std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>> toEraseMapUndo;
// WorldUndoManager::UndoObjectID insertParentUndoID;
// uint32_t insertUndoPosition;
// std::vector<WorldUndoManager::UndoObjectID> insertedUndoIDs;
using namespace NetworkingObjects;
using namespace GUIStuff;
using namespace ElementHelpers;
if(bookmarkListRoot) {
auto& gui = world.main.g.gui;
if(bookmarkListRoot->get_folder_list()->empty())
text_label_centered(gui, "No bookmarks yet...");
else {
gui.element<TreeListing>("bookmark list", TreeListing::Data {
.selectedIndices = &selectedBookmarkIndices,
.dirInfo = [&](const TreeListingObjIndexList& objIndex) -> std::optional<TreeListing::DirectoryInfo> {
auto bookmark = get_bookmark_from_obj_index(objIndex);
if(!bookmark->is_folder())
return std::nullopt;
else
return TreeListing::DirectoryInfo{
.dirSize = bookmark->get_folder_list()->size(),
.isOpen = bookmark->is_folder_open()
};
},
.setDirectoryOpen = [&](const TreeListingObjIndexList& objIndex, bool newDirectoryOpen) {
get_bookmark_from_obj_index(objIndex)->set_folder_open(newDirectoryOpen);
},
.drawNonDirectoryObjIconGUI = [&](const TreeListingObjIndexList& objIndex) {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.padding = CLAY_PADDING_ALL(2),
},
}) {
gui.element<SVGIcon>("bookmark ico", "data/icons/bookmark.svg");
}
},
.drawObjGUI = [&](const TreeListingObjIndexList& objIndex) {
auto bookmark = get_bookmark_from_obj_index(objIndex);
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}
},
}) {
text_label(gui, bookmark->get_name());
}
if(!bookmark->is_folder()) {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
svg_icon_button(gui, "jump button", "data/icons/jump.svg", {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.size = TreeListing::ENTRY_HEIGHT,
.onClick = [&, bookmark] {
bookmark->get_bookmark_data().jump_to(world);
}
});
});
}
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
svg_icon_button(gui, "delete button", "data/icons/trash.svg", {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.size = TreeListing::ENTRY_HEIGHT,
.onClick = [&, objIndex] {
remove_bookmark(objIndex);
}
});
});
},
.onDoubleClick = [&](const TreeListingObjIndexList& objIndex) {
get_bookmark_from_obj_index(objIndex)->get_bookmark_data().jump_to(world);
},
.onSelectChange = [&] {
editing_bookmark_check();
if(selectedBookmarkIndices.size() == 1) {
const TreeListingObjIndexList& objIndex = *selectedBookmarkIndices.begin();
NetObjTemporaryPtr<BookmarkListItem> tempPtr = get_bookmark_from_obj_index(objIndex);
if(tempPtr)
nameToEdit = tempPtr->get_name();
else
nameToEdit.clear();
}
else
nameToEdit.clear();
},
.moveObj = [&](const std::vector<TreeListingObjIndexList>& objectIndices, const TreeListingObjIndexList& newObjIndex) {
std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>> toEraseMapUndo;
WorldUndoManager::UndoObjectID insertParentUndoID;
uint32_t insertUndoPosition;
std::vector<WorldUndoManager::UndoObjectID> insertedUndoIDs;
// world.netObjMan.send_multi_update_messsage([&]() {
// std::unordered_map<NetObjID, std::vector<NetObjOrderedListIterator<BookmarkListItem>>> toEraseMap;
// uint32_t newIndex = index;
// std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
// auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listObj)->get_folder_list();
world.netObjMan.send_multi_update_messsage([&]() {
std::unordered_map<NetObjID, std::vector<NetObjOrderedListIterator<BookmarkListItem>>> toEraseMap;
uint32_t newIndex = newObjIndex.back();
std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
auto& listPtr = get_bookmark_parent_from_obj_index(newObjIndex)->get_folder_list();
// // Map parent folders to list of objects that should be erased from them
// for(size_t i = 0; i < objsToInsert.size(); i++) {
// 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));
// if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index)
// newIndex--;
// }
// Map parent folders to list of objects that should be erased from them
for(size_t i = 0; i < objectIndices.size(); i++) {
auto parentBookmarkList = get_bookmark_parent_from_obj_index(objectIndices[i]);
toEraseMap[parentBookmarkList.get_net_id()].emplace_back(parentBookmarkList->get_folder_list()->at(objectIndices[i].back()));
if(newIndex != 0 && parentBookmarkList == listPtr && objectIndices[i].back() <= newObjIndex.back())
newIndex--;
}
// // Prepare erase map for undo
// for(auto& [parentNetID, objsToEraseList] : toEraseMap) {
// auto& undoEraseListPairForParent = toEraseMapUndo[world.undo.get_undoid_from_netid(parentNetID)];
// uint32_t i = 0;
// for(auto& objToErase : objsToEraseList) {
// undoEraseListPairForParent.first.emplace_back(objToErase->pos - i);
// undoEraseListPairForParent.second.emplace_back(world.undo.get_undoid_from_netid(objToErase->obj.get_net_id()));
// i++;
// }
// }
// Prepare erase map for undo
for(auto& [parentNetID, objsToEraseList] : toEraseMap) {
auto& undoEraseListPairForParent = toEraseMapUndo[world.undo.get_undoid_from_netid(parentNetID)];
uint32_t i = 0;
for(auto& objToErase : objsToEraseList) {
undoEraseListPairForParent.first.emplace_back(objToErase->pos - i);
undoEraseListPairForParent.second.emplace_back(world.undo.get_undoid_from_netid(objToErase->obj.get_net_id()));
i++;
}
}
// // Erase the list of objects we previously mapped to each parent, and move the erased objects to vector toInsertObjPtrs
// for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
// auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
// listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
// }
// Erase the list of objects we previously mapped to each parent, and move the erased objects to vector toInsertObjPtrs
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
}
// // Insert objects in toInsertObjPtrs into the folder we have selected
// std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
// auto insertIt = listPtr->at(newIndex);
// 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;
// });
// toInsert.emplace_back(insertIt, std::move(*it));
// toInsert.back().second.reassign_ids();
// }
// std::vector<NetObjOrderedListIterator<BookmarkListItem>> insertedIterators = listPtr->insert_sorted_list_and_send_create(listPtr, toInsert);
// Insert objects in toInsertObjPtrs into the folder we have selected
std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
auto insertIt = listPtr->at(newIndex);
for(uint32_t i = 0; i < objectIndices.size(); i++) {
auto o = get_bookmark_from_obj_index(objectIndices[i]);
auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [&o](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
return objPtr == o;
});
toInsert.emplace_back(insertIt, std::move(*it));
toInsert.back().second.reassign_ids();
}
std::vector<NetObjOrderedListIterator<BookmarkListItem>> insertedIterators = listPtr->insert_sorted_list_and_send_create(listPtr, toInsert);
// // Prepare insert list for undo
// insertParentUndoID = world.undo.get_undoid_from_netid(listObj);
// insertUndoPosition = newIndex;
// for(auto& it : insertedIterators)
// insertedUndoIDs.emplace_back(world.undo.get_undoid_from_netid(it->obj.get_net_id()));
// }, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
// Prepare insert list for undo
insertParentUndoID = world.undo.get_undoid_from_netid(listPtr.get_net_id());
insertUndoPosition = newIndex;
for(auto& it : insertedIterators)
insertedUndoIDs.emplace_back(world.undo.get_undoid_from_netid(it->obj.get_net_id()));
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
// class MoveBookmarksWorldUndoAction : public WorldUndoAction {
// public:
// // If the undo ID maps to the net id, we can also assume that the object is definitely inside the list we want to move it from, and not inside some other list
// // If it was moved to another list, there would be an undo move that would move it back to this list, and if it was moved by another player the undo id wouldnt map back to the net id, and the undo would fail
// // We can also assume all objects in all lists remain in the same order for the same reason, so no need to sort anything if it was sorted when the undo action was generated
// MoveBookmarksWorldUndoAction(const std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>>& initUndoEraseMap,
// WorldUndoManager::UndoObjectID initInsertParentUndoID,
// uint32_t initInsertPosition,
// std::vector<WorldUndoManager::UndoObjectID> initInsertedUndoIDs):
// undoEraseMap(initUndoEraseMap),
// insertParentUndoID(initInsertParentUndoID),
// insertPosition(initInsertPosition),
// insertedUndoIDs(initInsertedUndoIDs)
// {}
// std::string get_name() const override {
// return "Move Bookmarks";
// }
// bool undo(WorldUndoManager& undoMan) override {
// std::vector<NetObjOwnerPtr<BookmarkListItem>> toMoveObjs;
// std::vector<NetObjOrderedListIterator<BookmarkListItem>> toEraseList;
// NetObjTemporaryPtr<NetObjOrderedList<BookmarkListItem>> eraseListPtr;
// std::unordered_map<NetObjID, std::pair<std::vector<uint32_t>*, std::vector<NetObjID>>> toInsertToMap;
class MoveBookmarksWorldUndoAction : public WorldUndoAction {
public:
// If the undo ID maps to the net id, we can also assume that the object is definitely inside the list we want to move it from, and not inside some other list
// If it was moved to another list, there would be an undo move that would move it back to this list, and if it was moved by another player the undo id wouldnt map back to the net id, and the undo would fail
// We can also assume all objects in all lists remain in the same order for the same reason, so no need to sort anything if it was sorted when the undo action was generated
MoveBookmarksWorldUndoAction(const std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>>& initUndoEraseMap,
WorldUndoManager::UndoObjectID initInsertParentUndoID,
uint32_t initInsertPosition,
std::vector<WorldUndoManager::UndoObjectID> initInsertedUndoIDs):
undoEraseMap(initUndoEraseMap),
insertParentUndoID(initInsertParentUndoID),
insertPosition(initInsertPosition),
insertedUndoIDs(initInsertedUndoIDs)
{}
std::string get_name() const override {
return "Move Bookmarks";
}
bool undo(WorldUndoManager& undoMan) override {
std::vector<NetObjOwnerPtr<BookmarkListItem>> toMoveObjs;
std::vector<NetObjOrderedListIterator<BookmarkListItem>> toEraseList;
NetObjTemporaryPtr<NetObjOrderedList<BookmarkListItem>> eraseListPtr;
std::unordered_map<NetObjID, std::pair<std::vector<uint32_t>*, std::vector<NetObjID>>> toInsertToMap;
// {
// std::optional<NetObjID> eraseListNetID = undoMan.get_netid_from_undoid(insertParentUndoID);
// if(!eraseListNetID.has_value())
// return false;
// eraseListPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(eraseListNetID.value())->get_folder_list();
// }
{
std::optional<NetObjID> eraseListNetID = undoMan.get_netid_from_undoid(insertParentUndoID);
if(!eraseListNetID.has_value())
return false;
eraseListPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(eraseListNetID.value())->get_folder_list();
}
// {
// std::vector<NetObjID> toEraseNetIDList;
// if(!undoMan.fill_netid_list_from_undoid_list(toEraseNetIDList, insertedUndoIDs))
// return false;
// toEraseList = eraseListPtr->get_list(toEraseNetIDList);
// }
{
std::vector<NetObjID> toEraseNetIDList;
if(!undoMan.fill_netid_list_from_undoid_list(toEraseNetIDList, insertedUndoIDs))
return false;
toEraseList = eraseListPtr->get_list(toEraseNetIDList);
}
// {
// for(auto& [undoID, indexUndoIdListPair] : undoEraseMap) {
// std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(undoID);
// if(!netID.has_value())
// return false;
// auto& insertMapEntry = toInsertToMap[netID.value()];
// insertMapEntry.first = &indexUndoIdListPair.first;
// if(!undoMan.fill_netid_list_from_undoid_list(insertMapEntry.second, indexUndoIdListPair.second))
// return false;
// }
// }
{
for(auto& [undoID, indexUndoIdListPair] : undoEraseMap) {
std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(undoID);
if(!netID.has_value())
return false;
auto& insertMapEntry = toInsertToMap[netID.value()];
insertMapEntry.first = &indexUndoIdListPair.first;
if(!undoMan.fill_netid_list_from_undoid_list(insertMapEntry.second, indexUndoIdListPair.second))
return false;
}
}
// undoMan.world.netObjMan.send_multi_update_messsage([&]() {
// eraseListPtr->erase_list(eraseListPtr, toEraseList, &toMoveObjs);
undoMan.world.netObjMan.send_multi_update_messsage([&]() {
eraseListPtr->erase_list(eraseListPtr, toEraseList, &toMoveObjs);
// for(auto& [parentNetID, indexNetIDListPair] : toInsertToMap) {
// auto& parentListPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(parentNetID)->get_folder_list();
// std::vector<NetObjOrderedListIterator<BookmarkListItem>> insertIteratorList = parentListPtr->at_ordered_indices(*indexNetIDListPair.first);
// auto& insertNetIDList = indexNetIDListPair.second;
// std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
// for(auto [insertIt, netID] : std::views::zip(insertIteratorList, insertNetIDList)) {
// auto it = std::find_if(toMoveObjs.begin(), toMoveObjs.end(), [id = netID](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
// return objPtr.get_net_id() == id;
// });
// toInsert.emplace_back(insertIt, std::move(*it));
// toInsert.back().second.reassign_ids();
// }
// parentListPtr->insert_sorted_list_and_send_create(parentListPtr, toInsert);
// }
// }, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
// return true;
// }
// bool redo(WorldUndoManager& undoMan) override {
// std::unordered_map<NetObjID, std::vector<NetObjID>> toEraseMap;
// NetObjTemporaryPtr<NetObjOrderedList<BookmarkListItem>> listPtr;
// std::vector<NetObjID> objsToInsert;
for(auto& [parentNetID, indexNetIDListPair] : toInsertToMap) {
auto& parentListPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(parentNetID)->get_folder_list();
std::vector<NetObjOrderedListIterator<BookmarkListItem>> insertIteratorList = parentListPtr->at_ordered_indices(*indexNetIDListPair.first);
auto& insertNetIDList = indexNetIDListPair.second;
std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
for(auto [insertIt, netID] : std::views::zip(insertIteratorList, insertNetIDList)) {
auto it = std::find_if(toMoveObjs.begin(), toMoveObjs.end(), [id = netID](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
return objPtr.get_net_id() == id;
});
toInsert.emplace_back(insertIt, std::move(*it));
toInsert.back().second.reassign_ids();
}
parentListPtr->insert_sorted_list_and_send_create(parentListPtr, toInsert);
}
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
return true;
}
bool redo(WorldUndoManager& undoMan) override {
std::unordered_map<NetObjID, std::vector<NetObjID>> toEraseMap;
NetObjTemporaryPtr<NetObjOrderedList<BookmarkListItem>> listPtr;
std::vector<NetObjID> objsToInsert;
// {
// for(auto& [undoID, indexUndoIDListPair] : undoEraseMap) {
// std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(undoID);
// if(!netID.has_value())
// return false;
// if(!undoMan.fill_netid_list_from_undoid_list(toEraseMap[netID.value()], indexUndoIDListPair.second))
// return false;
// }
// }
{
for(auto& [undoID, indexUndoIDListPair] : undoEraseMap) {
std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(undoID);
if(!netID.has_value())
return false;
if(!undoMan.fill_netid_list_from_undoid_list(toEraseMap[netID.value()], indexUndoIDListPair.second))
return false;
}
}
// {
// std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(insertParentUndoID);
// if(!netID.has_value())
// return false;
// listPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(netID.value())->get_folder_list();
// }
{
std::optional<NetObjID> netID = undoMan.get_netid_from_undoid(insertParentUndoID);
if(!netID.has_value())
return false;
listPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(netID.value())->get_folder_list();
}
// {
// if(!undoMan.fill_netid_list_from_undoid_list(objsToInsert, insertedUndoIDs))
// return false;
// }
{
if(!undoMan.fill_netid_list_from_undoid_list(objsToInsert, insertedUndoIDs))
return false;
}
// undoMan.world.netObjMan.send_multi_update_messsage([&]() {
// std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
undoMan.world.netObjMan.send_multi_update_messsage([&]() {
std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
// for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
// auto& listToEraseFromPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
// listToEraseFromPtr->erase_list(listToEraseFromPtr, listToEraseFromPtr->get_list(setToErase), &toInsertObjPtrs);
// }
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
auto& listToEraseFromPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
listToEraseFromPtr->erase_list(listToEraseFromPtr, listToEraseFromPtr->get_list(setToErase), &toInsertObjPtrs);
}
// std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
// auto insertIt = listPtr->at(insertPosition);
// for(uint32_t i = 0; i < objsToInsert.size(); i++) {
// auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [id = objsToInsert[i]](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
// return objPtr.get_net_id() == id;
// });
// toInsert.emplace_back(insertIt, std::move(*it));
// toInsert.back().second.reassign_ids();
// }
// listPtr->insert_sorted_list_and_send_create(listPtr, toInsert);
// }, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
std::vector<std::pair<NetObjOrderedListIterator<BookmarkListItem>, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
auto insertIt = listPtr->at(insertPosition);
for(uint32_t i = 0; i < objsToInsert.size(); i++) {
auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [id = objsToInsert[i]](NetObjOwnerPtr<BookmarkListItem>& objPtr) {
return objPtr.get_net_id() == id;
});
toInsert.emplace_back(insertIt, std::move(*it));
toInsert.back().second.reassign_ids();
}
listPtr->insert_sorted_list_and_send_create(listPtr, toInsert);
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
return true;
}
~MoveBookmarksWorldUndoAction() {}
// return true;
// }
// ~MoveBookmarksWorldUndoAction() {}
std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>> undoEraseMap;
WorldUndoManager::UndoObjectID insertParentUndoID;
uint32_t insertPosition;
std::vector<WorldUndoManager::UndoObjectID> insertedUndoIDs;
};
world.undo.push(std::make_unique<MoveBookmarksWorldUndoAction>(toEraseMapUndo, insertParentUndoID, insertUndoPosition, insertedUndoIDs));
}
});
// std::unordered_map<WorldUndoManager::UndoObjectID, std::pair<std::vector<uint32_t>, std::vector<WorldUndoManager::UndoObjectID>>> undoEraseMap;
// WorldUndoManager::UndoObjectID insertParentUndoID;
// uint32_t insertPosition;
// std::vector<WorldUndoManager::UndoObjectID> insertedUndoIDs;
// };
// world.undo.push(std::make_unique<MoveBookmarksWorldUndoAction>(toEraseMapUndo, insertParentUndoID, insertUndoPosition, insertedUndoIDs));
// }
// }, selectionData);
}
left_to_right_line_layout(gui, [&]() {
input_text(gui, "input new name", &nameForNew, {
.onEnter = [&] {
create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, false, {world.drawData.cam.c, world.main.window.size.cast<int32_t>()}));
}
});
// if(selectionData.objsSelected != oldSelection) {
// editing_bookmark_check();
// 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();
// else
// nameToEdit.clear();
// }
// else
// nameToEdit.clear();
// }
svg_icon_button(gui, "create new bookmark", "data/icons/plusbold.svg", {
.size = SMALL_BUTTON_SIZE,
.onClick = [&] {
create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, false, {world.drawData.cam.c, world.main.window.size.cast<int32_t>()}));
}
});
// if(toDeleteObject.has_value())
// remove_bookmark(toDeleteParent.value(), toDeleteObject.value());
// }
svg_icon_button(gui, "create new folder", "data/icons/folderbold.svg", {
.size = SMALL_BUTTON_SIZE,
.onClick = [&] {
auto newFolderObjInfo = create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, true, {}));
newFolderObjInfo->obj->set_folder_open(true);
}
});
});
// 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)
// create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, false, {world.drawData.cam.c, world.main.window.size.cast<int32_t>()}));
// else if(gui.svg_icon_button("create new folder", "data/icons/folderbold.svg", false, gui.SMALL_BUTTON_SIZE)) {
// auto newFolderObjInfo = create_bookmark(new BookmarkListItem(world.netObjMan, nameForNew, true, {}));
// 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);
// tempPtr->set_name(world.delayedUpdateObjectManager, nameToEdit);
// }
// }
// gui.pop_id();
//}
if(editingBookmark) {
text_label_centered(gui, editingBookmark->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
input_text_field(gui, "input edit name", "Name", &nameToEdit, {
.onEdit = [&] {
if(editingBookmark) { // This can be set to null on the way here (close bookmark popup when textbox is selected)
editingBookmark->set_name(world.delayedUpdateObjectManager, nameToEdit);
world.main.g.gui.set_to_layout();
}
}
});
}
}
}
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>> BookmarkManager::try_to_create_in_proper_position(BookmarkListItem* newItem) {
using namespace NetworkingObjects;
if(selectionData.orderedObjsSelected.empty())
return std::nullopt;
auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back();
NetObjTemporaryPtr<BookmarkListItem> parentPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(backObjParentObjectPair.parent);
if(!parentPtr)
return std::nullopt;
NetObjTemporaryPtr<BookmarkListItem> objectPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(backObjParentObjectPair.object);
if(!objectPtr)
if(selectedBookmarkIndices.empty())
return std::nullopt;
auto& lastObjSelected = *selectedBookmarkIndices.rbegin();
NetObjTemporaryPtr<BookmarkListItem> objectPtr = get_bookmark_from_obj_index(lastObjSelected);
if(objectPtr->is_folder()) {
objectPtr->set_folder_open(true);
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)};
}
NetObjTemporaryPtr<BookmarkListItem> parentPtr = get_bookmark_parent_from_obj_index(lastObjSelected);
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)};
}
@ -399,10 +424,13 @@ NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem> BookmarkManager::
auto insertedBookmarkPair = create_in_proper_position(newItem);
auto& it = insertedBookmarkPair.second;
world.undo.push(std::make_unique<AddBookmarkWorldUndoAction>(it->pos, world.undo.get_undoid_from_netid(insertedBookmarkPair.first), world.undo.get_undoid_from_netid(it->obj.get_net_id())));
world.main.g.gui.set_to_layout();
return it;
}
void BookmarkManager::remove_bookmark(const NetworkingObjects::NetObjID& parentID, const NetworkingObjects::NetObjID& objectID) {
void BookmarkManager::remove_bookmark(const GUIStuff::TreeListingObjIndexList& objIndex) {
editing_bookmark_check();
class DeleteBookmarkWorldUndoAction : public WorldUndoAction {
public:
DeleteBookmarkWorldUndoAction(std::unique_ptr<BookmarkCompleteUndoData> initBookmarkData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
@ -454,10 +482,12 @@ void BookmarkManager::remove_bookmark(const NetworkingObjects::NetObjID& parentI
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>(std::make_unique<BookmarkCompleteUndoData>(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);
auto parentPtr = get_bookmark_parent_from_obj_index(objIndex);
auto bookmarkPtr = get_bookmark_from_obj_index(objIndex);
auto it = parentPtr->get_folder_list()->get(bookmarkPtr.get_net_id());
world.undo.push(std::make_unique<DeleteBookmarkWorldUndoAction>(std::make_unique<BookmarkCompleteUndoData>(bookmarkPtr->get_complete_undo_data(world.undo)), it->pos, world.undo.get_undoid_from_netid(parentPtr.get_net_id()), world.undo.get_undoid_from_netid(bookmarkPtr.get_net_id())));
parentPtr->get_folder_list()->erase(parentPtr->get_folder_list(), it);
world.main.g.gui.set_to_layout();
}
void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) {
@ -520,20 +550,18 @@ void BookmarkManager::editing_bookmark_check() {
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(), world.undo.get_undoid_from_netid(oldNetObjID)));
}
if(editingBookmark) {
const std::string& currentNameData = editingBookmark->get_name();
if(currentNameData != editingBookmarkOldName.value())
world.undo.push(std::make_unique<EditBookmarkWorldUndoAction>(editingBookmarkOldName.value(), world.undo.get_undoid_from_netid(editingBookmark.get_net_id())));
}
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();
if(selectedBookmarkIndices.size() == 1) {
editingBookmark = get_bookmark_from_obj_index(*selectedBookmarkIndices.begin());
editingBookmarkOldName = editingBookmark->get_name();
}
else {
editingBookmark = NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>();
editingBookmarkOldName = std::nullopt;
}
oldSelection = selectionData.objsSelected;
}

View file

@ -20,17 +20,20 @@ class BookmarkManager {
NetworkingObjects::NetObjOwnerPtr<BookmarkListItem> bookmarkListRoot;
private:
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> get_bookmark_parent_from_obj_index(const GUIStuff::TreeListingObjIndexList& objIndex);
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> get_bookmark_from_obj_index(const GUIStuff::TreeListingObjIndexList& objIndex);
std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>> create_in_proper_position(BookmarkListItem* newItem);
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>> try_to_create_in_proper_position(BookmarkListItem* newItem);
NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem> create_bookmark(BookmarkListItem* newItem);
void remove_bookmark(const NetworkingObjects::NetObjID& parentID, const NetworkingObjects::NetObjID& objectID);
void remove_bookmark(const GUIStuff::TreeListingObjIndexList& objIndex);
GUIStuff::TreeListing::SelectionData selectionData;
std::unordered_set<NetworkingObjects::NetObjID> oldSelection;
std::string nameToEdit;
std::string nameForNew;
std::optional<std::string> editingBookmarkName;
std::set<GUIStuff::TreeListingObjIndexList> selectedBookmarkIndices;
NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem> editingBookmark;
std::optional<std::string> editingBookmarkOldName;
void editing_bookmark_check();

View file

@ -13,7 +13,6 @@ DrawingProgramLayerManagerGUI::DrawingProgramLayerManagerGUI(DrawingProgramLayer
{}
void DrawingProgramLayerManagerGUI::refresh_gui_data() {
selectionData = GUIStuff::TreeListing::SelectionData();
editing_layer_check();
oldSelection.clear();
nameToEdit.clear();
@ -359,196 +358,196 @@ void DrawingProgramLayerManagerGUI::setup_list_gui(const char* id, bool& hoverin
}
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>> DrawingProgramLayerManagerGUI::try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem) {
using namespace NetworkingObjects;
auto& world = layerMan.drawP.world;
if(selectionData.orderedObjsSelected.empty())
return std::nullopt;
auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back();
NetObjTemporaryPtr<DrawingProgramLayerListItem> parentPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(backObjParentObjectPair.parent);
if(!parentPtr)
return std::nullopt;
NetObjTemporaryPtr<DrawingProgramLayerListItem> objectPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(backObjParentObjectPair.object);
if(!objectPtr)
return std::nullopt;
if(objectPtr->is_folder()) {
objectPtr->get_folder().isFolderOpen = true;
return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>{objectPtr.get_net_id(), objectPtr->get_folder().folderList->insert_and_send_create(objectPtr->get_folder().folderList, objectPtr->get_folder().folderList->begin(), newItem)};
}
return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>{parentPtr.get_net_id(), parentPtr->get_folder().folderList->insert_and_send_create(parentPtr->get_folder().folderList, parentPtr->get_folder().folderList->get(objectPtr.get_net_id()), newItem)};
//using namespace NetworkingObjects;
//auto& world = layerMan.drawP.world;
//if(selectionData.orderedObjsSelected.empty())
// return std::nullopt;
//auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back();
//NetObjTemporaryPtr<DrawingProgramLayerListItem> parentPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(backObjParentObjectPair.parent);
//if(!parentPtr)
// return std::nullopt;
//NetObjTemporaryPtr<DrawingProgramLayerListItem> objectPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(backObjParentObjectPair.object);
//if(!objectPtr)
// return std::nullopt;
//if(objectPtr->is_folder()) {
// objectPtr->get_folder().isFolderOpen = true;
// return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>{objectPtr.get_net_id(), objectPtr->get_folder().folderList->insert_and_send_create(objectPtr->get_folder().folderList, objectPtr->get_folder().folderList->begin(), newItem)};
//}
//return std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>{parentPtr.get_net_id(), parentPtr->get_folder().folderList->insert_and_send_create(parentPtr->get_folder().folderList, parentPtr->get_folder().folderList->get(objectPtr.get_net_id()), newItem)};
}
std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>> DrawingProgramLayerManagerGUI::create_in_proper_position(DrawingProgramLayerListItem* newItem) {
auto toRet = try_to_create_in_proper_position(newItem);
if(!toRet)
return {layerMan.layerTreeRoot.get_net_id(), layerMan.layerTreeRoot->get_folder().folderList->insert_and_send_create(layerMan.layerTreeRoot->get_folder().folderList, layerMan.layerTreeRoot->get_folder().folderList->begin(), newItem)};
return toRet.value();
//auto toRet = try_to_create_in_proper_position(newItem);
//if(!toRet)
// return {layerMan.layerTreeRoot.get_net_id(), layerMan.layerTreeRoot->get_folder().folderList->insert_and_send_create(layerMan.layerTreeRoot->get_folder().folderList, layerMan.layerTreeRoot->get_folder().folderList->begin(), newItem)};
//return toRet.value();
}
NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem> DrawingProgramLayerManagerGUI::create_layer(DrawingProgramLayerListItem* newItem) {
auto& world = layerMan.drawP.world;
class AddLayerWorldUndoAction : public WorldUndoAction {
public:
AddLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemUndoData> initLayerData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
layerData(std::move(initLayerData)),
pos(newPos),
parentUndoID(initParentUndoID),
undoID(initUndoID)
{}
std::string get_name() const override {
return "Add Layer Item";
}
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& world = layerMan.drawP.world;
//class AddLayerWorldUndoAction : public WorldUndoAction {
// public:
// AddLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemUndoData> initLayerData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
// layerData(std::move(initLayerData)),
// pos(newPos),
// parentUndoID(initParentUndoID),
// undoID(initUndoID)
// {}
// std::string get_name() const override {
// return "Add Layer Item";
// }
// 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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toEraseParentID.value())->get_folder().folderList;
auto it = layerList->get(toEraseID.value());
layerData = std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(undoMan));
layerList->erase(layerList, it);
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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toEraseParentID.value())->get_folder().folderList;
// auto it = layerList->get(toEraseID.value());
// layerData = std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(undoMan));
// layerList->erase(layerList, it);
// 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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toInsertParentID.value())->get_folder().folderList;
auto insertedIt = layerList->emplace_direct(layerList, layerList->at(pos), undoMan.world, *layerData);
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
layerData = nullptr;
return true;
}
void scale_up(const WorldScalar& scaleAmount) override {
if(layerData)
layerData->scale_up(scaleAmount);
}
~AddLayerWorldUndoAction() {}
// auto& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toInsertParentID.value())->get_folder().folderList;
// auto insertedIt = layerList->emplace_direct(layerList, layerList->at(pos), undoMan.world, *layerData);
// undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
// layerData = nullptr;
// return true;
// }
// void scale_up(const WorldScalar& scaleAmount) override {
// if(layerData)
// layerData->scale_up(scaleAmount);
// }
// ~AddLayerWorldUndoAction() {}
std::unique_ptr<DrawingProgramLayerListItemUndoData> layerData;
uint32_t pos;
WorldUndoManager::UndoObjectID parentUndoID;
WorldUndoManager::UndoObjectID undoID;
};
// std::unique_ptr<DrawingProgramLayerListItemUndoData> layerData;
// uint32_t pos;
// WorldUndoManager::UndoObjectID parentUndoID;
// WorldUndoManager::UndoObjectID undoID;
//};
auto insertedLayerPair = create_in_proper_position(newItem);
auto& it = insertedLayerPair.second;
world.undo.push(std::make_unique<AddLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(world.undo)), it->pos, world.undo.get_undoid_from_netid(insertedLayerPair.first), world.undo.get_undoid_from_netid(it->obj.get_net_id())));
return it;
//auto insertedLayerPair = create_in_proper_position(newItem);
//auto& it = insertedLayerPair.second;
//world.undo.push(std::make_unique<AddLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(world.undo)), it->pos, world.undo.get_undoid_from_netid(insertedLayerPair.first), world.undo.get_undoid_from_netid(it->obj.get_net_id())));
//return it;
}
void DrawingProgramLayerManagerGUI::remove_layer(const NetworkingObjects::NetObjID& parentID, const NetworkingObjects::NetObjID& objectID) {
auto& world = layerMan.drawP.world;
class DeleteLayerWorldUndoAction : public WorldUndoAction {
public:
DeleteLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemUndoData> initLayerData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
layerData(std::move(initLayerData)),
pos(newPos),
parentUndoID(initParentUndoID),
undoID(initUndoID)
{}
std::string get_name() const override {
return "Delete Layer Item";
}
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& world = layerMan.drawP.world;
//class DeleteLayerWorldUndoAction : public WorldUndoAction {
// public:
// DeleteLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemUndoData> initLayerData, uint32_t newPos, WorldUndoManager::UndoObjectID initParentUndoID, WorldUndoManager::UndoObjectID initUndoID):
// layerData(std::move(initLayerData)),
// pos(newPos),
// parentUndoID(initParentUndoID),
// undoID(initUndoID)
// {}
// std::string get_name() const override {
// return "Delete Layer Item";
// }
// 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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toInsertParentID.value())->get_folder().folderList;
auto insertedIt = layerList->emplace_direct(layerList, layerList->at(pos), undoMan.world, *layerData);
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
layerData = nullptr;
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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toInsertParentID.value())->get_folder().folderList;
// auto insertedIt = layerList->emplace_direct(layerList, layerList->at(pos), undoMan.world, *layerData);
// undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
// layerData = nullptr;
// 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& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toEraseParentID.value())->get_folder().folderList;
auto it = layerList->get(toEraseID.value());
layerData = std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(undoMan));
layerList->erase(layerList, it);
return true;
}
void scale_up(const WorldScalar& scaleAmount) override {
if(layerData)
layerData->scale_up(scaleAmount);
}
~DeleteLayerWorldUndoAction() {}
// auto& layerList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(toEraseParentID.value())->get_folder().folderList;
// auto it = layerList->get(toEraseID.value());
// layerData = std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(undoMan));
// layerList->erase(layerList, it);
// return true;
// }
// void scale_up(const WorldScalar& scaleAmount) override {
// if(layerData)
// layerData->scale_up(scaleAmount);
// }
// ~DeleteLayerWorldUndoAction() {}
std::unique_ptr<DrawingProgramLayerListItemUndoData> layerData;
uint32_t pos;
WorldUndoManager::UndoObjectID parentUndoID;
WorldUndoManager::UndoObjectID undoID;
};
// std::unique_ptr<DrawingProgramLayerListItemUndoData> layerData;
// uint32_t pos;
// WorldUndoManager::UndoObjectID parentUndoID;
// WorldUndoManager::UndoObjectID undoID;
//};
auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(parentID)->get_folder().folderList;
auto it = folderList->get(objectID);
world.undo.push(std::make_unique<DeleteLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(world.undo)), it->pos, world.undo.get_undoid_from_netid(parentID), world.undo.get_undoid_from_netid(objectID)));
folderList->erase(folderList, it);
//auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(parentID)->get_folder().folderList;
//auto it = folderList->get(objectID);
//world.undo.push(std::make_unique<DeleteLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemUndoData>(it->obj->get_undo_data(world.undo)), it->pos, world.undo.get_undoid_from_netid(parentID), world.undo.get_undoid_from_netid(objectID)));
//folderList->erase(folderList, it);
}
void DrawingProgramLayerManagerGUI::editing_layer_check() {
auto& world = layerMan.drawP.world;
class EditLayerWorldUndoAction : public WorldUndoAction {
public:
EditLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemMetaInfo> initData, WorldUndoManager::UndoObjectID initUndoID):
data(std::move(initData)),
undoID(initUndoID)
{}
std::string get_name() const override {
return "Edit Layer";
}
bool undo(WorldUndoManager& undoMan) override {
return undo_redo(undoMan);
}
bool redo(WorldUndoManager& undoMan) override {
return undo_redo(undoMan);
}
bool undo_redo(WorldUndoManager& undoMan) {
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<DrawingProgramLayerListItem>(toModifyID.value());
auto newData = std::make_unique<DrawingProgramLayerListItemMetaInfo>(objPtr->get_metainfo());
objPtr->set_metainfo(undoMan.world.drawProg.layerMan, *data);
data = std::move(newData);
return true;
}
~EditLayerWorldUndoAction() {}
//auto& world = layerMan.drawP.world;
//class EditLayerWorldUndoAction : public WorldUndoAction {
// public:
// EditLayerWorldUndoAction(std::unique_ptr<DrawingProgramLayerListItemMetaInfo> initData, WorldUndoManager::UndoObjectID initUndoID):
// data(std::move(initData)),
// undoID(initUndoID)
// {}
// std::string get_name() const override {
// return "Edit Layer";
// }
// bool undo(WorldUndoManager& undoMan) override {
// return undo_redo(undoMan);
// }
// bool redo(WorldUndoManager& undoMan) override {
// return undo_redo(undoMan);
// }
// bool undo_redo(WorldUndoManager& undoMan) {
// 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<DrawingProgramLayerListItem>(toModifyID.value());
// auto newData = std::make_unique<DrawingProgramLayerListItemMetaInfo>(objPtr->get_metainfo());
// objPtr->set_metainfo(undoMan.world.drawProg.layerMan, *data);
// data = std::move(newData);
// return true;
// }
// ~EditLayerWorldUndoAction() {}
std::unique_ptr<DrawingProgramLayerListItemMetaInfo> data;
WorldUndoManager::UndoObjectID undoID;
};
// std::unique_ptr<DrawingProgramLayerListItemMetaInfo> data;
// WorldUndoManager::UndoObjectID undoID;
//};
if(oldSelection.size() == 1 && editingData.has_value()) {
const NetworkingObjects::NetObjID& oldNetObjID = *oldSelection.begin();
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(oldNetObjID);
if(tempPtr) {
const DrawingProgramLayerListItemMetaInfo& currentMetaData = tempPtr->get_metainfo();
if(currentMetaData != editingData.value())
world.undo.push(std::make_unique<EditLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemMetaInfo>(editingData.value()), world.undo.get_undoid_from_netid(oldNetObjID)));
}
}
editingData = std::nullopt;
if(selectionData.objsSelected.size() == 1) {
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
if(tempPtr)
editingData = tempPtr->get_metainfo();
}
oldSelection = selectionData.objsSelected;
//if(oldSelection.size() == 1 && editingData.has_value()) {
// const NetworkingObjects::NetObjID& oldNetObjID = *oldSelection.begin();
// auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(oldNetObjID);
// if(tempPtr) {
// const DrawingProgramLayerListItemMetaInfo& currentMetaData = tempPtr->get_metainfo();
// if(currentMetaData != editingData.value())
// world.undo.push(std::make_unique<EditLayerWorldUndoAction>(std::make_unique<DrawingProgramLayerListItemMetaInfo>(editingData.value()), world.undo.get_undoid_from_netid(oldNetObjID)));
// }
//}
//editingData = std::nullopt;
//if(selectionData.objsSelected.size() == 1) {
// auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
// if(tempPtr)
// editingData = tempPtr->get_metainfo();
//}
//oldSelection = selectionData.objsSelected;
}

View file

@ -20,7 +20,6 @@ class DrawingProgramLayerManagerGUI {
void remove_layer(const NetworkingObjects::NetObjID& parentID, const NetworkingObjects::NetObjID& objectID);
void editing_layer_check();
GUIStuff::TreeListing::SelectionData selectionData;
std::unordered_set<NetworkingObjects::NetObjID> oldSelection;
std::string nameToEdit;
std::string nameForNew;

View file

@ -1,284 +1,147 @@
#include "TreeListing.hpp"
#include "../GUIManager.hpp"
#include "Helpers/ConvertVec.hpp"
#include <chrono>
#include "../../TimePoint.hpp"
#include "ScrollArea.hpp"
#include "../GUIManager.hpp"
#include "../ElementHelpers/ScrollAreaHelpers.hpp"
#include "../ElementHelpers/ButtonHelpers.hpp"
#include "LayoutElement.hpp"
#define TIME_TO_HOVER_TO_OPEN_DIRECTORY std::chrono::milliseconds(700)
bool operator<(const GUIStuff::TreeListingObjIndexList& a, const GUIStuff::TreeListingObjIndexList& b) {
size_t biggestIndexSize = std::max(a.size(), b.size());
for(size_t i = 0; i < biggestIndexSize; i++) {
if(i == a.size())
return true;
else if(i == b.size())
return false;
else if(a[i] < b[i])
return true;
else if(a[i] > b[i])
return false;
}
return false;
}
namespace GUIStuff {
using namespace ElementHelpers;
TreeListing::TreeListing(GUIManager& gui):
Element(gui) {}
void TreeListing::layout(const Clay_ElementId& id, NetworkingObjects::NetObjID rootObjID, const DisplayData& displayData, SelectionData& selectionData) {
//auto& io = *gui.io;
void TreeListing::layout(const Clay_ElementId& id, const Data& newDisplayData) {
d = newDisplayData;
//if(!io.mouse.leftHeld)
// dragHoldSelected = false;
flattenedIndexList.clear();
recursive_visible_flattened_obj_list(flattenedIndexList, {});
//selectionData.orderedObjsSelected.clear();
//std::optional<ParentObjectIDStack> hoveredObject;
CLAY(id, {
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
}) {
scroll_area_many_entries(gui, "scroll", {
.entryHeight = ENTRY_HEIGHT,
.entryCount = flattenedIndexList.size(),
.elementContent = [&](size_t i) {
const ObjInfo& objInfo = flattenedIndexList[i];
gui.element<LayoutElement>("elem", [&](LayoutElement*, const Clay_ElementId& lId) {
SkColor4f backgroundColor;
if(d.selectedIndices && d.selectedIndices->contains(flattenedIndexList[i].objIndex))
backgroundColor = gui.io.theme->backColor1;
else
backgroundColor = gui.io.theme->backColor2;
//CLAY_AUTO_ID({
// .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
//}) {
// Clay_ElementId localID = CLAY_ID_LOCAL("scroll area");
// float setScrollAmount;
// float setScrollContentHeight;
// CLAY(localID, {
// .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
// }) {
// gui.scroll_bar_area("scroll area", true, [&](float scrollContentHeight, float containerHeight, float& scrollAmount) {
// setScrollAmount = scrollAmount;
// setScrollContentHeight = scrollContentHeight;
// size_t itemCount = 0;
// size_t itemCountToStartAt = -scrollAmount / ENTRY_HEIGHT;
// size_t itemCountToEndAt = (containerHeight - scrollAmount) / ENTRY_HEIGHT;
// itemCountToEndAt++;
// std::vector<NetworkingObjects::NetObjID> parentIDStack;
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT * itemCountToStartAt)}
// }
// }) {}
// recursive_gui(io, gui, displayData, selectionData, rootObjID, itemCount, itemCountToStartAt, itemCountToEndAt, 0, hoveredObject, parentIDStack, false);
// if(itemCount > itemCountToEndAt) {
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT * (itemCount - itemCountToEndAt))}
// }
// }) {}
// }
// }, false);
// }
// Clay_ElementData scrollAreaBB = Clay_GetElementData(localID);
// if(scrollAreaBB.found) {
// // Clamp by fabs(scrollcontentheight - 3), small offset is added to account for error (when youre at the very edge it might assume youre at the top of an element)
// float mouseRelativeYPos = std::clamp(std::fabs(io.mouse.pos.y() - scrollAreaBB.boundingBox.y - setScrollAmount), 0.0f, std::fabs(setScrollContentHeight - 3.0f));
// topHalfOfHovered = std::fmod(mouseRelativeYPos, ENTRY_HEIGHT) < (ENTRY_HEIGHT / 2.0f);
// }
//}
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
},
.backgroundColor = convert_vec4<Clay_Color>(backgroundColor)
}) {
if(objInfo.objIndex.size() > 1) {
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_FIXED((objInfo.objIndex.size() - 1) * ICON_SIZE), .height = CLAY_SIZING_GROW(0)}}
}) {}
}
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_FIXED(ICON_SIZE), .height = CLAY_SIZING_FIXED(ICON_SIZE)}}
}) {
if(!objInfo.isDirectory)
d.drawNonDirectoryObjIconGUI(objInfo.objIndex);
else {
gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] {
svg_icon_button(gui, "open dir button", objInfo.isOpen ? "data/icons/droparrow.svg" : "data/icons/droparrowclose.svg", {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.size = ICON_SIZE,
.onClick = [&] {
d.setDirectoryOpen(objInfo.objIndex, !objInfo.isOpen);
if(d.selectedIndices) {
d.selectedIndices->clear();
if(d.onSelectChange) d.onSelectChange();
}
}
});
});
}
}
d.drawObjGUI(objInfo.objIndex);
}
}, LayoutElement::Callbacks {
.mouseButton = [&, i] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) {
if(l->mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) {
gui.set_post_callback_func([&]{
auto& objIndex = flattenedIndexList[i].objIndex;
if(d.selectedIndices) {
auto it = d.selectedIndices->find(objIndex);
bool wasSelected = it != d.selectedIndices->end();
//// Any objects that were part of a collapsed directory will be unselected
//selectionData.objsSelected.clear();
//for(auto& [parent, object] : selectionData.orderedObjsSelected)
// selectionData.objsSelected.emplace(object);
//if(objDragged.has_value()) {
// if(hoveredObject.has_value() && !selectionData.objsSelected.contains(hoveredObject.value().object) && (std::chrono::steady_clock::now() - timeStartedHoveringOverObject) >= TIME_TO_HOVER_TO_OPEN_DIRECTORY) {
// ParentObjectIDStack& hoveredObjVal = hoveredObject.value();
// size_t hoveredObjIndex = displayData.getIndexOfObjInList({hoveredObjVal.parents.back(), hoveredObjVal.object});
// std::optional<DisplayData::ObjInList> objHoveringOver = displayData.getObjInListAtIndex(hoveredObjVal.parents.back(), hoveredObjIndex);
// if(objHoveringOver.value().isDirectory && !objHoveringOver.value().isDirectoryOpen)
// displayData.setDirectoryOpen(hoveredObjVal.object, true);
// }
// ParentObjectIDPair& objDraggedVal = objDragged.value();
// if(!selectionData.objsSelected.contains(objDraggedVal.object))
// objDragged = std::nullopt;
// else if(!io.mouse.leftHeld) {
// if(!hoveredObject.has_value())
// set_single_selected_object(selectionData);
// else {
// ParentObjectIDStack hoveredObjValToUse = hoveredObject.value(); // By value since it'll be edited
// size_t indexToMoveFrom = displayData.getIndexOfObjInList(objDraggedVal);
// size_t indexToMoveTo = displayData.getIndexOfObjInList({hoveredObjValToUse.parents.back(), hoveredObjValToUse.object});
// std::optional<DisplayData::ObjInList> objHoveringOver = displayData.getObjInListAtIndex(hoveredObjValToUse.parents.back(), indexToMoveTo);
// if(objHoveringOver.value().isDirectoryOpen && !topHalfOfHovered) { // Move to front of the directory object
// hoveredObjValToUse.parents.emplace_back(hoveredObjValToUse.object);
// indexToMoveTo = 0;
// }
// else if(!topHalfOfHovered)
// indexToMoveTo++;
// if((indexToMoveFrom == indexToMoveTo || (indexToMoveFrom + 1) == indexToMoveTo) && objDraggedVal.parent == hoveredObjValToUse.parents.back())
// set_single_selected_object(selectionData);
// else {
// bool wrongMovement = false;
// // Check if object is about to move into itself
// for(const NetworkingObjects::NetObjID& parent : hoveredObjValToUse.parents) {
// if(selectionData.objsSelected.contains(parent)) {
// wrongMovement = true;
// break;
// }
// }
// if(!wrongMovement) {
// displayData.moveObjectsToListAtIndex(hoveredObjValToUse.parents.back(), indexToMoveTo, selectionData.orderedObjsSelected);
// selectionData.objsSelected.clear();
// selectionData.orderedObjsSelected.clear();
// }
// else
// set_single_selected_object(selectionData);
// }
// }
// objDragged = std::nullopt;
// }
//}
//oldHoveredObject = hoveredObject;
if(gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held) {
if(!wasSelected) {
d.selectedIndices->emplace(objIndex);
if(d.onSelectChange) d.onSelectChange();
}
}
else if(gui.io.input->key(InputManager::KEY_GENERIC_LCTRL).held) {
if(!wasSelected)
d.selectedIndices->emplace(objIndex);
else
d.selectedIndices->erase(it);
if(d.onSelectChange) d.onSelectChange();
}
else if(!wasSelected || d.selectedIndices->size() != 1) {
d.selectedIndices->clear();
d.selectedIndices->emplace(objIndex);
if(d.onSelectChange) d.onSelectChange();
}
else if(button.clicks == 2)
if(d.onDoubleClick) d.onDoubleClick(objIndex);
}
else if(button.clicks == 2)
if(d.onDoubleClick) d.onDoubleClick(objIndex);
});
gui.set_to_layout();
}
}
});
}
});
}
}
void TreeListing::set_single_selected_object(SelectionData& selectionData) {
//selectionData.objsSelected.clear();
//selectionData.orderedObjsSelected.clear();
//selectionData.objsSelected.emplace(objDragged.value().object);
//selectionData.orderedObjsSelected.emplace_back(objDragged.value());
}
void TreeListing::recursive_gui(UpdateInputData& io, GUIManager& gui, const DisplayData& displayData, SelectionData& selectionData, NetworkingObjects::NetObjID objID, size_t& itemCount, size_t itemCountToStartAt, size_t itemCountToEndAt, size_t listDepth, std::optional<ParentObjectIDStack>& hoveredObject, std::vector<NetworkingObjects::NetObjID>& parentIDStack, bool parentJustSelected) {
//parentIDStack.emplace_back(objID);
//for(size_t i = 0;; i++) {
// std::optional<DisplayData::ObjInList> objInListOptional = displayData.getObjInListAtIndex(objID, i);
// if(!objInListOptional.has_value())
// break;
// else {
// auto& objInList = objInListOptional.value();
// bool selfJustSelected = false;
// if(itemCount >= itemCountToStartAt && itemCount < itemCountToEndAt) {
// gui.push_id(itemCount);
// bool buttonClicked = false;
// uint16_t topOutlineWidth = 0;
// uint16_t bottomOutlineWidth = 0;
// bool isOldHoveredObject = oldHoveredObject.has_value() && oldHoveredObject.value().object == objInList.id;
// SkColor4f backgroundColor;
// if(selectionData.objsSelected.contains(objInList.id))
// backgroundColor = io.theme->backColor1;
// else if(isOldHoveredObject && objInList.isDirectory && !objInList.isDirectoryOpen && objDragged.has_value())
// backgroundColor = lerp_vec(io.theme->backColor2, io.theme->fillColor1, std::clamp(std::chrono::duration<float, std::chrono::milliseconds::period>(std::chrono::steady_clock::now() - timeStartedHoveringOverObject) / TIME_TO_HOVER_TO_OPEN_DIRECTORY, 0.0f, 1.0f));
// else
// backgroundColor = io.theme->backColor2;
// if(oldHoveredObject.has_value() && oldHoveredObject.value().object == objInList.id) {
// if(objDragged.has_value()) {
// ParentObjectIDPair& objDraggedVal = objDragged.value();
// if(objDraggedVal.object != objInList.id) {
// if(topHalfOfHovered)
// topOutlineWidth = 1;
// else
// bottomOutlineWidth = 1;
// }
// }
// }
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)},
// .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
// },
// .backgroundColor = convert_vec4<Clay_Color>(backgroundColor)
// }) {
// if(listDepth != 0) {
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_FIXED(ENTRY_HEIGHT * listDepth), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)}
// },
// }) {}
// }
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}
// },
// .border = {
// .color = convert_vec4<Clay_Color>(io.theme->frontColor1),
// .width = {
// .left = 0,
// .right = 0,
// .top = topOutlineWidth,
// .bottom = bottomOutlineWidth,
// .betweenChildren = 0
// }
// }
// }) {
// if(objInList.isDirectory) {
// if(gui.svg_icon_button_transparent("ico", objInList.isDirectoryOpen ? "data/icons/droparrow.svg" : "data/icons/droparrowclose.svg", false, ENTRY_HEIGHT)) {
// displayData.setDirectoryOpen(objInList.id, !objInList.isDirectoryOpen);
// buttonClicked = true;
// }
// }
// else {
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_FIXED(ENTRY_HEIGHT), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)},
// .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
// },
// }) {
// buttonClicked |= displayData.drawNonDirectoryObjIconGUI(objInList.id);
// }
// }
// 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}
// }
// }) {
// buttonClicked |= displayData.drawObjGUI({objID, objInList.id});
// }
// }
//
// if(Clay_Hovered()) {
// hoveredObject = {parentIDStack, objInList.id};
// if(!isOldHoveredObject)
// timeStartedHoveringOverObject = std::chrono::steady_clock::now();
// if(io.mouse.leftClick && !buttonClicked && !parentJustSelected) {
// if(io.key.leftShift)
// dragHoldSelected = true;
// else if(io.key.leftCtrl) {
// bool alreadySelected = selectionData.objsSelected.contains(objInList.id);
// if(alreadySelected)
// selectionData.objsSelected.erase(objInList.id);
// else {
// select_and_unselect_parents(parentIDStack, objInList.id, selectionData);
// selfJustSelected = true;
// }
// }
// else {
// if(!selectionData.objsSelected.contains(objInList.id)) {
// selectionData.objsSelected.clear();
// selectionData.orderedObjsSelected.clear();
// selectionData.objsSelected.emplace(objInList.id);
// selfJustSelected = true;
// }
// objDragged = {objID, objInList.id};
// }
// }
// if(io.key.leftShift && dragHoldSelected && !parentJustSelected) {
// select_and_unselect_parents(parentIDStack, objInList.id, selectionData);
// selfJustSelected = true;
// }
// }
// }
// gui.pop_id();
// }
// if(!parentJustSelected) {
// if(selectionData.objsSelected.contains(objInList.id))
// selectionData.orderedObjsSelected.emplace_back(objID, objInList.id);
// }
// else
// unselect_object(objInList.id, selectionData);
// itemCount++;
// if(objInList.isDirectoryOpen)
// recursive_gui(io, gui, displayData, selectionData, objInList.id, itemCount, itemCountToStartAt, itemCountToEndAt, listDepth + 1, hoveredObject, parentIDStack, selfJustSelected | parentJustSelected);
// }
//}
//parentIDStack.pop_back();
}
void TreeListing::unselect_object(NetworkingObjects::NetObjID id, SelectionData& selectionData) {
//selectionData.objsSelected.erase(id);
//std::erase_if(selectionData.orderedObjsSelected, [&id](const auto& p) {
// return p.object == id;
//});
}
void TreeListing::select_and_unselect_parents(const std::vector<NetworkingObjects::NetObjID>& parentIDStack, NetworkingObjects::NetObjID newSelectedObj, SelectionData& selectionData) {
//for(const NetworkingObjects::NetObjID& parent : parentIDStack) {
// if(selectionData.objsSelected.contains(parent)) {
// unselect_object(parent, selectionData);
// break;
// }
//}
//selectionData.objsSelected.emplace(newSelectedObj);
void TreeListing::recursive_visible_flattened_obj_list(std::vector<ObjInfo>& objs, const TreeListingObjIndexList& objIndex) {
std::optional<DirectoryInfo> dirInfo = d.dirInfo(objIndex);
bool isRoot = objIndex.empty();
if(!isRoot)
objs.emplace_back(objIndex, dirInfo.has_value(), dirInfo.has_value() ? dirInfo.value().isOpen : false);
if(dirInfo.has_value() && (dirInfo.value().isOpen || isRoot)) {
TreeListingObjIndexList childObjIndex = objIndex;
childObjIndex.emplace_back();
for(size_t i = 0; i < dirInfo.value().dirSize; i++) {
childObjIndex.back() = i;
recursive_visible_flattened_obj_list(objs, childObjIndex);
}
}
}
}

View file

@ -1,6 +1,13 @@
#pragma once
#include "Element.hpp"
#include <Helpers/NetworkingObjects/NetObjID.hpp>
#include <set>
namespace GUIStuff {
typedef std::vector<size_t> TreeListingObjIndexList;
}
bool operator<(const GUIStuff::TreeListingObjIndexList& a, const GUIStuff::TreeListingObjIndexList& b);
namespace GUIStuff {
@ -9,54 +16,37 @@ class GUIManager;
class TreeListing : public Element {
public:
static constexpr float ENTRY_HEIGHT = 25.0f;
static constexpr float ICON_SIZE = 25.0f;
struct ParentObjectIDPair {
NetworkingObjects::NetObjID parent;
NetworkingObjects::NetObjID object;
bool operator==(const ParentObjectIDPair&) const = default;
struct ObjInfo {
TreeListingObjIndexList objIndex;
bool isDirectory = false;
bool isOpen = false;
};
struct ParentObjectIDStack {
std::vector<NetworkingObjects::NetObjID> parents;
NetworkingObjects::NetObjID object;
struct DirectoryInfo {
size_t dirSize;
bool isOpen;
};
struct DisplayData {
struct ObjInList {
NetworkingObjects::NetObjID id;
bool isDirectory = false;
bool isDirectoryOpen = false;
};
std::function<std::optional<ObjInList>(NetworkingObjects::NetObjID, size_t)> getObjInListAtIndex;
std::function<size_t(const ParentObjectIDPair&)> getIndexOfObjInList;
std::function<void(NetworkingObjects::NetObjID, bool)> setDirectoryOpen;
std::function<bool(NetworkingObjects::NetObjID)> drawNonDirectoryObjIconGUI;
std::function<bool(const ParentObjectIDPair&)> drawObjGUI;
std::function<void(NetworkingObjects::NetObjID, size_t, const std::vector<ParentObjectIDPair>&)> moveObjectsToListAtIndex;
};
struct SelectionData {
std::vector<ParentObjectIDPair> orderedObjsSelected;
std::unordered_set<NetworkingObjects::NetObjID> objsSelected;
struct Data {
std::set<TreeListingObjIndexList>* selectedIndices = nullptr;
std::function<std::optional<DirectoryInfo>(const TreeListingObjIndexList& objIndex)> dirInfo;
std::function<void(const TreeListingObjIndexList& objIndex, bool isOpen)> setDirectoryOpen;
std::function<void(const TreeListingObjIndexList& objIndex)> drawNonDirectoryObjIconGUI;
std::function<void(const TreeListingObjIndexList& objIndex)> drawObjGUI;
std::function<void(const TreeListingObjIndexList& objIndex)> onDoubleClick;
std::function<void()> onSelectChange;
std::function<void(const std::vector<TreeListingObjIndexList>& objIndices, const TreeListingObjIndexList& newObjIndex)> moveObj;
};
TreeListing(GUIManager& gui);
void layout(const Clay_ElementId& id, NetworkingObjects::NetObjID rootObjID, const DisplayData& displayData, SelectionData& selectionData);
void layout(const Clay_ElementId& id, const Data& newDisplayData);
private:
bool dragHoldSelected = false;
void recursive_visible_flattened_obj_list(std::vector<ObjInfo>& objs, const TreeListingObjIndexList& objIndex);
void set_single_selected_object(SelectionData& selectionData);
void recursive_gui(UpdateInputData& io, GUIManager& gui, const DisplayData& displayData, SelectionData& selectionData, NetworkingObjects::NetObjID objID, size_t& itemCount, size_t itemCountToStartAt, size_t itemCountToEndAt, size_t listDepth, std::optional<ParentObjectIDStack>& hoveredObject, std::vector<NetworkingObjects::NetObjID>& parentIDStack, bool parentJustSelected);
void select_and_unselect_parents(const std::vector<NetworkingObjects::NetObjID>& parentIDStack, NetworkingObjects::NetObjID newSelectedObj, SelectionData& selectionData);
void unselect_object(NetworkingObjects::NetObjID id, SelectionData& selectionData);
bool topHalfOfHovered = false;
std::optional<ParentObjectIDPair> objDragged;
std::optional<ParentObjectIDStack> oldHoveredObject;
std::chrono::steady_clock::time_point timeStartedHoveringOverObject;
std::vector<ObjInfo> flattenedIndexList;
Data d;
};
}

View file

@ -492,7 +492,6 @@ void Toolbar::top_toolbar() {
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1)
}) {
global_log();
bool bookmarkMenuPopUpJustOpen = false;
bool layerMenuPopUpJustOpen = false;
auto icon_button_top_toolbar = [&](const char* id, const std::string& svgPath, bool isSelected, const std::function<void()>& onClick) {
@ -556,21 +555,17 @@ void Toolbar::top_toolbar() {
layerMenuPopUpJustOpen = true;
}
});
icon_button_top_toolbar("Bookmark Menu Button", "data/icons/bookmark.svg", bookmarkMenuPopupOpen, [&] {
if(bookmarkMenuPopupOpen) {
main.world->bMan.refresh_gui_data();
bookmarkMenuPopupOpen = false;
}
else {
Element* bookmarkMenuButton = icon_button_top_toolbar("Bookmark Menu Button", "data/icons/bookmark.svg", bookmarkMenuPopupOpen, [&] {
if(bookmarkMenuPopupOpen)
stop_displaying_bookmark_menu();
else
bookmarkMenuPopupOpen = true;
bookmarkMenuPopUpJustOpen = true;
}
});
if(gridMenu.popupOpen)
grid_menu(gridMenuButton);
if(bookmarkMenuPopupOpen)
bookmark_menu(bookmarkMenuPopUpJustOpen);
bookmark_menu(bookmarkMenuButton);
if(layerMenuPopupOpen)
layer_menu(layerMenuPopUpJustOpen);
}
@ -855,7 +850,7 @@ void Toolbar::grid_menu(Element* gridMenuButton) {
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Grids");
float ENTRY_HEIGHT = 25.0f;
@ -958,32 +953,39 @@ void Toolbar::stop_displaying_grid_menu() {
main.g.gui.set_to_layout();
}
void Toolbar::bookmark_menu(bool justOpened) {
void Toolbar::stop_displaying_bookmark_menu() {
main.world->bMan.refresh_gui_data();
bookmarkMenuPopupOpen = false;
main.g.gui.set_to_layout();
}
void Toolbar::bookmark_menu(Element* bookmarkMenuButton) {
auto& gui = main.g.gui;
auto& io = gui.io;
gui.new_id("bookmark menu", [&] {
//Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT BOOKMARK MENU");
//CLAY(localId, {
// .layout = {
// .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) },
// .padding = CLAY_PADDING_ALL(io.theme->padding1),
// .childGap = io.theme->childGap1,
// .childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
// .layoutDirection = CLAY_TOP_TO_BOTTOM
// },
// .backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
// .cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
// .floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
//}) {
// gui.obstructing_window(localId);
// text_label_centered(gui, "Bookmarks");
// main.world->bMan.setup_list_gui("bookmark menu list");
// if(io.mouse.leftClick && !Clay_Hovered() && !justOpened) {
// bookmarkMenuPopupOpen = false;
// main.world->bMan.refresh_gui_data();
// }
//}
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.element<LayoutElement>("grid menu", [&] (LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) },
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1),
.floating = {.offset = {.x = 0, .y = static_cast<float>(io.theme->padding1)}, .zIndex = gui.get_z_index(), .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT}
}) {
text_label_centered(gui, "Bookmarks");
main.world->bMan.setup_list_gui("bookmark menu list");
}
}, LayoutElement::Callbacks {
.mouseButton = [&, bookmarkMenuButton] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) {
if(!l->mouseHovering && !l->childMouseHovering && !bookmarkMenuButton->mouseHovering && button.down)
stop_displaying_bookmark_menu();
}
});
});
}

View file

@ -94,7 +94,8 @@ class Toolbar {
void grid_menu(GUIStuff::Element* gridMenuButton);
void add_grid();
void stop_displaying_grid_menu();
void bookmark_menu(bool justOpened);
void stop_displaying_bookmark_menu();
void bookmark_menu(GUIStuff::Element* bookmarkMenuButton);
void layer_menu(bool justOpened);
void drawing_program_gui();
void options_menu();

View file

@ -1,5 +1,6 @@
#include "WorldUndoManager.hpp"
#include "World.hpp"
#include "MainProgram.hpp"
void WorldUndoAction::scale_up(const WorldScalar& scaleAmount) {}
WorldUndoAction::~WorldUndoAction() {}
@ -42,6 +43,9 @@ void WorldUndoManager::push_redo(std::unique_ptr<WorldUndoAction> undoAction) {
void WorldUndoManager::undo() {
if(undoQueue.empty())
return;
world.bMan.refresh_gui_data();
if(!undoQueue.back()->undo(*this))
clear();
else {
@ -50,11 +54,16 @@ void WorldUndoManager::undo() {
}
set_world_has_unsaved_local_changes();
world.main.g.gui.set_to_layout();
}
void WorldUndoManager::redo() {
if(redoQueue.empty())
return;
world.bMan.refresh_gui_data();
if(!redoQueue.back()->redo(*this))
clear();
else {
@ -63,6 +72,8 @@ void WorldUndoManager::redo() {
}
set_world_has_unsaved_local_changes();
world.main.g.gui.set_to_layout();
}
void WorldUndoManager::clear() {