diff --git a/include/Helpers/Networking/NetClient.cpp b/include/Helpers/Networking/NetClient.cpp index 9d88553..5ad9365 100644 --- a/include/Helpers/Networking/NetClient.cpp +++ b/include/Helpers/Networking/NetClient.cpp @@ -93,6 +93,13 @@ void NetClient::parse_received_messages() { } } +std::pair NetClient::get_progress_into_fragmented_message(const std::string& channel) { + auto& m = pfm[channel]; + if(m.partialFragmentMessage.empty()) + return {0, 0}; + return {m.partialFragmentMessageLoc, m.partialFragmentMessage.size()}; +} + void NetClient::send_queued_messages() { for(auto& [channelName, messageQueue] : messageQueues) { bool addMessageOrder = NetLibrary::is_ordered_channel(channelName); diff --git a/include/Helpers/Networking/NetClient.hpp b/include/Helpers/Networking/NetClient.hpp index 974f6a6..776a827 100644 --- a/include/Helpers/Networking/NetClient.hpp +++ b/include/Helpers/Networking/NetClient.hpp @@ -37,6 +37,7 @@ class NetClient : public std::enable_shared_from_this { void update(); void add_recv_callback(MessageCommandType commandID, const NetClientRecvCallback& callback); bool is_disconnected(); + std::pair get_progress_into_fragmented_message(const std::string& channel); private: std::string localID; diff --git a/src/ConnectionManager.cpp b/src/ConnectionManager.cpp index 4c0bde3..7095d45 100644 --- a/src/ConnectionManager.cpp +++ b/src/ConnectionManager.cpp @@ -1,4 +1,5 @@ #include "ConnectionManager.hpp" +#include "Helpers/Networking/NetLibrary.hpp" #include "Server/CommandList.hpp" #include @@ -38,3 +39,10 @@ bool ConnectionManager::is_client_disconnected() { bool ConnectionManager::is_host_disconnected() { return localServer && localServer->netServer->is_disconnected(); } + +std::pair ConnectionManager::client_get_resource_retrieval_progress() { + if(client) + return client->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL); + else + return {0, 0}; +} diff --git a/src/ConnectionManager.hpp b/src/ConnectionManager.hpp index ea7753e..e94a1c7 100644 --- a/src/ConnectionManager.hpp +++ b/src/ConnectionManager.hpp @@ -14,6 +14,7 @@ class ConnectionManager { } bool is_client_disconnected(); bool is_host_disconnected(); + std::pair client_get_resource_retrieval_progress(); private: std::shared_ptr client; std::unique_ptr localServer; diff --git a/src/DrawComponents/DrawImage.cpp b/src/DrawComponents/DrawImage.cpp index 4068240..39aebc9 100644 --- a/src/DrawComponents/DrawImage.cpp +++ b/src/DrawComponents/DrawImage.cpp @@ -5,6 +5,8 @@ #include "../SharedTypes.hpp" #include "../World.hpp" +#include "../MainProgram.hpp" + #ifndef IS_SERVER #include #include "../DrawCollision.hpp" @@ -54,6 +56,23 @@ void DrawImage::update_from_delayed_ptr(const std::shared_ptr& de d = newPtr->d; } +void DrawImage::draw_download_progress_bar(SkCanvas* canvas, const DrawData& drawData, float progress) { + if(progress == 0.0f) + return; + canvas->save(); + canvas_do_calculated_transform(canvas); + SkPaint p; + p.setStroke(true); + p.setStrokeWidth(10.0f); + p.setStrokeCap(SkPaint::kRound_Cap); + p.setColor4f(drawData.main->toolbar.io->theme->fillColor5); + Vector2f center = (d.p1 + d.p2) * 0.5f; + + const float DOWNLOAD_ARC_RADIUS = 50.0f; + canvas->drawArc(SkRect::MakeLTRB(center.x() - DOWNLOAD_ARC_RADIUS, center.y() - DOWNLOAD_ARC_RADIUS, center.x() + DOWNLOAD_ARC_RADIUS, center.y() + DOWNLOAD_ARC_RADIUS), 0.0f, progress * 360.0f, false, p); + canvas->restore(); +} + void DrawImage::draw(SkCanvas* canvas, const DrawData& drawData) { if(drawSetupData.shouldDraw) { canvas->save(); diff --git a/src/DrawComponents/DrawImage.hpp b/src/DrawComponents/DrawImage.hpp index 92f5579..27d3318 100644 --- a/src/DrawComponents/DrawImage.hpp +++ b/src/DrawComponents/DrawImage.hpp @@ -15,6 +15,8 @@ class DrawImage : public DrawComponent { virtual void get_used_resources(std::unordered_set& v) const override; virtual void remap_resource_ids(std::unordered_map& newIDs) override; + void draw_download_progress_bar(SkCanvas* canvas, const DrawData& drawData, float progress); + // User input data struct Data { Vector2f p1; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index ca043a7..5c7dda5 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -707,26 +707,6 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { } } else { - if(!drawData.main->takingScreenshot) { - for(auto& droppedDownFile : droppedDownloadingFiles) { - if(droppedDownFile.comp->obj->collabListInfo.lock()) { - canvas->save(); - auto img = std::static_pointer_cast(droppedDownFile.comp->obj); - img->canvas_do_calculated_transform(canvas); - SkPaint p; - p.setStroke(true); - p.setStrokeWidth(10.0f); - p.setStrokeCap(SkPaint::kRound_Cap); - p.setColor4f(drawData.main->toolbar.io->theme->fillColor5); - Vector2f center = (img->d.p1 + img->d.p2) * 0.5f; - - const float DOWNLOAD_ARC_RADIUS = 50.0f; - canvas->drawArc(SkRect::MakeLTRB(center.x() - DOWNLOAD_ARC_RADIUS, center.y() - DOWNLOAD_ARC_RADIUS, center.x() + DOWNLOAD_ARC_RADIUS, center.y() + DOWNLOAD_ARC_RADIUS), 0.0f, droppedDownFile.downData->progress * 360.0f, false, p); - canvas->restore(); - } - } - } - canvas->saveLayer(nullptr, nullptr); canvas->clear(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f}); compCache.refresh_all_draw_cache(drawData); @@ -735,6 +715,22 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { selection.draw_components(canvas, drawData); canvas->restore(); canvas->restore(); + + if(!drawData.main->takingScreenshot) { + for(auto& droppedDownFile : droppedDownloadingFiles) { + if(droppedDownFile.comp->obj->collabListInfo.lock()) + std::static_pointer_cast(droppedDownFile.comp->obj)->draw_download_progress_bar(canvas, drawData, droppedDownFile.downData->progress); + } + + for(auto& c : updateableComponents) { + if(c->get_type() == DRAWCOMPONENT_IMAGE) { + auto img = std::static_pointer_cast(c); + if(img->d.imageID == drawData.main->world->rMan.get_resource_being_retrieved() && img->d.imageID != ServerClientID{0, 0}) + img->draw_download_progress_bar(canvas, drawData, drawData.main->world->rMan.get_resource_retrieval_progress()); + } + } + } + selection.draw_gui(canvas, drawData); } diff --git a/src/ResourceManager.cpp b/src/ResourceManager.cpp index c0ce588..84d8ee5 100644 --- a/src/ResourceManager.cpp +++ b/src/ResourceManager.cpp @@ -18,12 +18,26 @@ ResourceManager::ResourceManager(World& initWorld): {} void ResourceManager::init_client_callbacks() { - world.con.client_add_recv_callback(CLIENT_NEW_RESOURCE, [&](cereal::PortableBinaryInputArchive& message) { - ServerClientID resourceID; - message(resourceID); - message(resources[resourceID]); - std::cout << "Received new resource: " << resourceID.first << " " << resourceID.second << " " << resources[resourceID].data->size() << std::endl; + world.con.client_add_recv_callback(CLIENT_NEW_RESOURCE_ID, [&](cereal::PortableBinaryInputArchive& message) { + message(resourceBeingRetrieved); }); + world.con.client_add_recv_callback(CLIENT_NEW_RESOURCE_DATA, [&](cereal::PortableBinaryInputArchive& message) { + message(resources[resourceBeingRetrieved]); + Logger::get().log("INFO", "Received new resource with id: " + std::to_string(resourceBeingRetrieved.first) + " " + std::to_string(resourceBeingRetrieved.second) + " of size " + std::to_string(resources[resourceBeingRetrieved].data->size())); + resourceBeingRetrieved = {0, 0}; + }); +} + +ServerClientID ResourceManager::get_resource_being_retrieved() { + return resourceBeingRetrieved; +} + +float ResourceManager::get_resource_retrieval_progress() { + std::pair progressBytes = world.con.client_get_resource_retrieval_progress(); + if(progressBytes.second == 0) + return 0.0f; + else + return static_cast(progressBytes.first) / static_cast(progressBytes.second); } void ResourceManager::update() { diff --git a/src/ResourceManager.hpp b/src/ResourceManager.hpp index ab8d0b3..6f00531 100644 --- a/src/ResourceManager.hpp +++ b/src/ResourceManager.hpp @@ -44,9 +44,13 @@ class ResourceManager { std::optional get_resource(const ServerClientID& id) const; ClientPortionID get_max_id(ServerPortionID serverID) const; const std::unordered_map& resource_list(); + ServerClientID get_resource_being_retrieved(); + float get_resource_retrieval_progress(); World& world; private: + ServerClientID resourceBeingRetrieved = {0, 0}; + std::unordered_map resources; std::unordered_map> displays; diff --git a/src/Server/CommandList.hpp b/src/Server/CommandList.hpp index c348223..069aafb 100644 --- a/src/Server/CommandList.hpp +++ b/src/Server/CommandList.hpp @@ -37,7 +37,8 @@ enum ClientCommands : MessageCommandType { CLIENT_ERASE_MANY_COMPONENTS, CLIENT_UPDATE_COMPONENT, CLIENT_MOVE_MOUSE, - CLIENT_NEW_RESOURCE, + CLIENT_NEW_RESOURCE_ID, + CLIENT_NEW_RESOURCE_DATA, CLIENT_CHAT_MESSAGE, CLIENT_NEW_BOOKMARK, CLIENT_REMOVE_BOOKMARK, diff --git a/src/Server/MainServer.cpp b/src/Server/MainServer.cpp index 245c289..59f3b94 100644 --- a/src/Server/MainServer.cpp +++ b/src/Server/MainServer.cpp @@ -63,8 +63,10 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): netServer->send_items_to_client(client, RELIABLE_COMMAND_CHANNEL, CLIENT_INITIAL_DATA, isDirectConnect, newClient.serverID, newClient.cursorColor); else { netServer->send_items_to_client(client, RELIABLE_COMMAND_CHANNEL, CLIENT_INITIAL_DATA, isDirectConnect, newClient.serverID, newClient.cursorColor, newClient.displayName, fileDisplayName, clients, data); - for(auto& [id, rData] : data.resources) - netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE, id, rData); + for(auto& [id, rData] : data.resources) { + netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, id); + netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, rData); + } } clients.emplace(newClient.serverID, newClient); }); @@ -190,7 +192,8 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): if(c.pendingResourceData.empty()) c.pendingResourceID.emplace(newID); else { - netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE, newID, c.pendingResourceData.front()); + netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, newID); + netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, c.pendingResourceData.front()); data.resources.emplace(newID, c.pendingResourceData.front()); c.pendingResourceData.pop(); } @@ -204,7 +207,8 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID): c.pendingResourceData.back() = std::move(resourceData); } else { - netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE, c.pendingResourceID.front(), resourceData); + netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, c.pendingResourceID.front()); + netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, resourceData); data.resources.emplace(c.pendingResourceID.front(), resourceData); c.pendingResourceID.pop(); }