Starting work on drawing program layers

This commit is contained in:
Yousef Khadadeh 2025-12-24 12:42:27 +03:00
parent c2e85e8a62
commit a29c5dc926
14 changed files with 334 additions and 138 deletions

View file

@ -80,6 +80,7 @@ set(sources "src/main.cpp"
"src/DrawingProgram/EllipseDrawEditTool.cpp" "src/DrawingProgram/EllipseDrawEditTool.cpp"
"src/DrawingProgram/RectDrawEditTool.cpp" "src/DrawingProgram/RectDrawEditTool.cpp"
"src/DrawingProgram/TextBoxEditTool.cpp" "src/DrawingProgram/TextBoxEditTool.cpp"
"src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp"
"src/CanvasComponents/CanvasComponentContainer.cpp" "src/CanvasComponents/CanvasComponentContainer.cpp"
"src/CanvasComponents/CanvasComponentAllocator.cpp" "src/CanvasComponents/CanvasComponentAllocator.cpp"
"src/CanvasComponents/BrushStrokeCanvasComponent.cpp" "src/CanvasComponents/BrushStrokeCanvasComponent.cpp"

View file

@ -18,6 +18,8 @@ class NetObjManagerTypeList {
std::function<void(const NetObjTemporaryPtr<ServerT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncServer; std::function<void(const NetObjTemporaryPtr<ServerT>&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)> readUpdateFuncServer;
}; };
template <typename ClientT, typename ServerT, typename ClientAllocatedType, typename ServerAllocatedType> void register_class(const ServerClientClassFunctions<ClientT, ServerT>& funcs) { template <typename ClientT, typename ServerT, typename ClientAllocatedType, typename ServerAllocatedType> void register_class(const ServerClientClassFunctions<ClientT, ServerT>& funcs) {
if((netTypeID + 1) == 0) // Unsigned type wraps around, so check if we're already at class count limit (if we are, we have to increase the size of NetTypeIDType)
throw std::runtime_error("[NetObjManagerTypeList::register_class] Reached limit of number of classes that can be registered. Increase the size of NetTypeIDType to continue");
typeIndexFunctionsClient[std::type_index(typeid(ClientT*))] = TypeIndexFunctions { typeIndexFunctionsClient[std::type_index(typeid(ClientT*))] = TypeIndexFunctions {
.readConstructorFunc = [f = funcs.readConstructorFuncClient](const NetObjTemporaryPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) { .readConstructorFunc = [f = funcs.readConstructorFuncClient](const NetObjTemporaryPtr<void>& obj, cereal::PortableBinaryInputArchive& message, const std::shared_ptr<NetServer::ClientData>& c) {
f(obj.cast<ClientT>(), message, c); f(obj.cast<ClientT>(), message, c);

View file

@ -11,18 +11,20 @@ void BookmarkData::jump_to(World& world) const {
BookmarkListItem::BookmarkListItem() {} BookmarkListItem::BookmarkListItem() {}
BookmarkListItem::BookmarkListItem(NetworkingObjects::NetObjManager& netObjMan, const std::string& initName, bool isFolder, const BookmarkData& initBookmarkData) { BookmarkListItem::BookmarkListItem(NetworkingObjects::NetObjManager& netObjMan, const std::string& initName, bool isFolder, const BookmarkData& initBookmarkData) {
name = initName;
if(isFolder) { if(isFolder) {
folderData = std::make_unique<BookmarkFolderData>(); folderData = std::make_unique<BookmarkFolderData>();
folderData->folderList = netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<BookmarkListItem>>(); folderData->folderList = netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<BookmarkListItem>>();
} }
else else
bookmarkData = std::make_unique<BookmarkData>(initBookmarkData); bookmarkData = std::make_unique<BookmarkData>(initBookmarkData);
nameData = netObjMan.make_obj<NameData>();
nameData->name = initName;
} }
void BookmarkListItem::reassign_netobj_ids_call() { void BookmarkListItem::reassign_netobj_ids_call() {
if(folderData) if(folderData)
folderData->folderList.reassign_ids(); folderData->folderList.reassign_ids();
nameData.reassign_ids();
} }
bool BookmarkListItem::is_folder() const { bool BookmarkListItem::is_folder() const {
@ -37,8 +39,15 @@ const NetObjOwnerPtr<NetObjOrderedList<BookmarkListItem>>& BookmarkListItem::get
return folderData->folderList; return folderData->folderList;
} }
void BookmarkListItem::set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) {
if(nameData && nameData->name != newName) {
nameData->name = newName;
delayedNetObjMan.send_update_to_all<NameData>(nameData, false);
}
}
const std::string& BookmarkListItem::get_name() const { const std::string& BookmarkListItem::get_name() const {
return name; return nameData->name;
} }
bool BookmarkListItem::is_folder_open() const { bool BookmarkListItem::is_folder_open() const {
@ -49,41 +58,29 @@ void BookmarkListItem::set_folder_open(bool newIsFolderOpen) {
folderData->isFolderOpen = newIsFolderOpen; folderData->isFolderOpen = newIsFolderOpen;
} }
void BookmarkListItem::set_name(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, const std::string& newName) { void BookmarkListItem::register_class(World& w) {
o->name = newName; w.netObjMan.register_class<BookmarkListItem, BookmarkListItem, BookmarkListItem, BookmarkListItem>({
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a) {
a(o->name);
});
}
void BookmarkListItem::register_class(NetObjManager& netObjMan) {
netObjMan.register_class<BookmarkListItem, BookmarkListItem, BookmarkListItem, BookmarkListItem>({
.writeConstructorFuncClient = write_constructor_data, .writeConstructorFuncClient = write_constructor_data,
.readConstructorFuncClient = read_constructor_data, .readConstructorFuncClient = read_constructor_data,
.readUpdateFuncClient = [](const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) { .readUpdateFuncClient = nullptr,
a(o->name);
},
.writeConstructorFuncServer = write_constructor_data, .writeConstructorFuncServer = write_constructor_data,
.readConstructorFuncServer = read_constructor_data, .readConstructorFuncServer = read_constructor_data,
.readUpdateFuncServer = [](const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) { .readUpdateFuncServer = nullptr
a(o->name);
o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a) {
a(o->name);
});
},
}); });
NetworkingObjects::register_ordered_list_class<BookmarkListItem>(w.netObjMan);
w.delayedUpdateObjectManager.register_class<NameData>(w.netObjMan);
} }
void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a) { void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a) {
a(o->name, o->is_folder()); a(o->is_folder());
if(o->is_folder()) if(o->is_folder())
o->folderData->folderList.write_create_message(a); o->folderData->folderList.write_create_message(a);
else else
a(*o->bookmarkData); a(*o->bookmarkData);
o->nameData.write_create_message(a);
} }
void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) { void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o->name);
bool isFolder; bool isFolder;
a(isFolder); a(isFolder);
if(isFolder) { if(isFolder) {
@ -94,4 +91,5 @@ void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemp
o->bookmarkData = std::make_unique<BookmarkData>(); o->bookmarkData = std::make_unique<BookmarkData>();
a(*o->bookmarkData); a(*o->bookmarkData);
} }
o->nameData = o.get_obj_man()->read_create_message<NameData>(a, c);
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <Helpers/NetworkingObjects/NetObjOwnerPtr.hpp> #include <Helpers/NetworkingObjects/NetObjOwnerPtr.hpp>
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp> #include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
#include <string> #include <string>
#include "../CoordSpaceHelper.hpp" #include "../CoordSpaceHelper.hpp"
@ -23,17 +24,24 @@ class BookmarkListItem {
bool is_folder_open() const; bool is_folder_open() const;
void set_folder_open(bool newIsFolderOpen); void set_folder_open(bool newIsFolderOpen);
const std::string& get_name() const; const std::string& get_name() const;
static void register_class(NetworkingObjects::NetObjManager& netObjMan); static void register_class(World& w);
static void set_name(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, const std::string& newName); // Set once after editing is finished
void reassign_netobj_ids_call(); void reassign_netobj_ids_call();
void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName);
private: private:
struct BookmarkFolderData { struct BookmarkFolderData {
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<BookmarkListItem>> folderList; NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<BookmarkListItem>> folderList;
bool isFolderOpen = false; bool isFolderOpen = false;
}; };
struct NameData {
std::string name;
template <typename Archive> void serialize(Archive& a) {
a(name);
}
};
static void write_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a); static void write_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a);
static void read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c); static void read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c);
std::unique_ptr<BookmarkFolderData> folderData; std::unique_ptr<BookmarkFolderData> folderData;
std::unique_ptr<BookmarkData> bookmarkData; std::unique_ptr<BookmarkData> bookmarkData;
std::string name; NetworkingObjects::NetObjOwnerPtr<NameData> nameData;
}; };

View file

@ -27,109 +27,118 @@ void BookmarkManager::refresh_gui_data() {
void BookmarkManager::setup_list_gui(const std::string& id) { void BookmarkManager::setup_list_gui(const std::string& id) {
using namespace NetworkingObjects; using namespace NetworkingObjects;
if(bookmarkListRoot) { if(bookmarkListRoot) {
std::optional<NetObjID> toDeleteParent;
std::optional<NetObjID> toDeleteObject;
auto& gui = world.main.toolbar.gui; auto& gui = world.main.toolbar.gui;
gui.push_id(id); gui.push_id(id);
gui.tree_listing("list", bookmarkListRoot.get_net_id(), GUIStuff::TreeListing::DisplayData{ if(bookmarkListRoot->get_folder_list()->empty()) {
.getObjInListAtIndex = [&](NetObjID parentId, size_t index) -> std::optional<GUIStuff::TreeListing::DisplayData::ObjInList> { gui.text_label_centered("No bookmarks yet...");
NetObjOrderedList<BookmarkListItem>& bookmarkParentFolder = *world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(parentId)->get_folder_list(); selectionData = GUIStuff::TreeListing::SelectionData();
if(bookmarkParentFolder.size() <= index) oldSelection.clear();
return std::nullopt; nameToEdit.clear();
return GUIStuff::TreeListing::DisplayData::ObjInList{
.id = bookmarkParentFolder.at(index)->obj.get_net_id(),
.isDirectory = bookmarkParentFolder.at(index)->obj->is_folder(),
.isDirectoryOpen = bookmarkParentFolder.at(index)->obj->is_folder() ? bookmarkParentFolder.at(index)->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);
if(Clay_Hovered() && gui.io->mouse.leftClick >= 2 && !tempPtr->is_folder())
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);
return true;
}
if(gui.svg_icon_button_transparent("delete button", "data/icons/trash.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
toDeleteParent = idPair.parent;
toDeleteObject = idPair.object;
return true;
}
return false;
},
.moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector<GUIStuff::TreeListing::ParentObjectIDPair>& objsToInsert) {
world.netObjMan.send_multi_update_messsage([&]() {
std::unordered_map<NetObjID, std::unordered_set<NetObjID>> 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();
for(size_t i = 0; i < objsToInsert.size(); i++) {
toEraseMap[objsToInsert[i].parent].emplace(objsToInsert[i].object);
if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index)
newIndex--;
}
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
listToEraseFromPtr->erase_unordered_set(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
}
std::vector<std::pair<uint32_t, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
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(newIndex + i, std::move(*it));
toInsert.back().second.reassign_ids();
}
listPtr->insert_ordered_list_and_send_create(listPtr, toInsert);
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
}
}, selectionData);
if(selectionData.objsSelected != oldSelection) {
oldSelection = selectionData.objsSelected;
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();
} }
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;
return GUIStuff::TreeListing::DisplayData::ObjInList{
.id = bookmarkParentFolder.at(index)->obj.get_net_id(),
.isDirectory = bookmarkParentFolder.at(index)->obj->is_folder(),
.isDirectoryOpen = bookmarkParentFolder.at(index)->obj->is_folder() ? bookmarkParentFolder.at(index)->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);
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);
return true;
}
if(gui.svg_icon_button_transparent("delete button", "data/icons/trash.svg", false, GUIStuff::TreeListing::ENTRY_HEIGHT)) {
toDeleteParent = idPair.parent;
toDeleteObject = idPair.object;
return true;
}
return false;
},
.moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector<GUIStuff::TreeListing::ParentObjectIDPair>& objsToInsert) {
world.netObjMan.send_multi_update_messsage([&]() {
std::unordered_map<NetObjID, std::unordered_set<NetObjID>> 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();
if(toDeleteObject.has_value()) { for(size_t i = 0; i < objsToInsert.size(); i++) {
auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toDeleteParent.value())->get_folder_list(); toEraseMap[objsToInsert[i].parent].emplace(objsToInsert[i].object);
folderList->erase(folderList, toDeleteObject.value()); if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index)
newIndex--;
}
for(auto& [listToEraseFrom, setToErase] : toEraseMap) {
auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(listToEraseFrom)->get_folder_list();
listToEraseFromPtr->erase_unordered_set(listToEraseFromPtr, setToErase, &toInsertObjPtrs);
}
std::vector<std::pair<uint32_t, NetObjOwnerPtr<BookmarkListItem>>> toInsert;
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(newIndex + i, std::move(*it));
toInsert.back().second.reassign_ids();
}
listPtr->insert_ordered_list_and_send_create(listPtr, toInsert);
}, NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
}
}, selectionData);
if(selectionData.objsSelected != oldSelection) {
oldSelection = selectionData.objsSelected;
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()) {
auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id<BookmarkListItem>(toDeleteParent.value())->get_folder_list();
folderList->erase(folderList, toDeleteObject.value());
}
} }
gui.left_to_right_line_layout([&]() { gui.left_to_right_line_layout([&]() {
@ -151,8 +160,7 @@ void BookmarkManager::setup_list_gui(const std::string& id) {
if(tempPtr) { if(tempPtr) {
gui.text_label_centered(tempPtr->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark"); gui.text_label_centered(tempPtr->is_folder() ? "Edit Bookmark Folder" : "Edit Bookmark");
gui.input_text_field("input edit name", "Name", &nameToEdit); gui.input_text_field("input edit name", "Name", &nameToEdit);
if(nameToEdit != tempPtr->get_name()) tempPtr->set_name(world.delayedUpdateObjectManager, nameToEdit);
tempPtr->set_name(tempPtr, nameToEdit);
} }
} }

View file

@ -11,8 +11,8 @@ CanvasComponentAllocator::CanvasComponentAllocator(CanvasComponentType typeToAll
comp = std::unique_ptr<CanvasComponent>(CanvasComponent::allocate_comp(typeToAllocate)); comp = std::unique_ptr<CanvasComponent>(CanvasComponent::allocate_comp(typeToAllocate));
} }
void CanvasComponentAllocator::register_class(World& world, NetworkingObjects::NetObjManager& objMan) { void CanvasComponentAllocator::register_class(World& world) {
world.delayedUpdateObjectManager.register_class<CanvasComponentAllocator>(objMan, NetworkingObjects::DelayUpdateSerializedClassManager::CustomConstructors<CanvasComponentAllocator>{ world.delayedUpdateObjectManager.register_class<CanvasComponentAllocator>(world.netObjMan, NetworkingObjects::DelayUpdateSerializedClassManager::CustomConstructors<CanvasComponentAllocator>{
.writeConstructor = [](const CanvasComponentAllocator& o, cereal::PortableBinaryOutputArchive& a) { .writeConstructor = [](const CanvasComponentAllocator& o, cereal::PortableBinaryOutputArchive& a) {
a(o.comp->get_type()); a(o.comp->get_type());
a(*o.comp); a(*o.comp);

View file

@ -12,5 +12,5 @@ class CanvasComponentAllocator {
CanvasComponentAllocator(); CanvasComponentAllocator();
CanvasComponentAllocator(CanvasComponentType typeToAllocate); CanvasComponentAllocator(CanvasComponentType typeToAllocate);
std::unique_ptr<CanvasComponent> comp; std::unique_ptr<CanvasComponent> comp;
static void register_class(World& world, NetworkingObjects::NetObjManager& objMan); static void register_class(World& world);
}; };

View file

@ -41,10 +41,6 @@ void CanvasComponentContainer::read_constructor_func(const NetworkingObjects::Ne
o->compAllocator->comp->compContainer = o.get(); o->compAllocator->comp->compContainer = o.get();
} }
void CanvasComponentContainer::delay_post_assignment_update(DrawingProgram& drawP, CanvasComponent& comp) {
comp.compContainer->commit_update(drawP);
}
void CanvasComponentContainer::save_file(cereal::PortableBinaryOutputArchive& a) const { void CanvasComponentContainer::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(coords); a(coords);
get_comp().save_file(a); get_comp().save_file(a);

View file

@ -13,7 +13,7 @@ class DrawingProgramCacheBVHNode;
class CanvasComponentContainer { class CanvasComponentContainer {
public: public:
typedef NetworkingObjects::NetObjOrderedList<CanvasComponentContainer> NetList; typedef NetworkingObjects::NetObjOrderedList<CanvasComponentContainer> NetList;
typedef NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<CanvasComponentContainer>> NetListOwnerPtr; typedef NetworkingObjects::NetObjOwnerPtr<NetList> NetListOwnerPtr;
typedef NetworkingObjects::NetObjOrderedListObjectInfo<CanvasComponentContainer> ObjInfo; typedef NetworkingObjects::NetObjOrderedListObjectInfo<CanvasComponentContainer> ObjInfo;
typedef std::shared_ptr<ObjInfo> ObjInfoSharedPtr; typedef std::shared_ptr<ObjInfo> ObjInfoSharedPtr;
typedef std::weak_ptr<ObjInfo> ObjInfoWeakPtr; typedef std::weak_ptr<ObjInfo> ObjInfoWeakPtr;
@ -28,7 +28,6 @@ class CanvasComponentContainer {
CanvasComponentContainer(); CanvasComponentContainer();
CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, CanvasComponentType type); CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, CanvasComponentType type);
static void register_class(NetworkingObjects::NetObjManager& t); static void register_class(NetworkingObjects::NetObjManager& t);
static void delay_post_assignment_update(DrawingProgram& drawP, CanvasComponent& comp);
void save_file(cereal::PortableBinaryOutputArchive& a) const; void save_file(cereal::PortableBinaryOutputArchive& a) const;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
CanvasComponent& get_comp() const; CanvasComponent& get_comp() const;

View file

@ -0,0 +1,10 @@
#pragma once
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
#include "../../CanvasComponents/CanvasComponent.hpp"
class DrawingProgramLayerListItem;
class DrawingProgramLayer {
public:
CanvasComponentContainer::NetListOwnerPtr components;
};

View file

@ -0,0 +1,10 @@
#pragma once
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
class DrawingProgramLayerListItem;
class DrawingProgramLayerFolder {
public:
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>> folderList;
bool isFolderOpen = false;
};

View file

@ -0,0 +1,115 @@
#include "DrawingProgramLayerListItem.hpp"
#include "DrawingProgramLayerFolder.hpp"
#include <cereal/types/string.hpp>
#include "DrawingProgramLayer.hpp"
#include "../../World.hpp"
using namespace NetworkingObjects;
DrawingProgramLayerListItem::DrawingProgramLayerListItem() {}
DrawingProgramLayerListItem::DrawingProgramLayerListItem(NetworkingObjects::NetObjManager& netObjMan, const std::string& initName, bool isFolder) {
if(isFolder) {
folderData = std::make_unique<DrawingProgramLayerFolder>();
folderData->folderList = netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>>();
}
else {
layerData = std::make_unique<DrawingProgramLayer>();
layerData->components = netObjMan.make_obj<CanvasComponentContainer::NetList>();
}
nameData = netObjMan.make_obj<NameData>();
nameData->name = initName;
displayData = netObjMan.make_obj<DisplayData>();
}
void DrawingProgramLayerListItem::reassign_netobj_ids_call() {
if(folderData)
folderData->folderList.reassign_ids();
else
layerData->components.reassign_ids();
nameData.reassign_ids();
displayData.reassign_ids();
}
bool DrawingProgramLayerListItem::is_folder() const {
return folderData != nullptr;
}
DrawingProgramLayerFolder& DrawingProgramLayerListItem::get_folder() const {
return *folderData;
}
DrawingProgramLayer& DrawingProgramLayerListItem::get_layer() const {
return *layerData;
}
void DrawingProgramLayerListItem::set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) const {
if(nameData && nameData->name != newName) {
nameData->name = newName;
delayedNetObjMan.send_update_to_all<NameData>(nameData, false);
}
}
const std::string& DrawingProgramLayerListItem::get_name() const {
return nameData->name;
}
void DrawingProgramLayerListItem::set_alpha(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, float newAlpha) const {
if(displayData && displayData->alpha != newAlpha) {
displayData->alpha = newAlpha;
delayedNetObjMan.send_update_to_all<DisplayData>(displayData, false);
}
}
float DrawingProgramLayerListItem::get_alpha() const {
return displayData->alpha;
}
void DrawingProgramLayerListItem::set_visible(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, bool newVisible) const {
if(displayData && displayData->visible != newVisible) {
displayData->visible = newVisible;
delayedNetObjMan.send_update_to_all<DisplayData>(displayData, false);
}
}
bool DrawingProgramLayerListItem::get_visible() const {
return displayData->visible;
}
void DrawingProgramLayerListItem::register_class(World& w) {
w.netObjMan.register_class<DrawingProgramLayerListItem, DrawingProgramLayerListItem, DrawingProgramLayerListItem, DrawingProgramLayerListItem>({
.writeConstructorFuncClient = write_constructor_func,
.readConstructorFuncClient = read_constructor_func,
.readUpdateFuncClient = nullptr,
.writeConstructorFuncServer = write_constructor_func,
.readConstructorFuncServer = read_constructor_func,
.readUpdateFuncServer = nullptr,
});
w.delayedUpdateObjectManager.register_class<NameData>(w.netObjMan);
w.delayedUpdateObjectManager.register_class<DisplayData>(w.netObjMan);
}
void DrawingProgramLayerListItem::write_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryOutputArchive& a) {
a(o->is_folder());
if(o->is_folder())
o->folderData->folderList.write_create_message(a);
else
o->layerData->components.write_create_message(a);
o->nameData.write_create_message(a);
o->displayData.write_create_message(a);
}
void DrawingProgramLayerListItem::read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
bool isFolder;
a(isFolder);
if(isFolder) {
o->folderData = std::make_unique<DrawingProgramLayerFolder>();
o->folderData->folderList = o.get_obj_man()->read_create_message<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>>(a, c);
}
else {
o->layerData = std::make_unique<DrawingProgramLayer>();
o->layerData->components = o.get_obj_man()->read_create_message<CanvasComponentContainer::NetList>(a, c);
}
o->nameData = o.get_obj_man()->read_create_message<NameData>(a, c);
o->displayData = o.get_obj_man()->read_create_message<DisplayData>(a, c);
}

View file

@ -0,0 +1,50 @@
#pragma once
#include <Helpers/NetworkingObjects/NetObjManager.hpp>
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
#include "DrawingProgramLayerFolder.hpp"
#include "DrawingProgramLayer.hpp"
class DrawingProgramLayerFolder;
class DrawingProgramLayer;
class World;
class DrawingProgramLayerListItem {
public:
DrawingProgramLayerListItem();
DrawingProgramLayerListItem(NetworkingObjects::NetObjManager& netObjMan, const std::string& initName, bool isFolder);
bool is_folder() const;
DrawingProgramLayerFolder& get_folder() const;
DrawingProgramLayer& get_layer() const;
static void register_class(World& w);
void reassign_netobj_ids_call();
void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) const;
const std::string& get_name() const;
void set_alpha(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, float newAlpha) const;
float get_alpha() const;
void set_visible(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, bool newVisible) const;
bool get_visible() const;
private:
static void write_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryOutputArchive& a);
static void read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c);
std::unique_ptr<DrawingProgramLayerFolder> folderData;
std::unique_ptr<DrawingProgramLayer> layerData;
struct NameData {
std::string name;
template <typename Archive> void serialize(Archive& a) {
a(name);
}
};
struct DisplayData {
float alpha = 1.0f;
bool visible = true;
template <typename Archive> void serialize(Archive& a) {
a(alpha, visible);
}
};
NetworkingObjects::NetObjOwnerPtr<NameData> nameData;
NetworkingObjects::NetObjOwnerPtr<DisplayData> displayData;
};

View file

@ -110,11 +110,10 @@ void World::init_client_data_list_callbacks() {
} }
void World::init_net_obj_type_list() { void World::init_net_obj_type_list() {
BookmarkListItem::register_class(netObjMan); BookmarkListItem::register_class(*this);
NetworkingObjects::register_ordered_list_class<BookmarkListItem>(netObjMan);
delayedUpdateObjectManager.register_class<WorldGrid>(netObjMan); delayedUpdateObjectManager.register_class<WorldGrid>(netObjMan);
NetworkingObjects::register_ordered_list_class<WorldGrid>(netObjMan); NetworkingObjects::register_ordered_list_class<WorldGrid>(netObjMan);
CanvasComponentAllocator::register_class(*this, netObjMan); CanvasComponentAllocator::register_class(*this);
CanvasComponentContainer::register_class(netObjMan); CanvasComponentContainer::register_class(netObjMan);
NetworkingObjects::register_ordered_list_class<CanvasComponentContainer>(netObjMan); NetworkingObjects::register_ordered_list_class<CanvasComponentContainer>(netObjMan);
canvasTheme.register_class(); canvasTheme.register_class();