diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f6ca97..47d6a94 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,6 @@ set(sources "src/main.cpp" "src/GridManager.cpp" "src/WorldGrid.cpp" "src/TimePoint.cpp" - "src/ConnectionManager.cpp" "src/InputManager.cpp" "src/UndoManager.cpp" "src/CanvasTheme.cpp" diff --git a/src/Bookmarks/BookmarkListItem.cpp b/src/Bookmarks/BookmarkListItem.cpp index 147ec92..261cb86 100644 --- a/src/Bookmarks/BookmarkListItem.cpp +++ b/src/Bookmarks/BookmarkListItem.cpp @@ -2,6 +2,8 @@ #include #include "../World.hpp" #include "../ScaleUpCanvas.hpp" +#include "BookmarkManager.hpp" +#include "../World.hpp" using namespace NetworkingObjects; @@ -104,3 +106,38 @@ void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtrbookmarkData); o->nameData.write_create_message(a); } + +void BookmarkListItem::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(*nameData); + a(static_cast(folderData)); + if(folderData) { + a(folderData->folderList->size()); + for(auto& item : *folderData->folderList) + item.obj->save_file(a); + } + else + a(*bookmarkData); +} + +void BookmarkListItem::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, BookmarkManager& bMan) { + nameData = bMan.world.netObjMan.make_obj(); + a(*nameData); + + bool isFolder; + a(isFolder); + if(isFolder) { + folderData = std::make_unique(); + folderData->folderList = bMan.world.netObjMan.make_obj>(); + uint32_t folderSize; + a(folderSize); + for(uint32_t i = 0; i < folderSize; i++) { + BookmarkListItem* item = new BookmarkListItem; + item->load_file(a, version, bMan); + folderData->folderList->push_back_and_send_create(folderData->folderList, item); + } + } + else { + bookmarkData = std::make_unique(); + a(*bookmarkData); + } +} diff --git a/src/Bookmarks/BookmarkListItem.hpp b/src/Bookmarks/BookmarkListItem.hpp index c87bccf..9ed35d8 100644 --- a/src/Bookmarks/BookmarkListItem.hpp +++ b/src/Bookmarks/BookmarkListItem.hpp @@ -4,6 +4,9 @@ #include #include #include "../CoordSpaceHelper.hpp" +#include + +class BookmarkManager; struct BookmarkData { CoordSpaceHelper coords; @@ -27,7 +30,9 @@ class BookmarkListItem { static void register_class(World& w); void reassign_netobj_ids_call(); void scale_up(const WorldScalar& scaleUpAmount); - + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, BookmarkManager& bMan); + void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName); private: struct BookmarkFolderData { diff --git a/src/Bookmarks/BookmarkManager.cpp b/src/Bookmarks/BookmarkManager.cpp index 80585a0..d51e4bc 100644 --- a/src/Bookmarks/BookmarkManager.cpp +++ b/src/Bookmarks/BookmarkManager.cpp @@ -9,12 +9,8 @@ BookmarkManager::BookmarkManager(World& w): world(w) {} -void BookmarkManager::init() { - // NOTE: Should find a way for bookmarks added from the network to take into account the client's canvasScale - // Have the canvasScale variable come with the ClientData object, and the grid scale commands can be part of - // the client data class - if(world.netObjMan.is_server()) - bookmarkListRoot = world.netObjMan.make_obj_from_ptr(new BookmarkListItem(world.netObjMan, "ROOT", true, {})); +void BookmarkManager::server_init_no_file() { + bookmarkListRoot = world.netObjMan.make_obj_from_ptr(new BookmarkListItem(world.netObjMan, "ROOT", true, {})); } void BookmarkManager::refresh_gui_data() { @@ -200,3 +196,13 @@ NetworkingObjects::NetObjOrderedListIterator BookmarkManager:: void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) { bookmarkListRoot->scale_up(scaleUpAmount); } + +void BookmarkManager::save_file(cereal::PortableBinaryOutputArchive& a) const { + bookmarkListRoot->save_file(a); +} + +void BookmarkManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + bookmarkListRoot = world.netObjMan.make_obj_from_ptr(new BookmarkListItem()); + + bookmarkListRoot->load_file(a, version, *this); +} diff --git a/src/Bookmarks/BookmarkManager.hpp b/src/Bookmarks/BookmarkManager.hpp index 9b9991b..e5d2916 100644 --- a/src/Bookmarks/BookmarkManager.hpp +++ b/src/Bookmarks/BookmarkManager.hpp @@ -4,22 +4,19 @@ #include #include "../GUIStuff/Elements/TreeListing.hpp" #include "BookmarkListItem.hpp" +#include class World; class BookmarkManager { public: BookmarkManager(World& w); - void init(); + void server_init_no_file(); void scale_up(const WorldScalar& scaleUpAmount); void setup_list_gui(const std::string& id); void refresh_gui_data(); - - template void save(Archive& a) const { - } - - template void load(Archive& a) { - } + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); NetworkingObjects::NetObjOwnerPtr bookmarkListRoot; private: @@ -30,5 +27,7 @@ class BookmarkManager { std::string nameToEdit; std::string nameForNew; + friend class BookmarkListItem; + World& world; }; diff --git a/src/CanvasComponents/CanvasComponentAllocator.cpp b/src/CanvasComponents/CanvasComponentAllocator.cpp index 9f0b941..db81350 100644 --- a/src/CanvasComponents/CanvasComponentAllocator.cpp +++ b/src/CanvasComponents/CanvasComponentAllocator.cpp @@ -43,3 +43,15 @@ void CanvasComponentAllocator::register_class(World& world) { } }); } + +void CanvasComponentAllocator::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(comp->get_type()); + comp->save_file(a); +} + +void CanvasComponentAllocator::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + CanvasComponentType t; + a(t); + comp = std::unique_ptr(CanvasComponent::allocate_comp(t)); + comp->load_file(a, version); +} diff --git a/src/CanvasComponents/CanvasComponentAllocator.hpp b/src/CanvasComponents/CanvasComponentAllocator.hpp index cb1c1e8..09cc428 100644 --- a/src/CanvasComponents/CanvasComponentAllocator.hpp +++ b/src/CanvasComponents/CanvasComponentAllocator.hpp @@ -3,6 +3,7 @@ #include "CanvasComponentType.hpp" #include #include +#include class World; class CanvasComponent; @@ -13,4 +14,6 @@ class CanvasComponentAllocator { CanvasComponentAllocator(CanvasComponentType typeToAllocate); std::unique_ptr comp; static void register_class(World& world); + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); }; diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index 6133824..8fb4955 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -6,6 +6,7 @@ #include "CanvasComponent.hpp" #include #include "../ScaleUpCanvas.hpp" +#include "Helpers/NetworkingObjects/NetObjManager.hpp" using namespace NetworkingObjects; @@ -58,12 +59,14 @@ void CanvasComponentContainer::write_constructor_func(const NetworkingObjects::N void CanvasComponentContainer::save_file(cereal::PortableBinaryOutputArchive& a) const { a(coords); - get_comp().save_file(a); + compAllocator->save_file(a); } -void CanvasComponentContainer::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { +void CanvasComponentContainer::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, NetObjManager& objMan) { a(coords); - get_comp().load_file(a, version); + compAllocator = objMan.make_obj_direct(); + compAllocator->load_file(a, version); + compAllocator->comp->compContainer = this; } void CanvasComponentContainer::draw(SkCanvas* canvas, const DrawData& drawData) const { diff --git a/src/CanvasComponents/CanvasComponentContainer.hpp b/src/CanvasComponents/CanvasComponentContainer.hpp index 3fd7551..b152bf2 100644 --- a/src/CanvasComponents/CanvasComponentContainer.hpp +++ b/src/CanvasComponents/CanvasComponentContainer.hpp @@ -37,7 +37,7 @@ class CanvasComponentContainer { static void register_class(World& w); std::shared_ptr get_data_copy() const; void save_file(cereal::PortableBinaryOutputArchive& a) const; - void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, NetworkingObjects::NetObjManager& objMan); CanvasComponent& get_comp() const; SCollision::AABB get_world_bounds() const; void draw(SkCanvas* canvas, const DrawData& drawData) const; diff --git a/src/CanvasTheme.cpp b/src/CanvasTheme.cpp index 7fe85c5..6773195 100644 --- a/src/CanvasTheme.cpp +++ b/src/CanvasTheme.cpp @@ -11,11 +11,9 @@ CanvasTheme::CanvasTheme(World& w): world(w) {} -void CanvasTheme::init() { - if(world.netObjMan.is_server()) { - backColor = world.netObjMan.make_obj_direct(world.main.defaultCanvasBackgroundColor); - set_tool_front_color(world.drawProg); - } +void CanvasTheme::server_init_no_file() { + backColor = world.netObjMan.make_obj_direct(world.main.defaultCanvasBackgroundColor); + set_tool_front_color(world.drawProg); } SkColor4f CanvasTheme::get_back_color() const { @@ -63,3 +61,24 @@ void CanvasTheme::read_create_message(cereal::PortableBinaryInputArchive& a) { void CanvasTheme::write_create_message(cereal::PortableBinaryOutputArchive& a) const { backColor.write_create_message(a); } + +void CanvasTheme::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(convert_vec3(get_back_color())); +} + +void CanvasTheme::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + backColor = world.netObjMan.make_obj_direct(world.main.defaultCanvasBackgroundColor); + set_tool_front_color(world.drawProg); + + if(version < VersionNumber(0, 1, 0)) + set_back_color(DEFAULT_CANVAS_BACKGROUND_COLOR); + else { + Vector3f canvasBackColor; + a(canvasBackColor); + const Vector3f OLD_DEFAULT_CANVAS_BACKGROUND_COLOR{0.12f, 0.12f, 0.12f}; + if(version < VersionNumber(0, 3, 0) && canvasBackColor == OLD_DEFAULT_CANVAS_BACKGROUND_COLOR) + set_back_color(DEFAULT_CANVAS_BACKGROUND_COLOR); + else + set_back_color(canvasBackColor); + } +} diff --git a/src/CanvasTheme.hpp b/src/CanvasTheme.hpp index e71fdcd..352bedf 100644 --- a/src/CanvasTheme.hpp +++ b/src/CanvasTheme.hpp @@ -4,6 +4,7 @@ #include #include #include +#include class DrawingProgram; class World; @@ -11,13 +12,15 @@ class World; class CanvasTheme { public: CanvasTheme(World& w); - void init(); + void server_init_no_file(); SkColor4f get_back_color() const; const SkColor4f& get_tool_front_color() const; void set_back_color(const Vector3f& newBackColor); void register_class(); void read_create_message(cereal::PortableBinaryInputArchive& a); void write_create_message(cereal::PortableBinaryOutputArchive& a) const; + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); private: void set_tool_front_color(DrawingProgram& drawP); struct BackColor { diff --git a/src/ConnectionManager.cpp b/src/ConnectionManager.cpp deleted file mode 100644 index 35bfe0d..0000000 --- a/src/ConnectionManager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "ConnectionManager.hpp" -#include "Helpers/Networking/NetLibrary.hpp" -#include "CommandList.hpp" -#include -#include "World.hpp" -#include - -void ConnectionManager::connect_p2p(World& initWorld, const std::string& serverFullID) { - client = std::make_shared(serverFullID); - lastKeepAliveTime = std::chrono::steady_clock::now(); - NetLibrary::register_client(client); - initWorld.netObjMan.set_client(client, SERVER_UPDATE_NETWORK_OBJECT, SERVER_UPDATE_MANY_NETWORK_OBJECTS); -} - -void ConnectionManager::update() { - if(client) { - client->update(); - if(std::chrono::steady_clock::now() - lastKeepAliveTime > std::chrono::seconds(2)) { - client->send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_KEEP_ALIVE); - lastKeepAliveTime = std::chrono::steady_clock::now(); - } - } -} - -void ConnectionManager::client_add_recv_callback(uint32_t commandID, const NetClientRecvCallback &callback) { - if(client) - client->add_recv_callback(commandID, callback); -} - -bool ConnectionManager::is_client_disconnected() { - return client && client->is_disconnected(); -} - -bool ConnectionManager::client_exists() { - return client != nullptr; -} - -NetLibrary::DownloadProgress ConnectionManager::client_get_resource_retrieval_progress() { - return client->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL); -} diff --git a/src/ConnectionManager.hpp b/src/ConnectionManager.hpp deleted file mode 100644 index a541e6c..0000000 --- a/src/ConnectionManager.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -class World; - -class ConnectionManager { - public: - void connect_p2p(World& initWorld, const std::string& serverFullID); - void update(); - void client_add_recv_callback(uint32_t commandID, const NetClientRecvCallback &callback); - template void client_send_items_to_server(const std::string& channel, Args&&... items) { - if(client) - client->send_items_to_server(channel, items...); - } - bool is_client_disconnected(); - bool host_exists(); - bool client_exists(); - NetLibrary::DownloadProgress client_get_resource_retrieval_progress(); - private: - std::shared_ptr client; - std::chrono::steady_clock::time_point lastKeepAliveTime; -}; diff --git a/src/DrawCamera.cpp b/src/DrawCamera.cpp index 1232cff..a1a9f10 100755 --- a/src/DrawCamera.cpp +++ b/src/DrawCamera.cpp @@ -169,3 +169,14 @@ void DrawCamera::update_main(World& w) { if(c.inverseScale < WorldScalar(1)) w.scale_up_step(); } + +void DrawCamera::save_file(cereal::PortableBinaryOutputArchive& a, const World& w) const { + a(c, w.main.window.size.cast().eval()); +} + +void DrawCamera::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, World& w) { + CoordSpaceHelper coordsToJumpTo; + Vector2f windowSizeToJumpTo; + a(coordsToJumpTo, windowSizeToJumpTo); + smooth_move_to(w, coordsToJumpTo, windowSizeToJumpTo, true); +} diff --git a/src/DrawCamera.hpp b/src/DrawCamera.hpp index 0a9bd91..673a23a 100644 --- a/src/DrawCamera.hpp +++ b/src/DrawCamera.hpp @@ -4,8 +4,7 @@ #include "SharedTypes.hpp" #include #include "CoordSpaceHelper.hpp" - -#include "include/core/SkMatrix.h" +#include using namespace Eigen; @@ -26,6 +25,9 @@ class DrawCamera { void update_main(World& main); void scale_up(World& w, const WorldScalar& scaleUpAmount); + + void save_file(cereal::PortableBinaryOutputArchive& a, const World& w) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, World& w); private: struct SmoothMove { CoordSpaceHelper start; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 3dd8e9f..8b3b7bb 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -45,8 +45,8 @@ DrawingProgram::DrawingProgram(World& initWorld): drawTool = DrawingProgramToolBase::allocate_tool_type(*this, DrawingProgramToolType::BRUSH); } -void DrawingProgram::init() { - layerMan.init(); +void DrawingProgram::server_init_no_file() { + layerMan.server_init_no_file(); } void DrawingProgram::scale_up(const WorldScalar& scaleUpAmount) { @@ -83,7 +83,7 @@ void DrawingProgram::init_server_callbacks() { } void DrawingProgram::init_client_callbacks() { - world.con.client_add_recv_callback(CLIENT_TRANSFORM_MANY_COMPONENTS, [&](cereal::PortableBinaryInputArchive& message) { + world.netClient->add_recv_callback(CLIENT_TRANSFORM_MANY_COMPONENTS, [&](cereal::PortableBinaryInputArchive& message) { std::vector> transforms; message(transforms); process_transform_message(transforms); @@ -111,7 +111,7 @@ void DrawingProgram::send_transforms_for(const std::vectorsend_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms); else - world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_MANY_COMPONENTS, transforms); + world.netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_MANY_COMPONENTS, transforms); } } @@ -538,29 +538,11 @@ void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, co } void DrawingProgram::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { - //uint64_t compCount; - //a(compCount); - //for(uint64_t i = 0; i < compCount; i++) { - // DrawComponentType t; - // a(t); - // auto newComp = DrawComponent::allocate_comp_type(t); - // a(newComp->id, newComp->coords); - // newComp->load_file(a, version); - // components.init_emplace_back(newComp); - //} - //parallel_loop_all_components([&](const auto& c){ - // c->obj->commit_update(*this, false); - //}); - //compCache.test_rebuild(components.client_list(), true); + layerMan.load_file(a, version); } void DrawingProgram::save_file(cereal::PortableBinaryOutputArchive& a) const { - //auto& cList = components->get_data(); - //a((uint64_t)cList.size()); - //for(size_t i = 0; i < cList.size(); i++) { - // a(cList[i]->obj->get_type(), cList[i]->obj->id, cList[i]->obj->coords); - // cList[i]->obj->save_file(a); - //} + layerMan.save_file(a); } void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index a9cf501..9dc65a6 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -23,7 +23,7 @@ class World; class DrawingProgram { public: DrawingProgram(World& initWorld); - void init(); + void server_init_no_file(); void toolbar_gui(); void tool_options_gui(); bool right_click_popup_gui(Vector2f popupPos); diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp index fda64c9..db0c917 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp @@ -1,6 +1,7 @@ #include "DrawingProgramLayer.hpp" #include "DrawingProgramLayerManager.hpp" #include "../DrawingProgram.hpp" +#include "../../World.hpp" #include void DrawingProgramLayer::draw(SkCanvas* canvas, const DrawData& drawData) const { @@ -12,8 +13,10 @@ void DrawingProgramLayer::set_component_list_callbacks(DrawingProgramLayerListIt auto insertCallback = [&](const CanvasComponentContainer::ObjInfoIterator& c) { c->obj->objInfo = c; c->obj->parentLayer = &layerListItem; - c->obj->commit_update(layerMan.drawP); // Run commit update on insert so that world bounds are calculated - layerMan.drawP.drawCache.add_component(&(*c)); + if(layerMan.commitUpdateOnComponentInsert) { + c->obj->commit_update(layerMan.drawP); // Run commit update on insert so that world bounds are calculated + layerMan.drawP.drawCache.add_component(&(*c)); + } if(c->obj->get_comp().get_type() == CanvasComponentType::IMAGE) layerMan.drawP.updateableComponents.emplace(&(*c)); }; @@ -41,12 +44,6 @@ void DrawingProgramLayer::set_to_erase() { eraseCallback(it); } -void DrawingProgramLayer::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const { - parallel_loop_container(*components, [&layerMan](auto& comp) { - comp.obj->commit_update_dont_invalidate_cache(layerMan.drawP); - }); -} - void DrawingProgramLayer::get_flattened_component_list(std::vector& objList) const { for(auto& p : *components) objList.emplace_back(&p); @@ -56,3 +53,20 @@ void DrawingProgramLayer::scale_up(const WorldScalar& scaleUpAmount) { for(auto& p : *components) p.obj->scale_up(scaleUpAmount); } + +void DrawingProgramLayer::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) { + components = layerMan.drawP.world.netObjMan.make_obj(); + uint32_t layerListSize; + a(layerListSize); + for(uint32_t i = 0; i < layerListSize; i++) { + CanvasComponentContainer* item = new CanvasComponentContainer(); + item->load_file(a, version, layerMan.drawP.world.netObjMan); + components->push_back_and_send_create(components, item); + } +} + +void DrawingProgramLayer::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(components->size()); + for(auto& comp : *components) + comp.obj->save_file(a); +} diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp index fa7b98b..2692b36 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp @@ -10,12 +10,14 @@ class DrawingProgramLayer { public: void draw(SkCanvas* canvas, const DrawData& drawData) const; void set_component_list_callbacks(DrawingProgramLayerListItem& layerListItem, DrawingProgramLayerManager& layerMan); - void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const; void get_flattened_component_list(std::vector& objList) const; void set_to_erase(); void scale_up(const WorldScalar& scaleUpAmount); CanvasComponentContainer::NetListOwnerPtr components; + + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan); + void save_file(cereal::PortableBinaryOutputArchive& a) const; private: std::function eraseCallback; }; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp index 0016901..6f095fe 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp @@ -2,6 +2,9 @@ #include "DrawingProgramLayerListItem.hpp" #include "DrawingProgramLayer.hpp" #include +#include "DrawingProgramLayerManager.hpp" +#include "../DrawingProgram.hpp" +#include "../../World.hpp" void DrawingProgramLayerFolder::draw(SkCanvas* canvas, const DrawData& drawData) const { for(auto& p : (*folderList) | std::views::reverse) @@ -24,11 +27,6 @@ void DrawingProgramLayerFolder::set_to_erase() { listItem.obj->set_to_erase(); } -void DrawingProgramLayerFolder::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const { - for(auto& listItem : *folderList) - listItem.obj->commit_update_dont_invalidate_cache(layerMan); -} - void DrawingProgramLayerFolder::get_flattened_component_list(std::vector& objList) const { for(auto& listItem : (*folderList) | std::views::reverse) listItem.obj->get_flattened_component_list(objList); @@ -54,3 +52,20 @@ void DrawingProgramLayerFolder::scale_up(const WorldScalar& scaleUpAmount) { for(auto& p : *folderList) p.obj->scale_up(scaleUpAmount); } + +void DrawingProgramLayerFolder::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) { + folderList = layerMan.drawP.world.netObjMan.make_obj>(); + uint32_t folderListSize; + a(folderListSize); + for(uint32_t i = 0; i < folderListSize; i++) { + DrawingProgramLayerListItem* item = new DrawingProgramLayerListItem(); + item->load_file(a, version, layerMan); + folderList->push_back_and_send_create(folderList, item); + } +} + +void DrawingProgramLayerFolder::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(folderList->size()); + for(auto& listItem : *folderList) + listItem.obj->save_file(a); +} diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp index aa4d1c4..45a2ba1 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp @@ -11,7 +11,6 @@ class DrawingProgramLayerFolder { public: void draw(SkCanvas* canvas, const DrawData& drawData) const; void set_component_list_callbacks(DrawingProgramLayerManager& layerMan); - void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const; void get_flattened_component_list(std::vector& objList) const; void set_to_erase(); NetworkingObjects::NetObjWeakPtr get_initial_editing_layer() const; @@ -19,4 +18,7 @@ class DrawingProgramLayerFolder { NetworkingObjects::NetObjOwnerPtr> folderList; bool isFolderOpen = false; + + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan); + void save_file(cereal::PortableBinaryOutputArchive& a) const; }; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp index 881423a..4c1682d 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp @@ -46,13 +46,6 @@ void DrawingProgramLayerListItem::set_component_list_callbacks(DrawingProgramLay layerData->set_component_list_callbacks(*this, layerMan); } -void DrawingProgramLayerListItem::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) { - if(folderData) - folderData->commit_update_dont_invalidate_cache(layerMan); - else - layerData->commit_update_dont_invalidate_cache(layerMan); -} - void DrawingProgramLayerListItem::get_flattened_component_list(std::vector& objList) const { if(folderData) folderData->get_flattened_component_list(objList); @@ -99,6 +92,35 @@ DrawingProgramLayer& DrawingProgramLayerListItem::get_layer() const { return *layerData; } +void DrawingProgramLayerListItem::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) { + nameData = layerMan.drawP.world.netObjMan.make_obj(); + a(*nameData); + + displayData = layerMan.drawP.world.netObjMan.make_obj(); + a(*displayData); + + bool isFolder; + a(isFolder); + if(isFolder) { + folderData = std::make_unique(); + folderData->load_file(a, version, layerMan); + } + else { + layerData = std::make_unique(); + layerData->load_file(a, version, layerMan); + } +} + +void DrawingProgramLayerListItem::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(*nameData); + a(*displayData); + a(static_cast(folderData)); + if(folderData) + folderData->save_file(a); + else + layerData->save_file(a); +} + void DrawingProgramLayerListItem::draw(SkCanvas* canvas, const DrawData& drawData) const { if(displayData->visible) { SkPaint layerPaint; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp index db99403..f8da55f 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp @@ -23,7 +23,6 @@ class DrawingProgramLayerListItem { void reassign_netobj_ids_call(); void set_to_erase(); void set_component_list_callbacks(DrawingProgramLayerManager &layerMan); - void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan); void draw(SkCanvas* canvas, const DrawData& drawData) const; void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) const; const std::string& get_name() const; @@ -34,6 +33,9 @@ class DrawingProgramLayerListItem { void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const; float get_alpha() const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan); + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void set_visible(DrawingProgramLayerManager& layerMan, bool newVisible) const; bool get_visible() const; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index c98cc4e..5cd4903 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -1,18 +1,17 @@ #include "DrawingProgramLayerManager.hpp" #include "../../World.hpp" #include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" +#include "Helpers/Parallel.hpp" DrawingProgramLayerManager::DrawingProgramLayerManager(DrawingProgram& drawProg): drawP(drawProg), // initialize drawP first for next objects to be initialized properly listGUI(*this) {} -void DrawingProgramLayerManager::init() { - if(drawP.world.netObjMan.is_server()) { - layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr(new DrawingProgramLayerListItem(drawP.world.netObjMan, "ROOT", true)); - layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well - editingLayer = layerTreeRoot->get_folder().folderList->emplace_back_direct(layerTreeRoot->get_folder().folderList, drawP.world.netObjMan, "First Layer", false)->obj; - } +void DrawingProgramLayerManager::server_init_no_file() { + layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr(new DrawingProgramLayerListItem(drawP.world.netObjMan, "ROOT", true)); + layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well + editingLayer = layerTreeRoot->get_folder().folderList->emplace_back_direct(layerTreeRoot->get_folder().folderList, drawP.world.netObjMan, "First Layer", false)->obj; } void DrawingProgramLayerManager::scale_up(const WorldScalar& scaleUpAmount) { @@ -25,8 +24,14 @@ void DrawingProgramLayerManager::write_components_server(cereal::PortableBinaryO void DrawingProgramLayerManager::read_components_client(cereal::PortableBinaryInputArchive& a) { layerTreeRoot = drawP.world.netObjMan.read_create_message(a, nullptr); - layerTreeRoot->commit_update_dont_invalidate_cache(*this); + commitUpdateOnComponentInsert = false; layerTreeRoot->set_component_list_callbacks(*this); + commitUpdateOnComponentInsert = true; + auto flattenedCompList = get_flattened_component_list(); + parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) { + comp->obj->commit_update_dont_invalidate_cache(drawP); + }); + drawP.rebuild_cache(); editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer(); } @@ -97,3 +102,21 @@ CanvasComponentContainer::ObjInfo* DrawingProgramLayerManager::add_component_to_ return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj)); } + +void DrawingProgramLayerManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr(new DrawingProgramLayerListItem()); + layerTreeRoot->load_file(a, version, *this); + commitUpdateOnComponentInsert = false; + layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well + commitUpdateOnComponentInsert = true; + auto flattenedCompList = get_flattened_component_list(); + parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) { + comp->obj->commit_update_dont_invalidate_cache(drawP); + }); + drawP.rebuild_cache(); + editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer(); +} + +void DrawingProgramLayerManager::save_file(cereal::PortableBinaryOutputArchive& a) const { + layerTreeRoot->save_file(a); +} diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp index dec6427..034d575 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp @@ -13,6 +13,7 @@ class DrawingProgramLayerManager { NetworkingObjects::NetObjOwnerPtr layerTreeRoot; NetworkingObjects::NetObjWeakPtr editingLayer; void set_initial_editing_layer(); + bool commitUpdateOnComponentInsert = true; public: enum class LayerSelector { ALL_VISIBLE_LAYERS, @@ -20,7 +21,7 @@ class DrawingProgramLayerManager { }; DrawingProgramLayerManager(DrawingProgram& drawProg); - void init(); + void server_init_no_file(); void draw(SkCanvas* canvas, const DrawData& drawData); void write_components_server(cereal::PortableBinaryOutputArchive& a); void read_components_client(cereal::PortableBinaryInputArchive& a); @@ -39,6 +40,9 @@ class DrawingProgramLayerManager { CanvasComponentContainer::ObjInfoIterator get_edited_layer_end_iterator(); bool component_passes_layer_selector(CanvasComponentContainer::ObjInfo* c, LayerSelector layerSelector); + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); + void save_file(cereal::PortableBinaryOutputArchive& a) const; + bool layer_tree_root_exists(); const DrawingProgramLayerListItem& get_layer_root(); uint32_t total_component_count(); diff --git a/src/GridManager.cpp b/src/GridManager.cpp index 882cc51..03b5f25 100644 --- a/src/GridManager.cpp +++ b/src/GridManager.cpp @@ -5,9 +5,8 @@ GridManager::GridManager(World& w): world(w) {} -void GridManager::init() { - if(world.netObjMan.is_server()) - grids = world.netObjMan.make_obj>(); +void GridManager::server_init_no_file() { + grids = world.netObjMan.make_obj>(); } void GridManager::add_default_grid(const std::string& newName) { @@ -71,3 +70,21 @@ void GridManager::scale_up(const WorldScalar& scaleUpAmount) { grids->at(i)->obj->scale_up(scaleUpAmount); } } + +void GridManager::save_file(cereal::PortableBinaryOutputArchive& a) const { + a(grids->size()); + for(auto& item : *grids) + a(*item.obj); +} + +void GridManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { + grids = world.netObjMan.make_obj>(); + + uint32_t gridSize; + a(gridSize); + for(uint32_t i = 0; i < gridSize; i++) { + WorldGrid* g = new WorldGrid; + a(*g); + grids->push_back_and_send_create(grids, g); + } +} diff --git a/src/GridManager.hpp b/src/GridManager.hpp index 0f19d5a..96de7f9 100644 --- a/src/GridManager.hpp +++ b/src/GridManager.hpp @@ -8,7 +8,7 @@ class World; class GridManager { public: GridManager(World& w); - void init(); + void server_init_no_file(); void add_default_grid(const std::string& newName); @@ -32,6 +32,8 @@ class GridManager { void draw_front(SkCanvas* canvas, const DrawData& drawData); void draw_coordinates(SkCanvas* canvas, const DrawData& drawData); void scale_up(const WorldScalar& scaleUpAmount); + void save_file(cereal::PortableBinaryOutputArchive& a) const; + void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); NetworkingObjects::NetObjOwnerPtr> grids; World& world; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 8a34033..84ebba0 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -71,7 +71,7 @@ void MainProgram::update() { const std::filesystem::path& droppedFilePath = droppedItem.dataPath.value(); if(droppedFilePath.has_extension() && droppedFilePath.extension().string() == std::string("." + World::FILE_EXTENSION)) { new_tab({ - .conType = World::CONNECTIONTYPE_LOCAL, + .isClient = false, .filePathSource = droppedFilePath }, true); return true; @@ -93,7 +93,7 @@ void MainProgram::update() { worldIndex = worlds.size() - 1; if(worlds.size() == 0) new_tab({ - .conType = World::CONNECTIONTYPE_LOCAL + .isClient = false }, true); std::shared_ptr oldWorld = world; @@ -131,7 +131,7 @@ void MainProgram::update() { void MainProgram::update_display_names() { for(auto& w : worlds) { - if(!w->network_being_used()) + if(!w->netObjMan.is_connected()) w->ownClientData->set_display_name(displayName); } } @@ -284,7 +284,7 @@ void MainProgram::draw(SkCanvas* canvas) { bool MainProgram::network_being_used() { for(auto& w : worlds) { - if(w->network_being_used()) + if(w->netObjMan.is_connected()) return true; } return false; @@ -292,7 +292,7 @@ bool MainProgram::network_being_used() { bool MainProgram::net_server_hosted() { for(auto& w : worlds) { - if(w->conType == World::CONNECTIONTYPE_SERVER) + if(w->netServer) return true; } return false; diff --git a/src/ResourceManager.cpp b/src/ResourceManager.cpp index 58a8163..6096b8b 100644 --- a/src/ResourceManager.cpp +++ b/src/ResourceManager.cpp @@ -18,14 +18,14 @@ ResourceManager::ResourceManager(World& initWorld): {} void ResourceManager::init_client_callbacks() { - world.con.client_add_recv_callback(SERVER_NEW_RESOURCE_ID, [&](cereal::PortableBinaryInputArchive& message) { + world.netClient->add_recv_callback(SERVER_NEW_RESOURCE_ID, [&](cereal::PortableBinaryInputArchive& message) { NetworkingObjects::NetObjID idBeingRetrieved; message(idBeingRetrieved); // There is a scenario where the resource id and data messages can be sent twice for the same resource (a resource can be sent early before CLIENT_INITIAL_DATA is sent, and then resent with CLIENT_INITIAL_DATA), so check if resource already exists, and only keep track of the ID if the resource doesn't exist yet if(!world.netObjMan.get_obj_temporary_ref_from_id(idBeingRetrieved)) resourcesBeingRetrieved.emplace(idBeingRetrieved, std::weak_ptr()); }); - world.con.client_add_recv_callback(SERVER_NEW_RESOURCE_DATA, [&](cereal::PortableBinaryInputArchive& message) { + world.netClient->add_recv_callback(SERVER_NEW_RESOURCE_DATA, [&](cereal::PortableBinaryInputArchive& message) { if(!resourcesBeingRetrieved.empty()) { // If the resource was sent for the second time, this will be empty, so we can ignore the message ResourceData newResource; message(newResource); @@ -69,8 +69,8 @@ float ResourceManager::get_resource_retrieval_progress(const NetworkingObjects:: return 0.0f; return static_cast(progressBytes.downloadedBytes) / static_cast(progressBytes.totalBytes); } - else if(world.con.client_exists() && !world.con.is_client_disconnected()) { - NetLibrary::DownloadProgress progressBytes = world.con.client_get_resource_retrieval_progress(); + else if(world.netClient) { + NetLibrary::DownloadProgress progressBytes = world.netClient->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL); if(progressBytes.totalBytes == 0) return 0.0f; return static_cast(progressBytes.downloadedBytes) / static_cast(progressBytes.totalBytes); @@ -133,9 +133,9 @@ const NetworkingObjects::NetObjOwnerPtr& ResourceManager::add_reso world.netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id()); world.netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource); } - else { - world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id()); - world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource); + else if(world.netClient) { + world.netClient->send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id()); + world.netClient->send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource); } return resourceInsert; } diff --git a/src/ScaleUpCanvas.cpp b/src/ScaleUpCanvas.cpp index 8bc7a95..fb9c0c0 100644 --- a/src/ScaleUpCanvas.cpp +++ b/src/ScaleUpCanvas.cpp @@ -1,5 +1,5 @@ #include "ScaleUpCanvas.hpp" WorldScalar get_canvas_scale_up_amount(uint32_t newGridSize, uint32_t oldGridSize) { - return FixedPoint::pow_int(CANVAS_SCALE_UP_STEP, newGridSize - oldGridSize); + return FixedPoint::pow_int(WorldScalar(10000), newGridSize - oldGridSize); } diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 5f15326..ad608bb 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -469,10 +469,10 @@ void Toolbar::top_toolbar() { } std::vector> tabNames; for(size_t i = 0; i < main.worlds.size(); i++) - tabNames.emplace_back(main.worlds[i]->network_being_used() ? "data/icons/network.svg" : "", main.worlds[i]->name); + tabNames.emplace_back(main.worlds[i]->netObjMan.is_connected() ? "data/icons/network.svg" : "", main.worlds[i]->name); std::optional closedTab; gui.tab_list("file tab list", tabNames, main.worldIndex, closedTab); - if(main.world->network_being_used() && gui.svg_icon_button_transparent("Player List Toggle Button", "data/icons/list.svg", playerMenuOpen)) + if(main.world->netObjMan.is_connected() && gui.svg_icon_button_transparent("Player List Toggle Button", "data/icons/list.svg", playerMenuOpen)) playerMenuOpen = !playerMenuOpen; if(gui.svg_icon_button_transparent("Menu Undo Button", "data/icons/undo.svg")) main.world->undo_with_checks(); @@ -528,7 +528,7 @@ void Toolbar::top_toolbar() { gui.obstructing_window(); if(gui.text_button_left_transparent("new file local", "New File")) { main.new_tab({ - .conType = World::CONNECTIONTYPE_LOCAL + .isClient = false }, true); } if(gui.text_button_left_transparent("save file", "Save")) @@ -536,7 +536,7 @@ void Toolbar::top_toolbar() { if(gui.text_button_left_transparent("save as file", "Save As")) save_as_func(); if(gui.text_button_left_transparent("open file", "Open")) - open_world_file(World::CONNECTIONTYPE_LOCAL, "", ""); + open_world_file(false, "", ""); if(gui.text_button_left_transparent("screenshot", "Take Screenshot")) main.world->drawProg.switch_to_tool(DrawingProgramToolType::SCREENSHOT); if(gui.text_button_left_transparent("add image or file to canvas", "Add Image/File to Canvas")) { @@ -555,7 +555,7 @@ void Toolbar::top_toolbar() { }); #endif } - if(main.world->network_being_used()) { + if(main.world->netObjMan.is_connected()) { if(gui.text_button_left_transparent("lobby info", "Lobby Info")) { optionsMenuOpen = true; optionsMenuType = LOBBY_INFO_MENU; @@ -877,7 +877,7 @@ std::unique_ptr Toolbar::build_paragraph_from_chat_ void Toolbar::chat_box() { constexpr float CHATBOX_WIDTH = 700; - if(main.world->network_being_used()) { + if(main.world->netObjMan.is_connected()) { CLAY_AUTO_ID({ .layout = { .layoutDirection = CLAY_LEFT_TO_RIGHT @@ -1297,15 +1297,15 @@ void Toolbar::player_list() { } } -void Toolbar::open_world_file(int conType, const std::string& netSource, const std::string& serverLocalID2) { +void Toolbar::open_world_file(bool isClient, const std::string& netSource, const std::string& serverLocalID2) { #ifdef __EMSCRIPTEN__ static struct UploadData { - int cT; + bool iC; std::string nS; std::string sLID; MainProgram* main; } uploadData; - uploadData.cT = conType; + uploadData.iC = isClient; uploadData.nS = netSource; uploadData.sLID = serverLocalID2; uploadData.main = &main; @@ -1313,7 +1313,7 @@ void Toolbar::open_world_file(int conType, const std::string& netSource, const s if(!buffer.empty()) { UploadData* uD = (UploadData*)callbackData; uD->main->new_tab({ - .conType = (World::ConnectionType)uD->cT, + .isClient = uD->iC, .filePathSource = std::filesystem::path(fileName), .netSource = uD->nS, .serverLocalID = uD->sLID, @@ -1322,9 +1322,9 @@ void Toolbar::open_world_file(int conType, const std::string& netSource, const s } }, &uploadData); #else - open_file_selector("Open", {{"Any File", "*"}, {"InfiniPaint Canvas", World::FILE_EXTENSION}}, [&, conType = conType, netSource = netSource, serverLocalID2 = serverLocalID2](const std::filesystem::path& p, const auto& e) { + open_file_selector("Open", {{"Any File", "*"}, {"InfiniPaint Canvas", World::FILE_EXTENSION}}, [&, isClient = isClient, netSource = netSource, serverLocalID2 = serverLocalID2](const std::filesystem::path& p, const auto& e) { main.new_tab({ - .conType = (World::ConnectionType)conType, + .isClient = isClient, .filePathSource = p, .netSource = netSource, .serverLocalID = serverLocalID2 @@ -1378,7 +1378,7 @@ void Toolbar::options_menu() { Logger::get().log("USERINFO", "Connect issue: Can't connect to your own address"); else { main.new_tab({ - .conType = World::CONNECTIONTYPE_CLIENT, + .isClient = true, .netSource = serverToConnectTo }, true); optionsMenuOpen = false; @@ -1647,7 +1647,7 @@ void Toolbar::options_menu() { }) { gui.push_id("lobby info menu"); gui.obstructing_window(); - if(!main.world || !main.world->network_being_used()) + if(!main.world || !main.world->netObjMan.is_connected()) optionsMenuOpen = false; else { std::string oldS = main.world->netSource; diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index 55b9eb7..41a0190 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -109,7 +109,7 @@ class Toolbar { void file_picker_gui(); void performance_metrics(); bool color_palette(const std::string& id, Vector4f* color, bool& hoveringOnDropdown); - void open_world_file(int conType, const std::string& netSource, const std::string& serverLocalID); + void open_world_file(bool isClient, const std::string& netSource, const std::string& serverLocalID); void load_default_palette(); void load_default_theme(); void about_menu_gui(); diff --git a/src/VersionConstants.cpp b/src/VersionConstants.cpp index 1fe16ff..4ad625b 100644 --- a/src/VersionConstants.cpp +++ b/src/VersionConstants.cpp @@ -10,6 +10,7 @@ VersionNumber header_to_version_number(const std::string& header) { m["INFPNT000002"] = VersionNumber(0, 1, 0); m["INFPNT000003"] = VersionNumber(0, 2, 0); m["INFPNT000004"] = VersionNumber(0, 3, 0); + m["INFPNT000005"] = VersionNumber(0, 4, 0); } auto it = m.find(header); if(it == m.end()) diff --git a/src/VersionConstants.hpp b/src/VersionConstants.hpp index 5c1d065..3d919cc 100644 --- a/src/VersionConstants.hpp +++ b/src/VersionConstants.hpp @@ -10,7 +10,7 @@ namespace VersionConstants { VersionNumber header_to_version_number(const std::string& header); constexpr int SAVEFILE_HEADER_LEN = 12; // DO NOT CHANGE THIS HEADER LENGTH - const std::string CURRENT_SAVEFILE_HEADER = "INFPNT000004"; // Change whenever the save file is incompatible with the previous version - const std::string CURRENT_VERSION_STRING = "0.3.1"; - constexpr VersionNumber CURRENT_VERSION_NUMBER(0, 3, 1); + const std::string CURRENT_SAVEFILE_HEADER = "INFPNT000005"; // Change whenever the save file is incompatible with the previous version + const std::string CURRENT_VERSION_STRING = "0.4.0"; + constexpr VersionNumber CURRENT_VERSION_NUMBER(0, 4, 0); } diff --git a/src/World.cpp b/src/World.cpp index 624e679..81c97f9 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -36,7 +36,7 @@ #endif World::World(MainProgram& initMain, OpenWorldInfo& worldInfo): - netObjMan(worldInfo.conType != CONNECTIONTYPE_CLIENT), + netObjMan(!worldInfo.isClient), main(initMain), rMan(*this), drawProg(*this), @@ -45,52 +45,31 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo): canvasTheme(*this) { init_net_obj_type_list(); - init_client_data_list(); - gridMan.init(); - bMan.init(); - drawProg.init(); - canvasTheme.init(); netSource = worldInfo.netSource; - if(worldInfo.conType == CONNECTIONTYPE_CLIENT || worldInfo.conType == CONNECTIONTYPE_SERVER) - main.init_net_library(); - drawData.rMan = &rMan; drawData.main = &main; - conType = worldInfo.conType; - switch(conType) { - case CONNECTIONTYPE_CLIENT: { - clientStillConnecting = true; - con.connect_p2p(*this, netSource); - set_name(""); - break; - } - case CONNECTIONTYPE_LOCAL: { - if(worldInfo.filePathSource.has_value()) - load_from_file(worldInfo.filePathSource.value(), worldInfo.fileDataBuffer); - set_name(name); - break; - } - case CONNECTIONTYPE_SERVER: { - break; - } + if(worldInfo.isClient) + init_client(worldInfo.netSource); + else { + init_client_data_list(); + if(worldInfo.filePathSource.has_value()) + load_from_file(worldInfo.filePathSource.value(), worldInfo.fileDataBuffer); + else + load_empty_canvas(); + set_name(name); } - - init_client_callbacks(); - con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.displayName); } void World::init_client_data_list() { - if(netObjMan.is_server()) { - clients = netObjMan.make_obj>(); - ownClientData = clients->emplace_direct(clients, ClientData::InitStruct{ - .cursorColor = get_random_cursor_color(), - .displayName = main.displayName - }); - init_client_data_list_callbacks(); - } + clients = netObjMan.make_obj>(); + ownClientData = clients->emplace_direct(clients, ClientData::InitStruct{ + .cursorColor = get_random_cursor_color(), + .displayName = main.displayName + }); + init_client_data_list_callbacks(); } Vector3f World::get_random_cursor_color() { @@ -124,56 +103,18 @@ void World::init_net_obj_type_list() { NetworkingObjects::register_unordered_set_class(netObjMan); } -void World::init_server_callbacks() { - rMan.init_server_callbacks(); - drawProg.init_server_callbacks(); - netServer->add_recv_callback(SERVER_INITIAL_DATA, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - ClientData::InitStruct newClientData; - newClientData.cursorColor = get_random_cursor_color(); - message(newClientData.displayName); - ensure_display_name_unique(newClientData.displayName); +void World::init_client(const std::string& serverFullID) { + main.init_net_library(); + clientStillConnecting = true; + netClient = std::make_shared(serverFullID); + lastKeepAliveSent = std::chrono::steady_clock::now(); + NetLibrary::register_client(netClient); + netObjMan.set_client(netClient, SERVER_UPDATE_NETWORK_OBJECT, SERVER_UPDATE_MANY_NETWORK_OBJECTS); + set_name(""); - newClientData.camCoords = ownClientData->get_cam_coords(); - newClientData.windowSize = ownClientData->get_window_size(); - newClientData.gridSize = ownClientData->get_grid_size(); - - NetworkingObjects::NetObjTemporaryPtr clientDataObjPtr = clients->emplace_direct(clients, newClientData); - client->customID = clientDataObjPtr.get_net_id().data; - auto ss(std::make_shared()); - { - cereal::PortableBinaryOutputArchive a(*ss); - a(CLIENT_INITIAL_DATA, name, clientDataObjPtr.get_net_id()); - bMan.bookmarkListRoot.write_create_message(a); - gridMan.grids.write_create_message(a); - drawProg.write_components_server(a); - canvasTheme.write_create_message(a); - clients.write_create_message(a); - } - netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss); - for(auto& r : rMan.resource_list()) { - netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, r.get_net_id()); - netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, *r); - } - }); - netServer->add_recv_callback(SERVER_UPDATE_NETWORK_OBJECT, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - netObjMan.read_update_message(message, client); - }); - netServer->add_recv_callback(SERVER_UPDATE_MANY_NETWORK_OBJECTS, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - netObjMan.read_many_update_message(message, client); - }); - netServer->add_recv_callback(SERVER_KEEP_ALIVE, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { - }); - netServer->add_disconnect_callback([&](std::shared_ptr client) { - NetworkingObjects::NetObjID idToErase; - idToErase.data = client->customID; - clients->erase(clients, idToErase); - }); -} - -void World::init_client_callbacks() { rMan.init_client_callbacks(); drawProg.init_client_callbacks(); - con.client_add_recv_callback(CLIENT_INITIAL_DATA, [&](cereal::PortableBinaryInputArchive& message) { + netClient->add_recv_callback(CLIENT_INITIAL_DATA, [&](cereal::PortableBinaryInputArchive& message) { std::string fileDisplayName; NetworkingObjects::NetObjID clientDataObjID; message(fileDisplayName, clientDataObjID); @@ -189,43 +130,22 @@ void World::init_client_callbacks() { clientStillConnecting = false; }); - con.client_add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) { + netClient->add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) { netObjMan.read_update_message(message, nullptr); }); - con.client_add_recv_callback(CLIENT_UPDATE_MANY_NETWORK_OBJECTS, [&](cereal::PortableBinaryInputArchive& message) { + netClient->add_recv_callback(CLIENT_UPDATE_MANY_NETWORK_OBJECTS, [&](cereal::PortableBinaryInputArchive& message) { netObjMan.read_many_update_message(message, nullptr); }); - con.client_add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) { + netClient->add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) { }); + + netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.displayName); } void World::focus_update() { - con.update(); - - if(netServer) { - if(netServer->is_disconnected()) { - Logger::get().log("USERINFO", "Host connection failed"); - netSource.clear(); - netServer = nullptr; - conType = CONNECTIONTYPE_LOCAL; - con = ConnectionManager(); - netObjMan.disconnect(); - } - else { - netServer->update(); - if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) { - netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE); - lastKeepAliveSent = std::chrono::steady_clock::now(); - } - } - } - - if(con.is_client_disconnected()) { - Logger::get().log("USERINFO", "Client connection failed"); - setToDestroy = true; - netObjMan.disconnect(); + connection_update(); + if(setToDestroy) return; - } if(!clientStillConnecting) { delayedUpdateObjectManager.update(netObjMan); @@ -253,6 +173,36 @@ void World::focus_update() { redo_with_checks(); } +void World::connection_update() { + if(netServer) { + if(netServer->is_disconnected()) { + Logger::get().log("USERINFO", "Host connection failed"); + netSource.clear(); + netServer = nullptr; + netObjMan.disconnect(); + } + else { + netServer->update(); + if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) { + netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE); + lastKeepAliveSent = std::chrono::steady_clock::now(); + } + } + } + else if(netClient) { + if(netClient->is_disconnected()) { + Logger::get().log("USERINFO", "Client connection failed"); + setToDestroy = true; + netObjMan.disconnect(); + } + netClient->update(); + if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) { + netClient->send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_KEEP_ALIVE); + lastKeepAliveSent = std::chrono::steady_clock::now(); + } + } +} + void World::undo_with_checks() { if(!clientStillConnecting && !drawProg.prevent_undo_or_redo()) undo.undo(); @@ -264,18 +214,9 @@ void World::redo_with_checks() { } void World::unfocus_update() { - con.update(); - if(con.is_client_disconnected()) { - Logger::get().log("USERINFO", "Client connection failed"); - setToDestroy = true; - } - if(netServer) { - netServer->update(); - if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) { - netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE); - lastKeepAliveSent = std::chrono::steady_clock::now(); - } - } + connection_update(); + if(setToDestroy) + return; } void World::send_chat_message(const std::string& message) { @@ -302,10 +243,6 @@ void World::early_destroy() { //con.early_destroy(); } -bool World::network_being_used() { - return conType != CONNECTIONTYPE_LOCAL; -} - void World::set_name(const std::string& n) { if(n.empty()) name = "New File"; @@ -353,15 +290,55 @@ void World::ensure_display_name_unique(std::string& displayName) { } void World::start_hosting(const std::string& initNetSource, const std::string& serverLocalID) { - if(conType != CONNECTIONTYPE_LOCAL) - return; main.init_net_library(); netServer = std::make_shared(serverLocalID); + lastKeepAliveSent = std::chrono::steady_clock::now(); NetLibrary::register_server(netServer); netObjMan.set_server(netServer, CLIENT_UPDATE_NETWORK_OBJECT, CLIENT_UPDATE_MANY_NETWORK_OBJECTS); - conType = CONNECTIONTYPE_SERVER; netSource = initNetSource; - init_server_callbacks(); + rMan.init_server_callbacks(); + drawProg.init_server_callbacks(); + netServer->add_recv_callback(SERVER_INITIAL_DATA, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { + ClientData::InitStruct newClientData; + newClientData.cursorColor = get_random_cursor_color(); + message(newClientData.displayName); + ensure_display_name_unique(newClientData.displayName); + + newClientData.camCoords = ownClientData->get_cam_coords(); + newClientData.windowSize = ownClientData->get_window_size(); + newClientData.gridSize = ownClientData->get_grid_size(); + + NetworkingObjects::NetObjTemporaryPtr clientDataObjPtr = clients->emplace_direct(clients, newClientData); + client->customID = clientDataObjPtr.get_net_id().data; + auto ss(std::make_shared()); + { + cereal::PortableBinaryOutputArchive a(*ss); + a(CLIENT_INITIAL_DATA, name, clientDataObjPtr.get_net_id()); + bMan.bookmarkListRoot.write_create_message(a); + gridMan.grids.write_create_message(a); + drawProg.write_components_server(a); + canvasTheme.write_create_message(a); + clients.write_create_message(a); + } + netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss); + for(auto& r : rMan.resource_list()) { + netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, r.get_net_id()); + netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, *r); + } + }); + netServer->add_recv_callback(SERVER_UPDATE_NETWORK_OBJECT, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { + netObjMan.read_update_message(message, client); + }); + netServer->add_recv_callback(SERVER_UPDATE_MANY_NETWORK_OBJECTS, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { + netObjMan.read_many_update_message(message, client); + }); + netServer->add_recv_callback(SERVER_KEEP_ALIVE, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { + }); + netServer->add_disconnect_callback([&](std::shared_ptr client) { + NetworkingObjects::NetObjID idToErase; + idToErase.data = client->customID; + clients->erase(clients, idToErase); + }); } void World::save_to_file(const std::filesystem::path& filePathToSaveAt) { @@ -406,6 +383,13 @@ void World::save_to_file(const std::filesystem::path& filePathToSaveAt) { } } +void World::load_empty_canvas() { + gridMan.server_init_no_file(); + bMan.server_init_no_file(); + drawProg.server_init_no_file(); + canvasTheme.server_init_no_file(); +} + void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std::string_view buffer) { filePath = force_extension_on_path(filePathToLoadFrom, FILE_EXTENSION); @@ -444,33 +428,19 @@ void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std: } void World::save_file(cereal::PortableBinaryOutputArchive& a) const { - a(drawData.cam.c, main.window.size.cast().eval()); - //a(convert_vec3(canvasTheme.backColor)); + drawData.cam.save_file(a, *this); + canvasTheme.save_file(a); drawProg.save_file(a); + bMan.save_file(a); + gridMan.save_file(a); } void World::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) { - CoordSpaceHelper coordsToJumpTo; - Vector2f windowSizeToJumpTo; - a(coordsToJumpTo, windowSizeToJumpTo); - - //if(version < VersionNumber(0, 1, 0)) - // set_canvas_background_color(DEFAULT_CANVAS_BACKGROUND_COLOR); - //else { - // Vector3f canvasBackColor; - // a(canvasBackColor); - // const Vector3f OLD_DEFAULT_CANVAS_BACKGROUND_COLOR{0.12f, 0.12f, 0.12f}; - // if(version < VersionNumber(0, 3, 0) && canvasBackColor == OLD_DEFAULT_CANVAS_BACKGROUND_COLOR) - // set_canvas_background_color(DEFAULT_CANVAS_BACKGROUND_COLOR); - // else - // set_canvas_background_color(canvasBackColor); - //} - - drawData.cam.smooth_move_to(*this, coordsToJumpTo, windowSizeToJumpTo, true); + drawData.cam.load_file(a, version, *this); + canvasTheme.load_file(a, version); drawProg.load_file(a, version); - //a(bMan); - //if(version >= VersionNumber(0, 2, 0)) - // a(gridMan); + bMan.load_file(a, version); + gridMan.load_file(a, version); } WorldScalar World::calculate_zoom_from_uniform_zoom(WorldScalar uniformZoom, WorldVec oldWindowSize) { diff --git a/src/World.hpp b/src/World.hpp index b303b51..260e70b 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -5,13 +5,13 @@ #include "UndoManager.hpp" #include "Bookmarks/BookmarkManager.hpp" #include "ResourceManager.hpp" -#include "ConnectionManager.hpp" #include "DrawingProgram/DrawingProgram.hpp" #include "Toolbar.hpp" #include "SharedTypes.hpp" #include "CanvasTheme.hpp" #include "GridManager.hpp" #include +#include #include #include "ClientData.hpp" @@ -24,14 +24,8 @@ class World { static constexpr std::string FILE_EXTENSION = "infpnt"; static constexpr size_t CHAT_SIZE = 10; - enum ConnectionType : int { - CONNECTIONTYPE_CLIENT, - CONNECTIONTYPE_SERVER, - CONNECTIONTYPE_LOCAL - }; - struct OpenWorldInfo { - ConnectionType conType; + bool isClient; std::optional filePathSource; std::string netSource; std::string serverLocalID; @@ -52,7 +46,6 @@ class World { ResourceManager rMan; DrawingProgram drawProg; BookmarkManager bMan; - ConnectionManager con; GridManager gridMan; std::deque chatMessages; @@ -75,9 +68,6 @@ class World { void draw(SkCanvas* canvas); void early_destroy(); - bool network_being_used(); - - ConnectionType conType; bool clientStillConnecting = false; void save_to_file(const std::filesystem::path& filePathToSaveAt); @@ -101,19 +91,23 @@ class World { NetworkingObjects::DelayUpdateSerializedClassManager delayedUpdateObjectManager; std::shared_ptr netServer; + std::shared_ptr netClient; private: + void load_empty_canvas(); + Vector3f get_random_cursor_color(); void init_client_data_list(); void init_client_data_list_callbacks(); void init_net_obj_type_list(); - void init_client_callbacks(); - void init_server_callbacks(); + void init_client(const std::string& serverFullID); void set_name(const std::string& n); void draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData); void ensure_display_name_unique(std::string& displayName); + void connection_update(); + TimePoint timeToSendCameraData; WorldVec mousePreviousWorldVec = {0, 0}; WorldVec mouseWorldMove = {0, 0}; diff --git a/src/main.cpp b/src/main.cpp index 7bf9fa9..0cd53f4 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -526,13 +526,13 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { if(listOfFilesToOpenFromCommand.empty()) { mS.m->new_tab({ - .conType = World::CONNECTIONTYPE_LOCAL + .isClient = false }, true); } else { for(std::filesystem::path& f : listOfFilesToOpenFromCommand) { mS.m->new_tab({ - .conType = World::CONNECTIONTYPE_LOCAL, + .isClient = false, .filePathSource = f }, true); }