More GUI code moved to events, code now compiles but application doesn't run

This commit is contained in:
Yousef Khadadeh 2026-03-30 17:05:24 +03:00
parent 3566b7e563
commit b4c35124c3
37 changed files with 913 additions and 879 deletions

View file

@ -24,300 +24,300 @@ void BookmarkManager::refresh_gui_data() {
}
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;
//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;
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 = index;
// std::vector<NetObjOwnerPtr<BookmarkListItem>> toInsertObjPtrs;
// auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listObj)->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 < 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--;
// }
// 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 < 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);
// 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(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);
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));
}
}, selectionData);
// 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);
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();
}
// 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();
// }
if(toDeleteObject.has_value())
remove_bookmark(toDeleteParent.value(), toDeleteObject.value());
}
// if(toDeleteObject.has_value())
// remove_bookmark(toDeleteParent.value(), toDeleteObject.value());
// }
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);
}
});
// 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);
}
}
// 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();
}
// gui.pop_id();
//}
}
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem>>> BookmarkManager::try_to_create_in_proper_position(BookmarkListItem* newItem) {

View file

@ -178,7 +178,7 @@ void DrawCamera::input_mouse_motion_callback(World& w, const InputManager::Mouse
}
void DrawCamera::input_mouse_wheel_callback(World& w, const InputManager::MouseWheelCallbackArgs& wheel) {
if(!smoothMove.occurring && !isTouchTransforming && wheel.tickAmount.y() && w.main.toolbar.check_if_position_isnt_obstructed(wheel.mousePos)) {
if(!smoothMove.occurring && !isTouchTransforming && wheel.tickAmount.y()) {
WorldVec mouseWorldPos = c.from_space(wheel.mousePos);
WorldScalar zoomFactor(1.0 + w.main.toolbar.scrollZoomSpeed);

View file

@ -59,7 +59,7 @@ void DrawingProgram::on_tab_out() {
}
void DrawingProgram::input_drop_file_callback(const InputManager::DropCallbackArgs& drop) {
if(world.main.toolbar.check_if_position_isnt_obstructed(drop.pos) && std::filesystem::is_regular_file(drop.data)) {
if(std::filesystem::is_regular_file(drop.data)) {
#ifdef __EMSCRIPTEN_
add_file_to_canvas_by_path(drop.data, world.main.input.mouse.pos, true);
#else
@ -69,7 +69,7 @@ void DrawingProgram::input_drop_file_callback(const InputManager::DropCallbackAr
}
void DrawingProgram::input_drop_text_callback(const InputManager::DropCallbackArgs& drop) {
if(world.main.toolbar.check_if_position_isnt_obstructed(drop.pos) && is_valid_http_url(drop.data)) {
if(is_valid_http_url(drop.data)) {
CanvasComponentContainer* newContainer = new CanvasComponentContainer(world.netObjMan, CanvasComponentType::IMAGE);
ImageCanvasComponent& img = static_cast<ImageCanvasComponent&>(newContainer->get_comp());
newContainer->coords = world.drawData.cam.c;
@ -88,8 +88,7 @@ void DrawingProgram::input_mouse_button_callback(const InputManager::MouseButton
drawTool->input_mouse_button_on_canvas_callback(b);
};
bool isHoveringOverCanvas = world.main.toolbar.check_if_position_isnt_obstructed(button.pos);
if(isHoveringOverCanvas && button.down) {
if(button.down) {
if(button.button == InputManager::MouseButton::RIGHT) {
if(!controls.middleClickHeld && !controls.leftClickHeld) {
if(world.main.toolbar.rightClickPopupLocation)
@ -457,7 +456,7 @@ void DrawingProgram::modify_grid(const NetworkingObjects::NetObjWeakPtr<WorldGri
}
void DrawingProgram::update() {
controls.cursorHoveringOverCanvas = world.main.toolbar.check_if_position_isnt_obstructed(world.main.input.mouse.pos);
controls.cursorHoveringOverCanvas = true; //world.main.toolbar.check_if_position_isnt_obstructed(world.main.input.mouse.pos);
if(addFileInNextFrame) {
add_file_to_canvas_by_path_execute(addFileInfo.first, addFileInfo.second);

View file

@ -23,26 +23,33 @@
#include <EmscriptenHelpers/emscripten_browser_clipboard.h>
#endif
#include "../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp"
#include "../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
DrawingProgramSelection::DrawingProgramSelection(DrawingProgram& initDrawP):
drawP(initDrawP)
{}
void DrawingProgramSelection::selection_gui() {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& t = drawP.world.main.toolbar;
t.gui.push_id("general selection gui");
t.gui.text_label("Select from:");
if(t.gui.radio_button_field("layer edited", "Layer being edited", drawP.controls.layerSelector == DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED))
drawP.controls.layerSelector = DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED;
if(t.gui.radio_button_field("all visible", "All visible layers", drawP.controls.layerSelector == DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS))
drawP.controls.layerSelector = DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS;
text_label(t.gui, "Select from:");
radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, {
{"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED},
{"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS}
});
if(is_something_selected()) {
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) {
if(strokeColorChangeData.newColor.w() == 0.0f)
strokeColorChangeData.newColor.w() = 1.0f;
t.color_selector_right(&strokeColorChangeData.newColor == t.colorRight ? nullptr : &strokeColorChangeData.newColor);
}
t.gui.text_label("Stroke Color");
left_to_right_line_layout(t.gui, [&]() {
//if(t.gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) {
// if(strokeColorChangeData.newColor.w() == 0.0f)
// strokeColorChangeData.newColor.w() = 1.0f;
// t.color_selector_right(&strokeColorChangeData.newColor == t.colorRight ? nullptr : &strokeColorChangeData.newColor);
//}
text_label(t.gui, "Stroke Color");
});
update_selection_stroke_color();
}

View file

@ -24,338 +24,338 @@ void DrawingProgramLayerManagerGUI::refresh_gui_data() {
}
void DrawingProgramLayerManagerGUI::setup_list_gui(const char* id, bool& hoveringOverDropdown) {
using namespace NetworkingObjects;
auto& world = layerMan.drawP.world;
if(layerMan.layerTreeRoot) {
auto& gui = world.main.toolbar.gui;
gui.push_id(id);
if(layerMan.layerTreeRoot->get_folder().folderList->empty()) {
gui.text_label_centered("No layers exist.");
selectionData = GUIStuff::TreeListing::SelectionData();
oldSelection.clear();
nameToEdit.clear();
}
else {
std::optional<NetObjID> toDeleteParent;
std::optional<NetObjID> toDeleteObject;
gui.tree_listing("list", layerMan.layerTreeRoot.get_net_id(), GUIStuff::TreeListing::DisplayData{
.getObjInListAtIndex = [&](NetObjID parentId, size_t index) -> std::optional<GUIStuff::TreeListing::DisplayData::ObjInList> {
NetObjOrderedList<DrawingProgramLayerListItem>& parentFolder = *world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(parentId)->get_folder().folderList;
if(parentFolder.size() <= index)
return std::nullopt;
return GUIStuff::TreeListing::DisplayData::ObjInList{
.id = parentFolder.at(index)->obj.get_net_id(),
.isDirectory = parentFolder.at(index)->obj->is_folder(),
.isDirectoryOpen = parentFolder.at(index)->obj->is_folder() ? parentFolder.at(index)->obj->get_folder().isFolderOpen : false
};
},
.getIndexOfObjInList = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
return world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(idPair.parent)->get_folder().folderList->get(idPair.object)->pos;
},
.setDirectoryOpen = [&](NetObjID netID, bool newDirectoryOpen) {
world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(netID)->get_folder().isFolderOpen = 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("ico", "data/icons/layer.svg");
}
return false;
},
.drawObjGUI = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(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)
layerMan.editingLayer = tempPtr;
if(!tempPtr->is_folder()) {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(GUIStuff::TreeListing::ENTRY_HEIGHT), .height = CLAY_SIZING_FIXED(GUIStuff::TreeListing::ENTRY_HEIGHT)},
.padding = CLAY_PADDING_ALL(2),
},
}) {
if(tempPtr.get_net_id() == layerMan.editingLayer.get_net_id())
gui.svg_icon("edit ico", "data/icons/pencil.svg");
}
}
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(gui.svg_icon_button_transparent("edit button", "data/icons/pencil.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
layerMan.editingLayer = tempPtr;
isButtonClicked = true;
}
if(gui.svg_icon_button_transparent("visible button", tempPtr->get_visible() ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
tempPtr->set_visible(layerMan, !tempPtr->get_visible());
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;
//auto& world = layerMan.drawP.world;
//if(layerMan.layerTreeRoot) {
// auto& gui = world.main.toolbar.gui;
// gui.push_id(id);
// if(layerMan.layerTreeRoot->get_folder().folderList->empty()) {
// gui.text_label_centered("No layers exist.");
// selectionData = GUIStuff::TreeListing::SelectionData();
// oldSelection.clear();
// nameToEdit.clear();
// }
// else {
// std::optional<NetObjID> toDeleteParent;
// std::optional<NetObjID> toDeleteObject;
// gui.tree_listing("list", layerMan.layerTreeRoot.get_net_id(), GUIStuff::TreeListing::DisplayData{
// .getObjInListAtIndex = [&](NetObjID parentId, size_t index) -> std::optional<GUIStuff::TreeListing::DisplayData::ObjInList> {
// NetObjOrderedList<DrawingProgramLayerListItem>& parentFolder = *world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(parentId)->get_folder().folderList;
// if(parentFolder.size() <= index)
// return std::nullopt;
// return GUIStuff::TreeListing::DisplayData::ObjInList{
// .id = parentFolder.at(index)->obj.get_net_id(),
// .isDirectory = parentFolder.at(index)->obj->is_folder(),
// .isDirectoryOpen = parentFolder.at(index)->obj->is_folder() ? parentFolder.at(index)->obj->get_folder().isFolderOpen : false
// };
// },
// .getIndexOfObjInList = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
// return world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(idPair.parent)->get_folder().folderList->get(idPair.object)->pos;
// },
// .setDirectoryOpen = [&](NetObjID netID, bool newDirectoryOpen) {
// world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(netID)->get_folder().isFolderOpen = 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("ico", "data/icons/layer.svg");
// }
// return false;
// },
// .drawObjGUI = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) {
// auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(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)
// layerMan.editingLayer = tempPtr;
// if(!tempPtr->is_folder()) {
// CLAY_AUTO_ID({
// .layout = {
// .sizing = {.width = CLAY_SIZING_FIXED(GUIStuff::TreeListing::ENTRY_HEIGHT), .height = CLAY_SIZING_FIXED(GUIStuff::TreeListing::ENTRY_HEIGHT)},
// .padding = CLAY_PADDING_ALL(2),
// },
// }) {
// if(tempPtr.get_net_id() == layerMan.editingLayer.get_net_id())
// gui.svg_icon("edit ico", "data/icons/pencil.svg");
// }
// }
// 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(gui.svg_icon_button_transparent("edit button", "data/icons/pencil.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
// layerMan.editingLayer = tempPtr;
// isButtonClicked = true;
// }
// if(gui.svg_icon_button_transparent("visible button", tempPtr->get_visible() ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
// tempPtr->set_visible(layerMan, !tempPtr->get_visible());
// 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;
world.netObjMan.send_multi_update_messsage([&]() {
std::unordered_map<NetObjID, std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>>> toEraseMap;
uint32_t newIndex = index;
std::vector<NetObjOwnerPtr<DrawingProgramLayerListItem>> toInsertObjPtrs;
auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(listObj)->get_folder().folderList;
// world.netObjMan.send_multi_update_messsage([&]() {
// std::unordered_map<NetObjID, std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>>> toEraseMap;
// uint32_t newIndex = index;
// std::vector<NetObjOwnerPtr<DrawingProgramLayerListItem>> toInsertObjPtrs;
// auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(listObj)->get_folder().folderList;
// 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<DrawingProgramLayerListItem>(objsToInsert[i].parent)->get_folder().folderList;
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 < objsToInsert.size(); i++) {
// auto& parentListPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(objsToInsert[i].parent)->get_folder().folderList;
// 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--;
// }
// 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<DrawingProgramLayerListItem>(listToEraseFrom)->get_folder().folderList;
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<DrawingProgramLayerListItem>(listToEraseFrom)->get_folder().folderList;
// listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
// }
// Insert objects in toInsertObjPtrs into the folder we have selected
std::vector<std::pair<NetObjOrderedListIterator<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> 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<DrawingProgramLayerListItem>& objPtr) {
return objPtr.get_net_id() == id;
});
toInsert.emplace_back(insertIt, std::move(*it));
toInsert.back().second.reassign_ids();
}
std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> 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<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> 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<DrawingProgramLayerListItem>& objPtr) {
// return objPtr.get_net_id() == id;
// });
// toInsert.emplace_back(insertIt, std::move(*it));
// toInsert.back().second.reassign_ids();
// }
// std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> 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(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);
class MoveLayersWorldUndoAction : 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
MoveLayersWorldUndoAction(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 Layers";
}
bool undo(WorldUndoManager& undoMan) override {
std::vector<NetObjOwnerPtr<DrawingProgramLayerListItem>> toMoveObjs;
std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> toEraseList;
NetObjTemporaryPtr<NetObjOrderedList<DrawingProgramLayerListItem>> eraseListPtr;
std::unordered_map<NetObjID, std::pair<std::vector<uint32_t>*, std::vector<NetObjID>>> toInsertToMap;
// class MoveLayersWorldUndoAction : 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
// MoveLayersWorldUndoAction(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 Layers";
// }
// bool undo(WorldUndoManager& undoMan) override {
// std::vector<NetObjOwnerPtr<DrawingProgramLayerListItem>> toMoveObjs;
// std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> toEraseList;
// NetObjTemporaryPtr<NetObjOrderedList<DrawingProgramLayerListItem>> 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<DrawingProgramLayerListItem>(eraseListNetID.value())->get_folder().folderList;
}
// {
// 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<DrawingProgramLayerListItem>(eraseListNetID.value())->get_folder().folderList;
// }
{
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<DrawingProgramLayerListItem>(parentNetID)->get_folder().folderList;
std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> insertIteratorList = parentListPtr->at_ordered_indices(*indexNetIDListPair.first);
auto& insertNetIDList = indexNetIDListPair.second;
std::vector<std::pair<NetObjOrderedListIterator<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> toInsert;
for(auto [insertIt, netID] : std::views::zip(insertIteratorList, insertNetIDList)) {
auto it = std::find_if(toMoveObjs.begin(), toMoveObjs.end(), [id = netID](NetObjOwnerPtr<DrawingProgramLayerListItem>& 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<DrawingProgramLayerListItem>> listPtr;
std::vector<NetObjID> objsToInsert;
// for(auto& [parentNetID, indexNetIDListPair] : toInsertToMap) {
// auto& parentListPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(parentNetID)->get_folder().folderList;
// std::vector<NetObjOrderedListIterator<DrawingProgramLayerListItem>> insertIteratorList = parentListPtr->at_ordered_indices(*indexNetIDListPair.first);
// auto& insertNetIDList = indexNetIDListPair.second;
// std::vector<std::pair<NetObjOrderedListIterator<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> toInsert;
// for(auto [insertIt, netID] : std::views::zip(insertIteratorList, insertNetIDList)) {
// auto it = std::find_if(toMoveObjs.begin(), toMoveObjs.end(), [id = netID](NetObjOwnerPtr<DrawingProgramLayerListItem>& 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<DrawingProgramLayerListItem>> 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<DrawingProgramLayerListItem>(netID.value())->get_folder().folderList;
}
// {
// 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<DrawingProgramLayerListItem>(netID.value())->get_folder().folderList;
// }
{
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<DrawingProgramLayerListItem>> toInsertObjPtrs;
// undoMan.world.netObjMan.send_multi_update_messsage([&]() {
// std::vector<NetObjOwnerPtr<DrawingProgramLayerListItem>> toInsertObjPtrs;
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
auto& listToEraseFromPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(listToEraseFrom)->get_folder().folderList;
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<DrawingProgramLayerListItem>(listToEraseFrom)->get_folder().folderList;
// listToEraseFromPtr->erase_list(listToEraseFromPtr, listToEraseFromPtr->get_list(setToErase), &toInsertObjPtrs);
// }
std::vector<std::pair<NetObjOrderedListIterator<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> 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<DrawingProgramLayerListItem>& 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<DrawingProgramLayerListItem>, NetObjOwnerPtr<DrawingProgramLayerListItem>>> 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<DrawingProgramLayerListItem>& 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;
}
~MoveLayersWorldUndoAction() {}
// return true;
// }
// ~MoveLayersWorldUndoAction() {}
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<MoveLayersWorldUndoAction>(toEraseMapUndo, insertParentUndoID, insertUndoPosition, insertedUndoIDs));
}
}, selectionData);
// 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<MoveLayersWorldUndoAction>(toEraseMapUndo, insertParentUndoID, insertUndoPosition, insertedUndoIDs));
// }
// }, selectionData);
if(selectionData.objsSelected != oldSelection) {
editing_layer_check();
oldSelection = selectionData.objsSelected;
if(selectionData.objsSelected.size() == 1) {
NetObjTemporaryPtr<DrawingProgramLayerListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
if(tempPtr) {
nameToEdit = tempPtr->get_name();
alphaValToEdit = tempPtr->get_alpha();
auto it = std::find(get_blend_mode_useful_list().begin(), get_blend_mode_useful_list().end(), tempPtr->get_blend_mode());
blendModeValToEdit = (it == get_blend_mode_useful_list().end()) ? 0 : (it - get_blend_mode_useful_list().begin());
}
else {
nameToEdit.clear();
alphaValToEdit = 0.0f;
blendModeValToEdit = 0;
}
}
else {
nameToEdit.clear();
alphaValToEdit = 0.0f;
blendModeValToEdit = 0;
}
}
// if(selectionData.objsSelected != oldSelection) {
// editing_layer_check();
// oldSelection = selectionData.objsSelected;
// if(selectionData.objsSelected.size() == 1) {
// NetObjTemporaryPtr<DrawingProgramLayerListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
// if(tempPtr) {
// nameToEdit = tempPtr->get_name();
// alphaValToEdit = tempPtr->get_alpha();
// auto it = std::find(get_blend_mode_useful_list().begin(), get_blend_mode_useful_list().end(), tempPtr->get_blend_mode());
// blendModeValToEdit = (it == get_blend_mode_useful_list().end()) ? 0 : (it - get_blend_mode_useful_list().begin());
// }
// else {
// nameToEdit.clear();
// alphaValToEdit = 0.0f;
// blendModeValToEdit = 0;
// }
// }
// else {
// nameToEdit.clear();
// alphaValToEdit = 0.0f;
// blendModeValToEdit = 0;
// }
// }
if(toDeleteObject.has_value())
remove_layer(toDeleteParent.value(), toDeleteObject.value());
}
// if(toDeleteObject.has_value())
// remove_layer(toDeleteParent.value(), toDeleteObject.value());
// }
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 layer", "data/icons/plusbold.svg", false, gui.SMALL_BUTTON_SIZE) || addByEnter) {
auto newLayerObjInfo = create_layer(new DrawingProgramLayerListItem(world.netObjMan, nameForNew, false));
layerMan.editingLayer = newLayerObjInfo->obj;
}
else if(gui.svg_icon_button("create new folder", "data/icons/folderbold.svg", false, gui.SMALL_BUTTON_SIZE)) {
auto newFolderObjInfo = create_layer(new DrawingProgramLayerListItem(world.netObjMan, nameForNew, true));
newFolderObjInfo->obj->get_folder().isFolderOpen = 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 layer", "data/icons/plusbold.svg", false, gui.SMALL_BUTTON_SIZE) || addByEnter) {
// auto newLayerObjInfo = create_layer(new DrawingProgramLayerListItem(world.netObjMan, nameForNew, false));
// layerMan.editingLayer = newLayerObjInfo->obj;
// }
// else if(gui.svg_icon_button("create new folder", "data/icons/folderbold.svg", false, gui.SMALL_BUTTON_SIZE)) {
// auto newFolderObjInfo = create_layer(new DrawingProgramLayerListItem(world.netObjMan, nameForNew, true));
// newFolderObjInfo->obj->get_folder().isFolderOpen = true;
// }
// });
if(selectionData.objsSelected.size() == 1) {
NetObjTemporaryPtr<DrawingProgramLayerListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
if(tempPtr) {
gui.text_label_centered(tempPtr->is_folder() ? "Edit Layer Folder" : "Edit Layer");
gui.input_text_field("input edit name", "Name", &nameToEdit);
tempPtr->set_name(world.delayedUpdateObjectManager, nameToEdit);
gui.slider_scalar_field("input alpha slider", "Alpha", &alphaValToEdit, 0.0f, 1.0f, 2);
tempPtr->set_alpha(layerMan, alphaValToEdit);
gui.left_to_right_line_layout([&]() {
gui.text_label("Blend Mode");
gui.dropdown_select("input blend mode", &blendModeValToEdit, get_blend_mode_useful_name_list(), 190.0f, [&hoveringOverDropdown]() {
if(Clay_Hovered())
hoveringOverDropdown = true;
});
});
tempPtr->set_blend_mode(layerMan, get_blend_mode_useful_list()[blendModeValToEdit]);
}
}
// if(selectionData.objsSelected.size() == 1) {
// NetObjTemporaryPtr<DrawingProgramLayerListItem> tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<DrawingProgramLayerListItem>(*selectionData.objsSelected.begin());
// if(tempPtr) {
// gui.text_label_centered(tempPtr->is_folder() ? "Edit Layer Folder" : "Edit Layer");
// gui.input_text_field("input edit name", "Name", &nameToEdit);
// tempPtr->set_name(world.delayedUpdateObjectManager, nameToEdit);
// gui.slider_scalar_field("input alpha slider", "Alpha", &alphaValToEdit, 0.0f, 1.0f, 2);
// tempPtr->set_alpha(layerMan, alphaValToEdit);
// gui.left_to_right_line_layout([&]() {
// gui.text_label("Blend Mode");
// gui.dropdown_select("input blend mode", &blendModeValToEdit, get_blend_mode_useful_name_list(), 190.0f, [&hoveringOverDropdown]() {
// if(Clay_Hovered())
// hoveringOverDropdown = true;
// });
// });
// tempPtr->set_blend_mode(layerMan, get_blend_mode_useful_list()[blendModeValToEdit]);
// }
// }
gui.pop_id();
}
// gui.pop_id();
//}
}
std::optional<std::pair<NetworkingObjects::NetObjID, NetworkingObjects::NetObjOrderedListIterator<DrawingProgramLayerListItem>>> DrawingProgramLayerManagerGUI::try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem) {

View file

@ -30,11 +30,8 @@ void EditTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
if(objInfoBeingEdited) {
bool editHappened = compEditTool->edit_gui(objInfoBeingEdited);
if(editHappened)
objInfoBeingEdited->obj->commit_update(drawP);
}
if(objInfoBeingEdited)
compEditTool->edit_gui(objInfoBeingEdited);
else {
t.gui.push_id("edit tool");
text_label_centered(t.gui, "Edit");

View file

@ -4,25 +4,26 @@
#include "../../../MainProgram.hpp"
#include "../EditTool.hpp"
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
BrushEditTool::BrushEditTool(DrawingProgram& initDrawP):
DrawingProgramEditToolBase(initDrawP)
{}
bool BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
auto& a = static_cast<BrushStrokeCanvasComponent&>(comp->obj->get_comp());
void BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace GUIStuff;
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("edit tool brush");
t.gui.text_label_centered("Edit Brush Stroke");
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight))
t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color);
t.gui.text_label("Outline Color");
text_label_centered(t.gui, "Edit Brush Stroke");
left_to_right_line_layout(t.gui, [&]() {
//if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight))
// t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color);
text_label(t.gui, "Outline Color");
});
t.gui.pop_id();
bool editHappened = a.d.color != oldColor;
oldColor = a.d.color;
return editHappened;
}
void BrushEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) {

View file

@ -12,7 +12,7 @@ class BrushEditTool : public DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
private:
Vector4f oldColor;
};

View file

@ -5,10 +5,9 @@ DrawingProgramEditToolBase::DrawingProgramEditToolBase(DrawingProgram& initDrawP
drawP(initDrawP)
{}
bool DrawingProgramEditToolBase::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) {
void DrawingProgramEditToolBase::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) {
Toolbar& t = drawP.world.main.toolbar;
t.paint_popup(popupPos);
return true;
}
void DrawingProgramEditToolBase::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) {}

View file

@ -12,8 +12,8 @@ class DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* compContainer) = 0;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* compContainer) = 0;
virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos);
virtual void edit_gui(CanvasComponentContainer::ObjInfo* compContainer) = 0;
virtual void right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos);
virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key);
virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint);
virtual void input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint);

View file

@ -7,39 +7,45 @@
#include <memory>
#include "../EditTool.hpp"
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/NumberSliderHelpers.hpp"
EllipseDrawEditTool::EllipseDrawEditTool(DrawingProgram& initDrawP):
DrawingProgramEditToolBase(initDrawP)
{}
bool EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
void EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& a = static_cast<EllipseCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("edit tool ellipse");
t.gui.text_label_centered("Edit Ellipse");
if(t.gui.radio_button_field("fillonly", "Fill only", a.d.fillStrokeMode == 0)) a.d.fillStrokeMode = 0;
if(t.gui.radio_button_field("outlineonly", "Outline only", a.d.fillStrokeMode == 1)) a.d.fillStrokeMode = 1;
if(t.gui.radio_button_field("filloutline", "Fill and Outline", a.d.fillStrokeMode == 2)) a.d.fillStrokeMode = 2;
text_label_centered(t.gui, "Edit Ellipse");
radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and outline", 2}
});
if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) {
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
t.gui.text_label("Fill Color");
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
// t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
text_label(t.gui, "Fill Color");
});
}
if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) {
t.gui.slider_scalar_field("relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
t.gui.text_label("Outline Color");
slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
// t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
text_label(t.gui, "Outline Color");
});
}
t.gui.pop_id();
bool editHappened = (!oldData.has_value()) || (a.d != oldData);
oldData = a.d;
return editHappened;
}
void EllipseDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) {

View file

@ -13,7 +13,7 @@ class EllipseDrawEditTool : public DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
private:
void commit();

View file

@ -10,6 +10,9 @@
#include "Eigen/Geometry"
#include <fstream>
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/ButtonHelpers.hpp"
#ifdef __EMSCRIPTEN__
#include <EmscriptenHelpers/emscripten_browser_file.h>
#endif
@ -42,30 +45,35 @@ bool ImageEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) {
return true;
}
bool ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
void ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace GUIStuff;
using namespace ElementHelpers;
ImageCanvasComponent& a = static_cast<ImageCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("edit tool image");
t.gui.text_label_centered("File Properties");
text_label_centered(t.gui, "File Properties");
auto resourceData = drawP.world.netObjMan.get_obj_temporary_ref_from_id<ResourceData>(a.d.imageID);
if(resourceData) {
t.gui.text_label("Name: " + resourceData->name);
if(t.gui.text_button_wide("file download", "Download file")) {
#ifdef __EMSCRIPTEN__
emscripten_browser_file::download(
resourceData->name,
"application/octet-binary",
*resourceData->data
);
#endif
t.open_file_selector("Download File", {{"Any File", "*"}}, [resourceData](const std::filesystem::path& p, const auto& e) {
SDL_SaveFile(p.c_str(), resourceData->data->c_str(), resourceData->data->size());
}, resourceData->name, true);
}
text_label(t.gui, "Name: " + resourceData->name);
text_button(t.gui, "file download", "Download file", {
.wide = true,
.onClick = [&] {
#ifdef __EMSCRIPTEN__
emscripten_browser_file::download(
resourceData->name,
"application/octet-binary",
*resourceData->data
);
#endif
t.open_file_selector("Download File", {{"Any File", "*"}}, [resourceData](const std::filesystem::path& p, const auto& e) {
SDL_SaveFile(p.c_str(), resourceData->data->c_str(), resourceData->data->size());
}, resourceData->name, true);
}
});
}
else
t.gui.text_label_centered("Loading resource...");
text_label_centered(t.gui, "Loading resource...");
t.gui.pop_id();
return false;
}

View file

@ -10,5 +10,5 @@ class ImageEditTool : public DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
};

View file

@ -5,39 +5,44 @@
#include <memory>
#include "../EditTool.hpp"
#include "../../../GUIStuff/ElementHelpers/NumberSliderHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp"
RectDrawEditTool::RectDrawEditTool(DrawingProgram& initDrawP):
DrawingProgramEditToolBase(initDrawP)
{}
bool RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
void RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& a = static_cast<RectangleCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("edit tool rectangle");
t.gui.text_label_centered("Edit Rectangle");
t.gui.slider_scalar_field("relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f);
if(t.gui.radio_button_field("fillonly", "Fill only", a.d.fillStrokeMode == 0)) a.d.fillStrokeMode = 0;
if(t.gui.radio_button_field("outlineonly", "Outline only", a.d.fillStrokeMode == 1)) a.d.fillStrokeMode = 1;
if(t.gui.radio_button_field("filloutline", "Fill and Outline", a.d.fillStrokeMode == 2)) a.d.fillStrokeMode = 2;
text_label_centered(t.gui, "Edit Rectangle");
slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f);
radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and outline", 2}
});
if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) {
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
t.gui.text_label("Fill Color");
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
// t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
text_label(t.gui, "Fill Color");
});
}
if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) {
t.gui.slider_scalar_field("relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
t.gui.text_label("Outline Color");
slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
// t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
text_label(t.gui, "Outline Color");
});
}
t.gui.pop_id();
bool editHappened = (!oldData.has_value()) || (a.d != oldData);
oldData = a.d;
return editHappened;
}
void RectDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) {

View file

@ -12,7 +12,7 @@ class RectDrawEditTool : public DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
private:
std::optional<RectangleCanvasComponent::Data> oldData;
};

View file

@ -14,142 +14,149 @@
#include <memory>
#include "../EditTool.hpp"
#include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp"
#include "../../../GUIStuff/Elements/PositionAdjustingPopupMenu.hpp"
using namespace RichText;
TextBoxEditTool::TextBoxEditTool(DrawingProgram& initDrawP):
DrawingProgramEditToolBase(initDrawP)
{}
bool TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
auto& currentMods = *currentModsPtr;
t.gui.push_id("edit tool text");
t.gui.text_label_centered("Edit Text");
text_label_centered(t.gui, "Edit Text");
t.gui.left_to_right_line_layout([&]() {
t.gui.text_label("Font");
if(t.gui.font_picker("font picker", &newFontName)) {
currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared<FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{newFontName.c_str(), newFontName.size()}});
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);});
}
left_to_right_line_layout(t.gui, [&] {
text_label(t.gui, "Font");
//if(t.gui.font_picker("font picker", &newFontName)) {
// currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared<FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{newFontName.c_str(), newFontName.size()}});
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);});
//}
});
t.gui.left_to_right_line_centered_layout([&]() {
if(t.gui.svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) {
newIsBold = !newIsBold;
currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared<WeightTextStyleModifier>(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight);
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);});
}
//left_to_right_line_centered_layout(t.gui, [&] {
// if(svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) {
// newIsBold = !newIsBold;
// currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared<WeightTextStyleModifier>(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);});
// }
if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) {
newIsItalic = !newIsItalic;
currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared<SlantTextStyleModifier>(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant);
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);});
}
// if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) {
// newIsItalic = !newIsItalic;
// currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared<SlantTextStyleModifier>(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);});
// }
bool decorationEdited = false;
if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) {
newIsUnderlined = !newIsUnderlined;
decorationEdited = true;
}
if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) {
newIsLinethrough = !newIsLinethrough;
decorationEdited = true;
}
if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) {
newIsOverline = !newIsOverline;
decorationEdited = true;
}
if(decorationEdited) {
currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared<DecorationTextStyleModifier>(get_new_decoration_value());
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);});
}
});
// bool decorationEdited = false;
// if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) {
// newIsUnderlined = !newIsUnderlined;
// decorationEdited = true;
// }
// if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) {
// newIsLinethrough = !newIsLinethrough;
// decorationEdited = true;
// }
// if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) {
// newIsOverline = !newIsOverline;
// decorationEdited = true;
// }
// if(decorationEdited) {
// currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared<DecorationTextStyleModifier>(get_new_decoration_value());
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);});
// }
//});
t.gui.left_to_right_line_centered_layout([&]() {
if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft))
add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);});
if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter))
add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);});
if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight))
add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);});
if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify))
add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);});
if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr))
add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);});
if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl))
add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);});
});
//t.gui.left_to_right_line_centered_layout([&]() {
// if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);});
// if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);});
// if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);});
// if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);});
// if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr))
// add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);});
// if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl))
// add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);});
//});
if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
hold_undo_data("Font Size", a);
currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared<SizeTextStyleModifier>(newFontSize);
a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]);
}
else
release_undo_data("Font Size");
//if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
// hold_undo_data("Font Size", a);
// currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared<SizeTextStyleModifier>(newFontSize);
// a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]);
//}
//else
// release_undo_data("Font Size");
// Text color
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight))
t.color_selector_right(&newTextColor == t.colorRight ? nullptr : &newTextColor);
t.gui.text_label("Text Color");
});
//// Text color
//t.gui.left_to_right_line_layout([&]() {
// if(t.gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight))
// t.color_selector_right(&newTextColor == t.colorRight ? nullptr : &newTextColor);
// t.gui.text_label("Text Color");
//});
if(&newTextColor == t.colorRight)
hold_undo_data("Text Color", a);
else
release_undo_data("Text Color");
//if(&newTextColor == t.colorRight)
// hold_undo_data("Text Color", a);
//else
// release_undo_data("Text Color");
if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) {
currentMods[TextStyleModifier::ModifierType::COLOR] = std::make_shared<ColorTextStyleModifier>(newTextColor);
a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]);
}
//if((&newTextColor == t.colorRight) && t.isUpdatingColorRight) {
// currentMods[TextStyleModifier::ModifierType::COLOR] = std::make_shared<ColorTextStyleModifier>(newTextColor);
// a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]);
//}
// Highlight color
t.gui.left_to_right_line_layout([&]() {
if(t.gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) {
if(newHighlightColor.w() == 0.0f) { // Make highlight appear when the button is pressed
newHighlightColor.w() = 1.0f;
currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);});
}
t.color_selector_right(&newHighlightColor == t.colorRight ? nullptr : &newHighlightColor);
}
if(newHighlightColor.w() != 0.0f) {
if(t.gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) {
newHighlightColor = {0.0f, 0.0f, 0.0f, 0.0f};
currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);});
}
}
t.gui.text_label("Highlight Color");
});
//// Highlight color
//t.gui.left_to_right_line_layout([&]() {
// if(t.gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) {
// if(newHighlightColor.w() == 0.0f) { // Make highlight appear when the button is pressed
// newHighlightColor.w() = 1.0f;
// currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);});
// }
// t.color_selector_right(&newHighlightColor == t.colorRight ? nullptr : &newHighlightColor);
// }
// if(newHighlightColor.w() != 0.0f) {
// if(t.gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) {
// newHighlightColor = {0.0f, 0.0f, 0.0f, 0.0f};
// currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);});
// }
// }
// t.gui.text_label("Highlight Color");
//});
if(&newHighlightColor == t.colorRight)
hold_undo_data("Highlight Color", a);
else
release_undo_data("Highlight Color");
//if(&newHighlightColor == t.colorRight)
// hold_undo_data("Highlight Color", a);
//else
// release_undo_data("Highlight Color");
if((&newHighlightColor == t.colorRight) && t.isUpdatingColorRight) {
currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);
}
//if((&newHighlightColor == t.colorRight) && t.isUpdatingColorRight) {
// currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
// a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);
//}
t.gui.pop_id();
//t.gui.pop_id();
if(a.textBox->inputChangedTextBox)
set_styles_at_selection(a);
//if(a.textBox->inputChangedTextBox)
// set_styles_at_selection(a);
// NOTE: There should be a system that periodically sends updates even if no changes are made, since unreliable channels can drop update data
bool oldInputChangedTextBox = a.textBox->inputChangedTextBox;
a.textBox->inputChangedTextBox = false;
return oldInputChangedTextBox;
//// NOTE: There should be a system that periodically sends updates even if no changes are made, since unreliable channels can drop update data
//bool oldInputChangedTextBox = a.textBox->inputChangedTextBox;
//a.textBox->inputChangedTextBox = false;
//return oldInputChangedTextBox;
}
void TextBoxEditTool::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) {
@ -188,35 +195,33 @@ void TextBoxEditTool::input_mouse_motion_callback(CanvasComponentContainer::ObjI
}
}
bool TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) {
void TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) {
using namespace GUIStuff;
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
bool shouldClose = false;
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
t.gui.list_popup_menu("Text popup menu", popupPos, [&]() {
t.gui.text_label_light("Text menu");
t.gui.element<PositionAdjustingPopupMenu>("Text popup menu", popupPos, [&, popupPos] {
text_label_light(t.gui, "Text menu");
InputManager& input = drawP.world.main.input;
if(t.gui.text_button_left_transparent("Paste", "Paste")) {
drawP.popup_menu_action_button("Paste", "Paste", [&] {
input.call_text_paste(true);
shouldClose = true;
}
if(t.gui.text_button_left_transparent("Paste without formatting", "Paste without formatting")) {
});
drawP.popup_menu_action_button("Paste without formatting", "Paste without formatting", [&] {
input.call_text_paste(false);
shouldClose = true;
}
});
if(a.cursor->selectionBeginPos != a.cursor->selectionEndPos) {
if(t.gui.text_button_left_transparent("Copy", "Copy")) {
drawP.popup_menu_action_button("Copy", "Copy", [&] {
input.set_clipboard_plain_and_richtext_pair(a.textBox->process_copy(*a.cursor));
shouldClose = true;
}
if(t.gui.text_button_left_transparent("Cut", "Cut")) {
});
drawP.popup_menu_action_button("Cut", "Cut", [&] {
input.text.do_textbox_operation_with_undo([&]() {
input.set_clipboard_plain_and_richtext_pair(a.textBox->process_cut(*a.cursor));
});
shouldClose = true;
}
});
}
});
return !shouldClose;
}
void TextBoxEditTool::hold_undo_data(const std::string& undoName, TextBoxCanvasComponent& a) {

View file

@ -13,8 +13,8 @@ class TextBoxEditTool : public DrawingProgramEditToolBase {
virtual void edit_start(EditTool& editTool,CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override;
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) override;
virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual void right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) override;
virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) override;
virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) override;

View file

@ -135,7 +135,7 @@ void GridModifyTool::gui_toolbox() {
};
left_to_right_line_layout(t.gui, [&]() {
text_label(t.gui, "Type");
t.gui.element<DropDown<size_t>>("filepicker select type", &typeSelected, listOfGridTypes, 200.0f);
t.gui.element<DropDown<size_t>>("filepicker select type", &typeSelected, listOfGridTypes);
});
g.gridType = static_cast<WorldGrid::GridType>(typeSelected);
uint32_t sDiv = g.subdivisions;

View file

@ -9,7 +9,7 @@
#include <limits>
#include "../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp"
#include "../../GUIStuff/ElementHelpers/CheckBoxHelpers.cpp"
#include "../../GUIStuff/ElementHelpers/CheckBoxHelpers.hpp"
LineDrawTool::LineDrawTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)

View file

@ -15,7 +15,7 @@ void text_button(GUIManager& gui, const char* id, std::string_view text, const T
.childAlignment = {.x = options.centered ? CLAY_ALIGN_X_CENTER : CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
}
}) {
gui.element<SelectableButton>(id, options);
gui.element<SelectableButton>(id, d);
}
}
@ -30,7 +30,7 @@ void text_button_sized(GUIManager& gui, const char* id, std::string_view text, C
.childAlignment = {.x = options.centered ? CLAY_ALIGN_X_CENTER : CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
}
}) {
gui.element<SelectableButton>(id, options);
gui.element<SelectableButton>(id, d);
}
}
@ -40,7 +40,7 @@ void svg_icon_button(GUIManager& gui, const char* id, const std::string& svgPath
gui.element<SVGIcon>("icon", svgPath, p.isSelected || p.isHovering || p.isHeld);
};
CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(options.size), .height = CLAY_SIZING_FIXED(options.size) } } }) {
gui.element<SelectableButton>(id, options);
gui.element<SelectableButton>(id, d);
}
}

View file

@ -47,9 +47,10 @@ void text_button_sized(GUIManager& gui, const char* id, std::string_view text, C
void svg_icon_button(GUIManager& gui, const char* id, const std::string& svgPath, const SVGButtonOptions& options = {});
template <typename T> void color_button(GUIManager& gui, const char* id, T* val, const FixedSizeColorButtonOptions& options = {}) {
gui.push_id(id);
SelectableButton::Data d = selectable_button_options_to_data(options);
d.innerContent = [&] (const SelectableButton::InnerContentCallbackParameters&) {
gui.element<ColorRectangleDisplay>([val, hasAlpha = options.hasAlpha] {
gui.element<ColorRectangleDisplay>("color display", [val, hasAlpha = options.hasAlpha] {
if(hasAlpha)
return SkColor4f{(*val)[0], (*val)[1], (*val)[2], 1.0f};
else
@ -57,8 +58,9 @@ template <typename T> void color_button(GUIManager& gui, const char* id, T* val,
});
};
CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_FIXED(options.size), .height = CLAY_SIZING_FIXED(options.size) } } }) {
gui.element<SelectableButton>(id, options);
gui.element<SelectableButton>("button", d);
}
gui.pop_id();
}
}}

View file

@ -1,44 +1,11 @@
#pragma once
#include "../GUIManager.hpp"
#include "TextBoxHelpers.hpp"
#include "../Elements/ColorPicker.hpp"
#include "../Elements/ColorPickerButton.decl.hpp"
#include "ColorPickerItemsHelpers.hpp"
#include "../Elements/ColorPickerButton.hpp"
namespace GUIStuff { namespace ElementHelpers {
struct ColorPickerItemsOptions {
bool hasAlpha = true;
std::function<void()> onEdit;
};
template <typename T> void color_picker_items(GUIManager& gui, const char* id, T* val, const ColorPickerItemsOptions& options = {}) {
gui.push_id(id);
auto fullOnEdit = [&gui, oE = options.onEdit, val]() {
oE();
gui.set_to_layout();
};
gui.element<ColorPicker>("c", val, options.hasAlpha, fullOnEdit);
left_to_right_line_layout([&]() {
text_label(gui, "R");
input_color_component_255("r", &(*val)[0], { .onEdit = fullOnEdit });
text_label(gui, "G");
input_color_component_255("g", &(*val)[1], { .onEdit = fullOnEdit });
text_label(gui, "B");
input_color_component_255("b", &(*val)[2], { .onEdit = fullOnEdit });
if(options.hasAlpha) {
text_label(gui, "A");
input_color_component_255("a", &(*val)[3], { .onEdit = fullOnEdit });
}
});
left_to_right_line_layout([&]() {
text_label(gui, "Hex");
input_color_hex("h", val, { .onEdit = fullOnEdit, .hasAlpha = options.hasAlpha });
});
gui.pop_id();
}
template <typename T> void color_picker_button_field(GUIManager& gui, const char* id, std::string_view name, T* val, const ColorPickerButtonData& options = {}) {
left_to_right_line_layout([&]() {
left_to_right_line_layout(gui, [&]() {
gui.element<ColorPickerButton<T>>(id, val, options);
text_label(gui, name);
});

View file

@ -0,0 +1,39 @@
#pragma once
#include "../GUIManager.hpp"
#include "TextBoxHelpers.hpp"
#include "../Elements/ColorPicker.hpp"
namespace GUIStuff { namespace ElementHelpers {
struct ColorPickerItemsOptions {
bool hasAlpha = true;
std::function<void()> onEdit;
};
template <typename T> void color_picker_items(GUIManager& gui, const char* id, T* val, const ColorPickerItemsOptions& options = {}) {
gui.push_id(id);
auto fullOnEdit = [&gui, oE = options.onEdit, val]() {
oE();
gui.set_to_layout();
};
gui.element<ColorPicker<T>>("c", val, options.hasAlpha, fullOnEdit);
left_to_right_line_layout(gui, [&]() {
text_label(gui, "R");
input_color_component_255(gui, "r", &(*val)[0], { .onEdit = fullOnEdit });
text_label(gui, "G");
input_color_component_255(gui, "g", &(*val)[1], { .onEdit = fullOnEdit });
text_label(gui, "B");
input_color_component_255(gui, "b", &(*val)[2], { .onEdit = fullOnEdit });
if(options.hasAlpha) {
text_label(gui, "A");
input_color_component_255(gui, "a", &(*val)[3], { .onEdit = fullOnEdit });
}
});
left_to_right_line_layout(gui, [&]() {
text_label(gui, "Hex");
input_color_hex(gui, "h", val, { .hasAlpha = options.hasAlpha, .onEdit = fullOnEdit });
});
gui.pop_id();
}
} }

View file

@ -4,15 +4,15 @@
#include "../Elements/NumberSlider.hpp"
namespace GUIStuff { namespace ElementHelpers {
template <typename T> bool slider_scalar_field(GUIManager& gui, const char* id, std::string_view name, T* val, T min, T max, TextBoxScalarOptions options = {}) {
template <typename T> void slider_scalar_field(GUIManager& gui, const char* id, std::string_view name, T* val, T min, T max, TextBoxScalarOptions options = {}) {
gui.push_id(id);
options.onEdit = [&, oE = options.onEdit] {
oE();
gui.set_to_layout();
};
left_to_right_line_layout([&]() {
left_to_right_line_layout(gui, [&]() {
text_label(gui, name);
input_scalar("textbox", val, min, max, options);
input_scalar(gui, "textbox", val, min, max, options);
});
gui.element<NumberSlider<T>>("slider", val, min, max, options.onEdit);
gui.pop_id();

View file

@ -1,5 +1,4 @@
#include "TextBoxHelpers.hpp"
#include "../Elements/TextBox.impl.hpp"
#include "LayoutHelpers.hpp"
namespace GUIStuff { namespace ElementHelpers {
@ -29,7 +28,7 @@ void input_color_component_255(GUIManager& gui, const char* id, float* val, cons
return ss.str();
};
gui.element<TextBox<std::string>>(id, d);
gui.element<TextBox<float>>(id, d);
}
void input_text(GUIManager& gui, const char* id, std::string* val, const TextBoxOptions& options) {

View file

@ -1,6 +1,6 @@
#pragma once
#include "../GUIManager.hpp"
#include "../Elements/TextBox.decl.hpp"
#include "../Elements/TextBox.hpp"
#include "TextLabelHelpers.hpp"
#include "LayoutHelpers.hpp"
@ -83,10 +83,10 @@ template <typename T> void input_scalar(GUIManager& gui, const char* id, T* val,
std::stringstream ss;
if(std::is_floating_point<T>()) {
ss.precision(decimalPrecision);
ss << std::fixed << *a;
ss << std::fixed << a;
}
else
ss << *a;
ss << a;
return ss.str();
};
@ -95,7 +95,7 @@ template <typename T> void input_scalar(GUIManager& gui, const char* id, T* val,
template <typename TContainer, typename T> void input_scalars_field(GUIManager& gui, const char* id, std::string_view name, TContainer* val, size_t elemCount, T minVal, T maxVal, const TextBoxScalarOptions& options = {}) {
gui.push_id(id);
left_to_right_line_layout([&]() {
left_to_right_line_layout(gui, [&]() {
text_label(gui, name);
for(size_t i = 0; i < elemCount; i++) {
gui.push_id(i);
@ -107,7 +107,7 @@ template <typename TContainer, typename T> void input_scalars_field(GUIManager&
}
template <typename T> void input_scalar_field(GUIManager& gui, const char* id, std::string_view name, T* val, T minVal, T maxVal, const TextBoxScalarOptions& options = {}) {
left_to_right_line_layout([&]() {
left_to_right_line_layout(gui, [&]() {
text_label(gui, name);
input_scalar<T>(gui, id, val, minVal, maxVal, options);
});
@ -125,7 +125,12 @@ template <typename T> void input_color_hex(GUIManager& gui, const char* id, T* v
TextBoxData<T> d = textbox_options_to_data<T>(options);
d.textInputProps = textInputProps;
d.fromStr = [hasAlpha = options.hasAlpha](const std::string& a) {
T def = {0.0f, 0.0f, 0.0f, 1.0f};
T def;
def[0] = 0.0f;
def[1] = 0.0f;
def[2] = 0.0f;
if(hasAlpha)
def[3] = 1.0f;
unsigned startIndex = 0;
if(a.empty())
return def;

View file

@ -77,15 +77,6 @@ template <typename T> class ColorPicker : public Element {
static constexpr float BAR_WIDTH = 30.0;
static constexpr float BAR_GAP = 5.0;
static sk_sp<SkShader> hueBarShader;
static sk_sp<SkRuntimeEffect> svSelectionAreaEffect;
static sk_sp<SkRuntimeEffect> alphaBarEffect;
static sk_sp<SkShader> get_hue_shader();
static sk_sp<SkShader> get_sv_selection_shader(float hue);
static sk_sp<SkShader> get_alpha_bar_shader(const Vector3f& mainColor, float horizontalResolution);
T* data;
Vector3f savedHsv; // We save the HSV so that conversion doesnt ruin the UI
std::function<void()> onChange;

View file

@ -4,9 +4,11 @@
namespace GUIStuff {
template <typename T> ColorPicker<T>::ColorPicker(GUIManager& gui): Element(gui) {}
template <typename T> void ColorPicker<T>::layout(T* data, bool selectAlpha, const std::function<void()>& onChange) {
this->data = data;
savedHsv = rgb_to_hsv<T>(*data);
savedHsv = rgb_to_hsv<Vector3f, T>(*data);
this->selectAlpha = selectAlpha;
this->onChange = onChange;
@ -29,7 +31,7 @@ template <typename T> void ColorPicker<T>::clay_draw(SkCanvas* canvas, UpdateInp
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
SkPaint svSelectionAreaPaint;
svSelectionAreaPaint.setShader(get_sv_selection_shader(savedHsv.x() / 360.0f));
svSelectionAreaPaint.setShader(ColorPickerShaders::get_sv_selection_shader(savedHsv.x() / 360.0f));
canvas->drawPaint(svSelectionAreaPaint);
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
@ -50,7 +52,7 @@ template <typename T> void ColorPicker<T>::clay_draw(SkCanvas* canvas, UpdateInp
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
SkPaint hueBarPaint;
hueBarPaint.setShader(get_hue_shader());
hueBarPaint.setShader(ColorPickerShaders::get_hue_shader());
canvas->drawPaint(hueBarPaint);
canvas->drawLine(0.0f, 1.0f - normalizedHue, 1.0f, 1.0f - normalizedHue, selectionLinePaint);
@ -64,7 +66,7 @@ template <typename T> void ColorPicker<T>::clay_draw(SkCanvas* canvas, UpdateInp
SkPaint alphaBarPaint;
if(selectAlpha)
alphaBarPaint.setShader(get_alpha_bar_shader({(*data)[0], (*data)[1], (*data)[2]}, alphaBarDim.x()));
alphaBarPaint.setShader(ColorPickerShaders::get_alpha_bar_shader({(*data)[0], (*data)[1], (*data)[2]}, alphaBarDim.x()));
else
alphaBarPaint.setColor4f(SkColor4f{(*data)[0], (*data)[1], (*data)[2], 1.0f});
canvas->drawPaint(alphaBarPaint);
@ -103,7 +105,7 @@ template <typename T> bool ColorPicker<T>::input_mouse_button_callback(const Inp
template <typename T> bool ColorPicker<T>::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) {
update_color_picker_pos(motion.pos);
return Element::input_mouse_button_callback(motion, mouseHovering);
return Element::input_mouse_motion_callback(motion, mouseHovering);
}
template <typename T> void ColorPicker<T>::update_color_picker_pos(const Vector2f& p) {
@ -111,6 +113,8 @@ template <typename T> void ColorPicker<T>::update_color_picker_pos(const Vector2
gui.set_post_callback_func([&, p]() {
auto& bb = boundingBox.value();
switch(held) {
case HeldBar::NONE:
break;
case HeldBar::SV_HELD: {
float svSelectionAreaSize = bb.width() - (BAR_GAP + BAR_WIDTH);
Vector2f newSv = cwise_vec_clamp<Vector2f>((p - bb.min) / svSelectionAreaSize, Vector2f{0.0f, 0.0f}, Vector2f{1.0f, 1.0f});

View file

@ -4,14 +4,14 @@
namespace GUIStuff {
struct ColorPickerButtonData {
bool hasAlpha = false;
bool hasAlpha = true;
std::function<void()> onEdit;
};
template <typename T> class ColorPickerButton : public Element {
public:
ColorPickerButton(GUIManager& gui);
void layout(T* val, ColorPickerButtonData& d);
void layout(T* val, const ColorPickerButtonData& d);
private:
ColorPickerButtonData data;
bool isOpen = false;

View file

@ -1,12 +1,13 @@
#include "ColorPickerButton.decl.hpp"
#include "../ElementHelpers/ColorPickerHelpers.hpp"
#include "../ElementHelpers/ColorPickerItemsHelpers.hpp"
#include "../ElementHelpers/ButtonHelpers.hpp"
#include "../ElementHelpers/LayoutHelpers.hpp"
namespace GUIStuff {
template <typename T> ColorPickerButton<T>::ColorPickerButton(GUIManager& gui): Element(gui) {}
template <typename T> void ColorPickerButton<T>::layout(T* val, ColorPickerButtonData& d) {
template <typename T> void ColorPickerButton<T>::layout(T* val, const ColorPickerButtonData& d) {
this->data = d;
GUIStuff::ElementHelpers::color_button(gui, "Color Picker Button", val, {
@ -17,7 +18,7 @@ template <typename T> void ColorPickerButton<T>::layout(T* val, ColorPickerButto
}
});
if(isOpen) {
top_to_bottom_window_popup_layout("Color Picker", CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&, val, data = data]() {
ElementHelpers::top_to_bottom_window_popup_layout(gui, "Color Picker", CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&, val, data = data]() {
ElementHelpers::color_picker_items(gui, "c", val, {
.hasAlpha = data.hasAlpha,
.onEdit = data.onEdit

View file

@ -2,6 +2,8 @@
namespace GUIStuff {
sk_sp<SkRuntimeEffect> ColorRectangleDisplay::alphaBackgroundEffect;
ColorRectangleDisplay::ColorRectangleDisplay(GUIManager& gui): Element(gui) {}
void ColorRectangleDisplay::layout(const std::function<SkColor4f()>& colorFunc) {

View file

@ -14,9 +14,8 @@ constexpr double ROTATE_BAR_SNAP_DISTRIBUTION = std::numbers::pi * 0.25;
PaintCircleMenu::PaintCircleMenu(GUIManager& gui):
Element(gui) {}
void PaintCircleMenu::layout(const Data& data, const std::function<void()>& onChange) {
void PaintCircleMenu::layout(const Data& data) {
d = data;
this->onChange = onChange;
CLAY_AUTO_ID({
.layout = {

View file

@ -13,7 +13,7 @@ class PaintCircleMenu : public Element {
std::function<void()> onRotate;
std::function<void()> onPaletteClick;
};
void layout(const Data& data, const std::function<void()>& onChange);
void layout(const Data& data);
virtual bool collides_with_point(const Vector2f& p) const override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
virtual bool input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) override;
@ -22,7 +22,6 @@ class PaintCircleMenu : public Element {
void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA);
void draw_palette_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA);
Data d;
std::function<void()> onChange;
unsigned colorSelectionIndex = 0;
bool isHovering = false;
bool isRotateBarHeld = false;

View file

@ -3,12 +3,14 @@
namespace GUIStuff {
template <typename T> TextBox<T>::TextBox(GUIManager& gui): Element(gui) {}
template <typename T> void TextBox<T>::layout(const TextBoxData<T>& userInfo) {
auto& io = *gui.io;
this->userInfo = userInfo;
textbox->onUserTextEdit = [&] {
if(userInfo.immutable)
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, toStr(*userInfo.data));
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data));
else {
if(update_data() && userInfo.onEdit)
gui.set_post_callback_func(userInfo.onEdit);
@ -79,7 +81,7 @@ template <typename T> bool TextBox<T>::input_mouse_button_callback(const InputMa
gui.io->input->remove_rich_text_box_input(textbox);
if(update_data())
gui.set_post_callback_func(userInfo.onEdit);
update_textbox(io);
init_textbox(*gui.io);
isSelected = false;
}
}
@ -115,7 +117,7 @@ template <typename T> void TextBox<T>::init_textbox(UpdateInputData& io) {
cur = std::make_shared<RichText::TextBox::Cursor>();
rect = std::make_shared<SCollision::AABB<float>>();
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, toStr(*userInfo.data));
cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data));
}
template <typename T> bool TextBox<T>::update_data() {

View file

@ -999,7 +999,6 @@ void Toolbar::update_notification_gui() {
void Toolbar::grid_menu(bool justOpened) {
if(main.world->gridMan.grids) {
gui.push_id("grid menu");
Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT GRID MENU");
//CLAY(localId, {
// .layout = {
// .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) },
@ -1763,7 +1762,7 @@ void Toolbar::options_menu() {
color_picker_button_field(gui, "canvasColor", "Canvas Color", newColorToSet.get(), {
.hasAlpha = false,
.onEdit = [&, newColorToSet] {
main.world->canvasTheme.set_back_color(convert_vec3<Vector3f>(newColorToSet));
main.world->canvasTheme.set_back_color(convert_vec3<Vector3f>(*newColorToSet));
}
});
text_button_wide("done", "Done", [&] {
@ -2211,7 +2210,6 @@ void Toolbar::file_picker_gui_done() {
}
void Toolbar::file_picker_gui() {
bool isDoneByDoubleClick = false;
center_obstructing_window_gui("file picker gui window", CLAY_SIZING_FIXED(700), CLAY_SIZING_FIXED(500), [&] {
text_label_centered(gui, filePicker.filePickerWindowName);
left_to_right_line_layout(gui, [&]() {

View file

@ -96,7 +96,6 @@ class Toolbar {
bool flipZoomToolDirection = false;
float final_gui_scale();
bool check_if_position_isnt_obstructed(const Vector2f& pos);
bool app_close_requested();
private: