diff --git a/CMakeLists.txt b/CMakeLists.txt index 0adeacb..0f6ca97 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set(sources "src/main.cpp" "src/World.cpp" "src/FileHelpers.cpp" "src/VersionConstants.cpp" + "src/ScaleUpCanvas.cpp" "src/Bookmarks/BookmarkListItem.cpp" "src/Bookmarks/BookmarkManager.cpp" "src/ResourceDisplay/ResourceDisplay.cpp" diff --git a/include/Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp b/include/Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp index 22f9e60..cbd6349 100644 --- a/include/Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp +++ b/include/Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp @@ -11,13 +11,13 @@ namespace NetworkingObjects { std::function writeConstructor = [](const T& o, cereal::PortableBinaryOutputArchive& a) { a(o); }; - std::function readConstructor = [](T& o, cereal::PortableBinaryInputArchive& a) { + std::function& c)> readConstructor = [](T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { a(o); }; std::function writeUpdate = [](const T& o, cereal::PortableBinaryOutputArchive& a) { a(o); }; - std::function readUpdate = [](T& o, cereal::PortableBinaryInputArchive& a) { + std::function& c)> readUpdate = [](T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { a(o); }; std::function(const T& o)> allocateCopy = [](const T& o) { @@ -35,11 +35,11 @@ namespace NetworkingObjects { template void register_class(NetObjManager& objMan, const CustomConstructors& t = CustomConstructors()) { objMan.register_class({ .writeConstructorFuncClient = [writeConstructor = t.writeConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a) {writeConstructor(*o, a);}, - .readConstructorFuncClient = [readConstructor = t.readConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) {readConstructor(*o, a);}, - .readUpdateFuncClient = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){client_read_update_func(o, a, readUpdate);}, + .readConstructorFuncClient = [readConstructor = t.readConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) {readConstructor(*o, a, nullptr);}, + .readUpdateFuncClient = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c){client_read_update_func(o, a, readUpdate);}, .writeConstructorFuncServer = [writeConstructor = t.writeConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a) {writeConstructor(*o, a);}, - .readConstructorFuncServer = [readConstructor = t.readConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) {readConstructor(*o, a);}, - .readUpdateFuncServer = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&){server_read_update_func(o, a, readUpdate);} + .readConstructorFuncServer = [readConstructor = t.readConstructor](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) {readConstructor(*o, a, c);}, + .readUpdateFuncServer = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c){server_read_update_func(o, a, readUpdate, c);} }); typeIndexFuncs[std::type_index(typeid(T))] = { .writeUpdateFunc = [writeFunc = t.writeUpdate](const void* o, cereal::PortableBinaryOutputArchive& a) { @@ -103,15 +103,15 @@ namespace NetworkingObjects { } } - template void client_read_update_func(const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::function& readUpdate) { + template void client_read_update_func(const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::function&)>& readUpdate) { auto it = updatingObjs.find(o.get_net_id()); if(it == updatingObjs.end()) { - readUpdate(*o, a); + readUpdate(*o, a, nullptr); typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast(o.get())); } else { auto& [netID, updatingObjData] = *it; - readUpdate(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData), a); + readUpdate(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData), a, nullptr); *updatingObjData.doLastAssignment = true; } } @@ -155,12 +155,12 @@ namespace NetworkingObjects { } } - template void server_read_update_func(const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::function& readUpdate) { + template void server_read_update_func(const NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::function&)>& readUpdate, const std::shared_ptr& c) { auto it = updatingObjs.find(o.get_net_id()); bool finalUpdate; if(it == updatingObjs.end()) { a(finalUpdate); - readUpdate(*o, a); + readUpdate(*o, a, c); typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast(o.get())); o.send_server_update_to_all_clients(finalUpdate ? RELIABLE_COMMAND_CHANNEL : UNRELIABLE_COMMAND_CHANNEL, [&typeIndexFuncs = typeIndexFuncs](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a) { typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast(o.get()), a); @@ -169,7 +169,7 @@ namespace NetworkingObjects { else { auto& [netID, updatingObjData] = *it; a(finalUpdate); - readUpdate(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData), a); + readUpdate(*std::static_pointer_cast(updatingObjData.objToUpdateCurrentData), a, c); *updatingObjData.doLastAssignment = true; } } diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index 94a19f2..c0dbda0 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -181,6 +181,8 @@ namespace NetworkingObjects { return data.end(); } virtual NetObjOrderedListIterator at(uint32_t index) override { + if(index >= data.size()) + return data.end(); return std::next(data.begin(), index); } virtual NetObjOrderedListIterator get(const NetObjID& id) override { @@ -196,6 +198,8 @@ namespace NetworkingObjects { return data.end(); } virtual NetObjOrderedListConstIterator at(uint32_t index) const override { + if(index >= data.size()) + return data.end(); return std::next(data.begin(), index); } virtual NetObjOrderedListConstIterator get(const NetObjID& id) const override { @@ -366,6 +370,8 @@ namespace NetworkingObjects { return clientData.end(); } virtual NetObjOrderedListIterator at(uint32_t index) override { + if(index >= clientData.size()) + return clientData.end(); return std::next(clientData.begin(), index); } virtual NetObjOrderedListIterator get(const NetObjID& id) override { @@ -381,6 +387,8 @@ namespace NetworkingObjects { return clientData.end(); } virtual NetObjOrderedListConstIterator at(uint32_t index) const override { + if(index >= clientData.size()) + return clientData.end(); return std::next(clientData.begin(), index); } virtual NetObjOrderedListConstIterator get(const NetObjID& id) const override { diff --git a/src/Bookmarks/BookmarkListItem.cpp b/src/Bookmarks/BookmarkListItem.cpp index cb6a044..c5fead5 100644 --- a/src/Bookmarks/BookmarkListItem.cpp +++ b/src/Bookmarks/BookmarkListItem.cpp @@ -1,6 +1,7 @@ #include "BookmarkListItem.hpp" #include #include "../World.hpp" +#include "../ScaleUpCanvas.hpp" using namespace NetworkingObjects; @@ -27,6 +28,15 @@ void BookmarkListItem::reassign_netobj_ids_call() { nameData.reassign_ids(); } +void BookmarkListItem::scale_up(const WorldScalar& scaleUpAmount) { + if(folderData) { + for(auto& i : *folderData->folderList) + i.obj->scale_up(scaleUpAmount); + } + else + bookmarkData->coords.inverseScale *= scaleUpAmount; +} + bool BookmarkListItem::is_folder() const { return folderData != nullptr; } @@ -59,12 +69,27 @@ void BookmarkListItem::set_folder_open(bool newIsFolderOpen) { } void BookmarkListItem::register_class(World& w) { + auto readConstructorData = [&w](const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + bool isFolder; + a(isFolder); + if(isFolder) { + o->folderData = std::make_unique(); + o->folderData->folderList = o.get_obj_man()->read_create_message>(a, c); + } + else { + o->bookmarkData = std::make_unique(); + a(*o->bookmarkData); + } + o->nameData = o.get_obj_man()->read_create_message(a, c); + + canvas_scale_up_check(*o, w, c); + }; w.netObjMan.register_class({ .writeConstructorFuncClient = write_constructor_data, - .readConstructorFuncClient = read_constructor_data, + .readConstructorFuncClient = readConstructorData, .readUpdateFuncClient = nullptr, .writeConstructorFuncServer = write_constructor_data, - .readConstructorFuncServer = read_constructor_data, + .readConstructorFuncServer = readConstructorData, .readUpdateFuncServer = nullptr }); NetworkingObjects::register_ordered_list_class(w.netObjMan); @@ -79,17 +104,3 @@ void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtrbookmarkData); o->nameData.write_create_message(a); } - -void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { - bool isFolder; - a(isFolder); - if(isFolder) { - o->folderData = std::make_unique(); - o->folderData->folderList = o.get_obj_man()->read_create_message>(a, c); - } - else { - o->bookmarkData = std::make_unique(); - a(*o->bookmarkData); - } - o->nameData = o.get_obj_man()->read_create_message(a, c); -} diff --git a/src/Bookmarks/BookmarkListItem.hpp b/src/Bookmarks/BookmarkListItem.hpp index 6a9fc1d..c87bccf 100644 --- a/src/Bookmarks/BookmarkListItem.hpp +++ b/src/Bookmarks/BookmarkListItem.hpp @@ -26,6 +26,7 @@ class BookmarkListItem { const std::string& get_name() const; static void register_class(World& w); void reassign_netobj_ids_call(); + void scale_up(const WorldScalar& scaleUpAmount); void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName); private: @@ -40,7 +41,6 @@ class BookmarkListItem { } }; static void write_constructor_data(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a); - static void read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c); std::unique_ptr folderData; std::unique_ptr bookmarkData; NetworkingObjects::NetObjOwnerPtr nameData; diff --git a/src/Bookmarks/BookmarkManager.cpp b/src/Bookmarks/BookmarkManager.cpp index c90cb7e..80585a0 100644 --- a/src/Bookmarks/BookmarkManager.cpp +++ b/src/Bookmarks/BookmarkManager.cpp @@ -198,4 +198,5 @@ NetworkingObjects::NetObjOrderedListIterator BookmarkManager:: } void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) { + bookmarkListRoot->scale_up(scaleUpAmount); } diff --git a/src/CanvasComponents/CanvasComponentAllocator.cpp b/src/CanvasComponents/CanvasComponentAllocator.cpp index df63cc6..9f0b941 100644 --- a/src/CanvasComponents/CanvasComponentAllocator.cpp +++ b/src/CanvasComponents/CanvasComponentAllocator.cpp @@ -17,7 +17,7 @@ void CanvasComponentAllocator::register_class(World& world) { a(o.comp->get_type()); a(*o.comp); }, - .readConstructor = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a) { + .readConstructor = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { CanvasComponentType typeToAllocate; a(typeToAllocate); o.comp = std::unique_ptr(CanvasComponent::allocate_comp(typeToAllocate)); @@ -26,7 +26,7 @@ void CanvasComponentAllocator::register_class(World& world) { .writeUpdate = [](const CanvasComponentAllocator& o, cereal::PortableBinaryOutputArchive& a) { a(*o.comp); }, - .readUpdate = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a) { + .readUpdate = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { a(*o.comp); }, .allocateCopy = [](const CanvasComponentAllocator& o) { diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index d1c9385..d5aba33 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -5,6 +5,7 @@ #include "../World.hpp" #include "CanvasComponent.hpp" #include +#include "../ScaleUpCanvas.hpp" using namespace NetworkingObjects; @@ -22,13 +23,19 @@ CanvasComponentContainer::CanvasComponentContainer(NetworkingObjects::NetObjMana coords = copyData.coords; } -void CanvasComponentContainer::register_class(NetObjManager& objMan) { - objMan.register_class({ +void CanvasComponentContainer::register_class(World& w) { + auto readConstructorFunc = [&w](const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + a(o->coords); + o->compAllocator = o.get_obj_man()->read_create_message(a, c); + o->compAllocator->comp->compContainer = o.get(); + canvas_scale_up_check(*o, w, c); + }; + w.netObjMan.register_class({ .writeConstructorFuncClient = write_constructor_func, - .readConstructorFuncClient = read_constructor_func, + .readConstructorFuncClient = readConstructorFunc, .readUpdateFuncClient = nullptr, .writeConstructorFuncServer = write_constructor_func, - .readConstructorFuncServer = read_constructor_func, + .readConstructorFuncServer = readConstructorFunc, .readUpdateFuncServer = nullptr, }); } @@ -49,12 +56,6 @@ void CanvasComponentContainer::write_constructor_func(const NetworkingObjects::N o->compAllocator.write_create_message(a); } -void CanvasComponentContainer::read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { - a(o->coords); - o->compAllocator = o.get_obj_man()->read_create_message(a, c); - o->compAllocator->comp->compContainer = o.get(); -} - void CanvasComponentContainer::save_file(cereal::PortableBinaryOutputArchive& a) const { a(coords); get_comp().save_file(a); @@ -94,7 +95,7 @@ void CanvasComponentContainer::commit_update_dont_invalidate_cache(DrawingProgra calculate_world_bounds(); } -void CanvasComponentContainer::commit_transform_dont_invalidate_cache(DrawingProgram& drawP) { +void CanvasComponentContainer::commit_transform_dont_invalidate_cache() { calculate_world_bounds(); } @@ -142,6 +143,11 @@ CanvasComponentContainer::TransformDrawData CanvasComponentContainer::calculate_ return toRet; } +void CanvasComponentContainer::scale_up(const WorldScalar& scaleUpAmount) { + coords.inverseScale *= scaleUpAmount; + calculate_world_bounds(); +} + unsigned CanvasComponentContainer::get_mipmap_level(const DrawData& drawData) const { if(drawData.mipMapLevelTwo > coords.inverseScale) return 2; diff --git a/src/CanvasComponents/CanvasComponentContainer.hpp b/src/CanvasComponents/CanvasComponentContainer.hpp index 0590d27..3fd7551 100644 --- a/src/CanvasComponents/CanvasComponentContainer.hpp +++ b/src/CanvasComponents/CanvasComponentContainer.hpp @@ -34,7 +34,7 @@ class CanvasComponentContainer { CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, CanvasComponentType type); CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, const CopyData& copyData); - static void register_class(NetworkingObjects::NetObjManager& t); + 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); @@ -42,7 +42,7 @@ class CanvasComponentContainer { SCollision::AABB get_world_bounds() const; void draw(SkCanvas* canvas, const DrawData& drawData) const; void commit_update(DrawingProgram& drawP); - void commit_transform_dont_invalidate_cache(DrawingProgram& drawP); // Must be thread safe + void commit_transform_dont_invalidate_cache(); // Must be thread safe void commit_transform(DrawingProgram& drawP); void commit_update_dont_invalidate_cache(DrawingProgram& drawP); // Must be thread safe bool should_draw(const DrawData& drawData) const; @@ -50,6 +50,7 @@ class CanvasComponentContainer { bool collides_with_cam_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection& checkAgainstCam) const; bool collides_with(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection& checkAgainstWorld, const SCollision::ColliderCollection& checkAgainstCam) const; void send_comp_update(DrawingProgram& drawP, bool finalUpdate); + void scale_up(const WorldScalar& scaleUpAmount); std::weak_ptr cacheParentBvhNode; DrawingProgramLayerListItem* parentLayer = nullptr; @@ -60,7 +61,6 @@ class CanvasComponentContainer { friend class ImageCanvasComponent; static void write_constructor_func(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a); - static void read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c); struct TransformDrawData { Vector2f translation; diff --git a/src/ClientData.cpp b/src/ClientData.cpp index 18b118c..cfba1da 100644 --- a/src/ClientData.cpp +++ b/src/ClientData.cpp @@ -1,7 +1,9 @@ #include "ClientData.hpp" +#include "CommandList.hpp" #include "World.hpp" #include #include "MainProgram.hpp" +#include "ScaleUpCanvas.hpp" using namespace NetworkingObjects; @@ -9,7 +11,8 @@ enum class ClientDataCommand : uint8_t { SET_CURSOR_POS = 0, SET_WINDOW_SIZE, SET_CAM_COORDS, - SEND_CHAT_MESSAGE + SEND_CHAT_MESSAGE, + SET_GRID_SIZE }; ClientData::ClientData() { @@ -26,6 +29,7 @@ void ClientData::set_from_init_struct(const InitStruct& initStruct) { cursorPos = initStruct.cursorPos; cursorColor = initStruct.cursorColor; displayName = initStruct.displayName; + gridSize = initStruct.gridSize; } void ClientData::register_class(World& world) { @@ -49,6 +53,14 @@ void ClientData::register_class(World& world) { std::string chatMessage; a(chatMessage); world.add_chat_message(o->displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL); + break; + } + case ClientDataCommand::SET_GRID_SIZE: { + uint32_t oldGridSize = o->gridSize; + a(o->gridSize); + if(oldGridSize < o->gridSize) + world.scale_up(WorldScalar(o->gridSize - oldGridSize) * CANVAS_SCALE_UP_STEP); + break; } } }, @@ -85,6 +97,16 @@ void ClientData::register_class(World& world) { }); break; } + case ClientDataCommand::SET_GRID_SIZE: { + uint32_t oldGridSize = o->gridSize; + a(o->gridSize); + if(oldGridSize < o->gridSize) + world.scale_up(WorldScalar(o->gridSize - oldGridSize) * CANVAS_SCALE_UP_STEP); + o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive & a) { + a(ClientDataCommand::SET_GRID_SIZE, o->gridSize); + }); + break; + } } }, }); @@ -123,6 +145,14 @@ void ClientData::send_chat_message(const NetworkingObjects::NetObjTemporaryPtr& o, World& world) { + o->gridSize++; + world.scale_up(CANVAS_SCALE_UP_STEP); + o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive & a) { + a(ClientDataCommand::SET_GRID_SIZE, o->gridSize); + }); +} + void ClientData::set_display_name(const std::string& newDisplayName) { displayName = newDisplayName; } @@ -143,6 +173,10 @@ const Vector2f& ClientData::get_cursor_pos() const { return cursorPos; } +uint32_t ClientData::get_grid_size() const { + return gridSize; +} + const std::string& ClientData::get_display_name() const { return displayName; } diff --git a/src/ClientData.hpp b/src/ClientData.hpp index 18b0102..ea22933 100644 --- a/src/ClientData.hpp +++ b/src/ClientData.hpp @@ -13,6 +13,7 @@ class ClientData { Vector3f cursorColor = {1.0f, 1.0f, 1.0f}; std::string displayName; + uint32_t gridSize = 0; }; ClientData(); @@ -22,19 +23,21 @@ class ClientData { static void set_window_size(const NetworkingObjects::NetObjTemporaryPtr& o, Vector2f newWindowSize); static void set_camera_coords(const NetworkingObjects::NetObjTemporaryPtr& o, const CoordSpaceHelper& newCoords); static void send_chat_message(const NetworkingObjects::NetObjTemporaryPtr& o, World& world, const std::string& chatMessage); + static void scale_up_step(const NetworkingObjects::NetObjTemporaryPtr& o, World& world); void set_display_name(const std::string& newDisplayName); void set_cursor_color(const Vector3f& newCursorColor); const CoordSpaceHelper& get_cam_coords() const; const Vector2f& get_window_size() const; const Vector2f& get_cursor_pos() const; + uint32_t get_grid_size() const; const std::string& get_display_name() const; const Vector3f& get_cursor_color() const; void draw_cursor(SkCanvas* canvas, const DrawData& drawData) const; template void serialize(Archive& a) { - a(camCoords, windowSize, cursorPos, cursorColor, displayName); + a(camCoords, windowSize, cursorPos, cursorColor, displayName, gridSize); } private: void set_from_init_struct(const InitStruct& initStruct); @@ -44,5 +47,6 @@ class ClientData { Vector3f cursorColor; std::string displayName; + uint32_t gridSize; }; diff --git a/src/CommandList.hpp b/src/CommandList.hpp index d49b4fa..463e6af 100644 --- a/src/CommandList.hpp +++ b/src/CommandList.hpp @@ -23,6 +23,3 @@ enum ClientCommands : MessageCommandType { CLIENT_NEW_RESOURCE_DATA, CLIENT_TRANSFORM_MANY_COMPONENTS }; - -// Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage -#define CANVAS_SCALE_UP_STEP WorldScalar("100000000000000000000000000000000000000000000000000") diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 51bd495..57c0f7f 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -32,6 +32,7 @@ #include "Layers/DrawingProgramLayer.hpp" #include "Layers/DrawingProgramLayerListItem.hpp" #include +#include "../ScaleUpCanvas.hpp" #include "Tools/EraserTool.hpp" @@ -49,11 +50,10 @@ void DrawingProgram::init() { } void DrawingProgram::scale_up(const WorldScalar& scaleUpAmount) { - //for(auto& c : components->get_data()) - // c->obj->scale_up(scaleUpAmount); - //selection.deselect_all(); - //force_rebuild_cache(); - //switch_to_tool(drawTool->get_type() == DrawingProgramToolType::GRIDMODIFY ? DrawingProgramToolType::EDIT : drawTool->get_type(), true); + selection.deselect_all(); + layerMan.scale_up(scaleUpAmount); + rebuild_cache(); + switch_to_tool(drawTool->get_type() == DrawingProgramToolType::GRIDMODIFY ? DrawingProgramToolType::EDIT : drawTool->get_type(), true); } void DrawingProgram::write_components_server(cereal::PortableBinaryOutputArchive& a) { @@ -69,6 +69,14 @@ void DrawingProgram::init_server_callbacks() { world.netServer->add_recv_callback(SERVER_TRANSFORM_MANY_COMPONENTS, [&](std::shared_ptr client, cereal::PortableBinaryInputArchive& message) { std::vector> transforms; message(transforms); + + auto clientData = world.netObjMan.get_obj_temporary_ref_from_id(NetworkingObjects::NetObjID(client->customID)); + if(clientData->get_grid_size() < world.ownClientData->get_grid_size()) { + WorldScalar scaleUpAmount = get_canvas_scale_up_amount(world.ownClientData->get_grid_size(), clientData->get_grid_size()); + for(auto& [netID, coord] : transforms) + coord.inverseScale *= scaleUpAmount; + } + process_transform_message(transforms); world.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms); }); diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp index 7cd0df5..fda64c9 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp @@ -51,3 +51,8 @@ void DrawingProgramLayer::get_flattened_component_list(std::vectorscale_up(scaleUpAmount); +} diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp index 8e01134..fa7b98b 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp @@ -13,6 +13,7 @@ class DrawingProgramLayer { 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; private: diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp index 777a218..0016901 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp @@ -49,3 +49,8 @@ NetworkingObjects::NetObjWeakPtr DrawingProgramLaye } return {}; } + +void DrawingProgramLayerFolder::scale_up(const WorldScalar& scaleUpAmount) { + for(auto& p : *folderList) + p.obj->scale_up(scaleUpAmount); +} diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp index 2ff3cc4..aa4d1c4 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp @@ -15,6 +15,7 @@ class DrawingProgramLayerFolder { void get_flattened_component_list(std::vector& objList) const; void set_to_erase(); NetworkingObjects::NetObjWeakPtr get_initial_editing_layer() const; + void scale_up(const WorldScalar& scaleUpAmount); NetworkingObjects::NetObjOwnerPtr> folderList; bool isFolderOpen = false; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp index 9429eff..881423a 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp @@ -80,6 +80,13 @@ uint32_t DrawingProgramLayerListItem::get_component_count() const { return layerData->components->size(); } +void DrawingProgramLayerListItem::scale_up(const WorldScalar& scaleUpAmount) { + if(folderData) + folderData->scale_up(scaleUpAmount); + else + layerData->scale_up(scaleUpAmount); +} + bool DrawingProgramLayerListItem::is_folder() const { return folderData != nullptr; } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp index d34a6c7..db99403 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp @@ -29,6 +29,7 @@ class DrawingProgramLayerListItem { const std::string& get_name() const; void get_flattened_component_list(std::vector& objList) const; void get_flattened_layer_list(std::vector& objList); + void scale_up(const WorldScalar& scaleUpAmount); void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const; float get_alpha() const; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index 189effa..c98cc4e 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -15,6 +15,10 @@ void DrawingProgramLayerManager::init() { } } +void DrawingProgramLayerManager::scale_up(const WorldScalar& scaleUpAmount) { + layerTreeRoot->scale_up(scaleUpAmount); +} + void DrawingProgramLayerManager::write_components_server(cereal::PortableBinaryOutputArchive& a) { layerTreeRoot.write_create_message(a); } @@ -92,3 +96,4 @@ CanvasComponentContainer::ObjInfo* DrawingProgramLayerManager::add_component_to_ return nullptr; return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj)); } + diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp index 9553636..dec6427 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp @@ -25,6 +25,7 @@ class DrawingProgramLayerManager { void write_components_server(cereal::PortableBinaryOutputArchive& a); void read_components_client(cereal::PortableBinaryInputArchive& a); bool is_a_layer_being_edited(); + void scale_up(const WorldScalar& scaleUpAmount); template void erase_component_container(const List& compsToErase) { std::unordered_map> idsToEraseInSpecificLayers; for(auto& c : compsToErase) diff --git a/src/ScaleUpCanvas.cpp b/src/ScaleUpCanvas.cpp new file mode 100644 index 0000000..2a7a2a5 --- /dev/null +++ b/src/ScaleUpCanvas.cpp @@ -0,0 +1,5 @@ +#include "ScaleUpCanvas.hpp" + +WorldScalar get_canvas_scale_up_amount(uint32_t newGridSize, uint32_t oldGridSize) { + return WorldScalar(newGridSize - oldGridSize) * CANVAS_SCALE_UP_STEP; +} diff --git a/src/ScaleUpCanvas.hpp b/src/ScaleUpCanvas.hpp new file mode 100644 index 0000000..c1c7ea0 --- /dev/null +++ b/src/ScaleUpCanvas.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include "World.hpp" + +// Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage +#define CANVAS_SCALE_UP_STEP WorldScalar("100000000000000000000000000000000000000000000000000") + +WorldScalar get_canvas_scale_up_amount(uint32_t newGridSize, uint32_t oldGridSize); + +template void canvas_scale_up_check(T& obj, World& world, const std::shared_ptr& c) { + if(c) { + auto clientData = world.netObjMan.get_obj_temporary_ref_from_id(NetworkingObjects::NetObjID(c->customID)); + if(clientData->get_grid_size() < world.ownClientData->get_grid_size()) + obj.scale_up(get_canvas_scale_up_amount(world.ownClientData->get_grid_size(), clientData->get_grid_size())); + } +} diff --git a/src/World.cpp b/src/World.cpp index d53f018..624e679 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -112,10 +112,10 @@ void World::init_client_data_list_callbacks() { void World::init_net_obj_type_list() { BookmarkListItem::register_class(*this); - delayedUpdateObjectManager.register_class(netObjMan); + WorldGrid::register_class(*this); NetworkingObjects::register_ordered_list_class(netObjMan); CanvasComponentAllocator::register_class(*this); - CanvasComponentContainer::register_class(netObjMan); + CanvasComponentContainer::register_class(*this); NetworkingObjects::register_ordered_list_class(netObjMan); DrawingProgramLayerListItem::register_class(*this); NetworkingObjects::register_ordered_list_class(netObjMan); @@ -135,6 +135,7 @@ void World::init_server_callbacks() { 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; @@ -488,9 +489,8 @@ void World::draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData } void World::scale_up_step() { - //canvasScale++; - //con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_CANVAS_SCALE, canvasScale); - //scale_up(WorldScalar(CANVAS_SCALE_UP_STEP)); + if(ownClientData) + ownClientData->scale_up_step(ownClientData, *this); } void World::scale_up(const WorldScalar& scaleUpAmount) { diff --git a/src/WorldGrid.cpp b/src/WorldGrid.cpp index 9eb17ca..ef00021 100644 --- a/src/WorldGrid.cpp +++ b/src/WorldGrid.cpp @@ -2,6 +2,7 @@ #include "GridManager.hpp" #include "Helpers/MathExtras.hpp" #include "MainProgram.hpp" +#include "ScaleUpCanvas.hpp" #include #include @@ -10,7 +11,6 @@ sk_sp WorldGrid::squarePointEffect; sk_sp WorldGrid::squareLinesEffect; sk_sp WorldGrid::horizontalLinesEffect; Vector2f WorldGrid::oldWindowSize = Vector2f{0.0f, 0.0f}; -unsigned WorldGrid::GRID_UNIT_PIXEL_SIZE = 25; // NOTE: Skia shaders return premultiplied alpha colors @@ -175,6 +175,17 @@ sk_sp WorldGrid::get_shader(GridType gType, const ShaderData& shaderDa return s; } +void WorldGrid::register_class(World& w) { + auto readWorldGrid = [&](WorldGrid& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) { + a(o); + canvas_scale_up_check(o, w, c); + }; + w.delayedUpdateObjectManager.register_class(w.netObjMan, NetworkingObjects::DelayUpdateSerializedClassManager::CustomConstructors{ + .readConstructor = readWorldGrid, + .readUpdate = readWorldGrid + }); +} + Vector2f WorldGrid::get_closest_grid_point(const WorldVec& gridOffset, const WorldScalar& gridSize, const DrawData& drawData) { WorldVec fracCamPosOnGrid; fracCamPosOnGrid.x() = (drawData.cam.c.pos.x() - gridOffset.x()) % gridSize; diff --git a/src/WorldGrid.hpp b/src/WorldGrid.hpp index d111ed2..c604cc8 100644 --- a/src/WorldGrid.hpp +++ b/src/WorldGrid.hpp @@ -12,6 +12,7 @@ class WorldGrid { a(name, gridType, size, visible, offset, bounds, color, removeDivisionsOutwards, subdivisions, showCoordinates, displayInFront); } + static void register_class(World& w); void draw(GridManager& gMan, SkCanvas* canvas, const DrawData& drawData); void draw_coordinates(SkCanvas* canvas, const DrawData& drawData, Vector2f& axisOffset); @@ -37,7 +38,7 @@ class WorldGrid { void set_subdivisions(uint32_t v); void scale_up(const WorldScalar& scaleUpAmount); - static unsigned GRID_UNIT_PIXEL_SIZE; + static constexpr unsigned GRID_UNIT_PIXEL_SIZE = 25; WorldScalar coordinatesDivWorldSize; WorldScalar coordinatesGridCoordDivSize;